2026年4月28日のGitHub上のMicrosoftDocs系公式ドキュメント更新で確認すべき結論は、.NET 11以降、SslStreamがサーバーとしてクライアント証明書を検証するとき、欠落した中間証明書をAIA経由で自動ダウンロードする前提では運用できなくなる、という点です。影響を受けやすいのは、mTLS、独自TLSサーバー、社内CA・プライベートCA、IoT機器や取引先システムからクライアント証明書を受ける.NETアプリケーションです。
まず確認すべきことは3つです。AuthenticateAsServerまたはAuthenticateAsServerAsyncを使っているか、ClientCertificateRequired = trueにしているか、そしてクライアントが中間証明書を含む証明書チェーンをTLSハンドシェイクで送っているかです。.NET 11では、必要な中間証明書がクライアントから渡されず、サーバー側にも用意されていない場合、証明書検証エラーでハンドシェイクが失敗する可能性があります。Microsoft Learnの該当ページでも、この変更は.NET 11 Preview 3で導入され、影響APIとしてSslStream.AuthenticateAsServerとSslStream.AuthenticateAsServerAsyncが挙げられています。(Microsoft Learn)
GitHubの公式ドキュメント更新で何が変わったか
今回の更新は、GitHubというサービス自体のUIやAPI変更ではなく、GitHub上のdotnet/docsリポジトリで管理されているMicrosoft Learn向け公式ドキュメントの更新です。該当コミットでは、.NET 11の互換性情報にNetworkingセクションが追加され、「SslStream server-side AIA certificate downloads disabled by default」がbehavioral changeとして整理されています。あわせて、新しい互換性ページとSslStreamのベストプラクティス文書への注記も追加されています。(GitHub)
変更の核心は、サーバー側のSslStreamがクライアント証明書を検証する場面です。従来は、クライアントが中間証明書を送らなかった場合でも、サーバーが証明書のAIA、つまりAuthority Information Access拡張を使って不足している中間証明書の取得を試みることがありました。AIAには発行者証明書を取得できる場所が含まれるため、検証側が外部サーバーへアクセスしてチェーン構築を補完できる場合があります。(Microsoft Learn)
.NET 11以降は、サーバーがクライアント証明書を検証する際、既定ではこのAIA証明書ダウンロードを行いません。クライアントが必要な中間証明書をTLSハンドシェイクで送らず、サーバー側にも必要な中間証明書がない場合、ハンドシェイクは証明書検証エラーで失敗します。ただし、独自のCertificateChainPolicyを指定している場合は、そのX509ChainPolicy.DisableCertificateDownloadsの値が尊重されます。(Microsoft Learn)
| 確認項目 | 以前の挙動 | .NET 11以降の挙動 |
|---|---|---|
| クライアントが中間証明書を送らない場合 | サーバーがAIA経由で不足分の取得を試みることがあった | 既定ではAIAダウンロードを行わない |
| 失敗の出方 | 外部取得に成功すれば通る可能性があった | 必要な中間証明書がなければ検証エラーになり得る |
カスタムX509ChainPolicy | 指定内容に依存 | DisableCertificateDownloadsの値が尊重される |
| 変更種別 | 既定動作に依存した運用が可能だった | behavioral changeとして移行確認が必要 |
AIAダウンロード無効化の理由はパフォーマンスとセキュリティ
この変更は、単なる仕様整理ではありません。TLSハンドシェイク中にAIAサーバーへアクセスすると、AIAサーバーが遅い、応答しない、外部通信が遮断されている、といった要因でハンドシェイク全体が遅延します。また、クライアント証明書に含まれる情報をもとにサーバーが外部HTTPリクエストを送る構造は、攻撃者がサーバーの通信先に影響を与える余地を作ります。Microsoftの説明でも、性能劣化とセキュリティリスクが変更理由として示されています。(Microsoft Learn)
実務上は、「これまで動いていたから問題ない」ではなく、「偶然AIAで補完されていた不完全な証明書チェーンが、.NET 11で表面化する」と捉えるべきです。特に、クライアント証明書を配布する側とサーバーを運用する側が別組織の場合、どちらが中間証明書を持つべきかが曖昧なまま運用されていることがあります。
影響を受けやすいシステム
影響確認の優先度が高いのは、次のようなシステムです。
SslStreamで独自のTLSサーバーを実装しているAuthenticateAsServerまたはAuthenticateAsServerAsyncを使っているClientCertificateRequired = trueでクライアント証明書を必須にしている- 社内CA、プライベートCA、取引先CA、デバイス証明書を使っている
- クライアント側の証明書配布手順に「中間証明書を含める」確認がない
- コンテナ、Linuxサーバー、Windowsサーバーなど環境ごとに証明書ストアの内容が異なる
- .NET 11への移行、またはGitHub ActionsなどCI上で.NET 11のテスト追加を予定している
反対に、通常のGitHubリポジトリ操作、GitHub Actionsの一般的なワークフロー、GitHub APIの利用そのものが直接変更されるわけではありません。GitHub上で公開された公式ドキュメント更新をきっかけに、.NETアプリケーション側のTLS・証明書検証設計を確認する、という位置付けで理解すると混乱しにくくなります。
まずコードベースで確認するポイント
.NET 11移行の前に、GitHubのコード検索やローカル検索で対象コードを洗い出します。最初に見るべきキーワードは、SslStream、AuthenticateAsServer、AuthenticateAsServerAsync、ClientCertificateRequired、CertificateChainPolicyです。
PowerShellなら、次のように検索できます。
Select-String -Path .\**\*.cs -Pattern `
"SslStream", `
"AuthenticateAsServer", `
"AuthenticateAsServerAsync", `
"ClientCertificateRequired", `
"CertificateChainPolicy"
LinuxやGitHub Actions上のシェルなら、次のような検索でも十分です。
grep -R "AuthenticateAsServer" -n .
grep -R "ClientCertificateRequired" -n .
grep -R "CertificateChainPolicy" -n .
洗い出した後は、次の表で影響度を判断します。
| 確認項目 | 判断基準 | 次の対応 |
|---|---|---|
ClientCertificateRequired = trueか | trueなら影響確認の優先度が高い | クライアント証明書チェーンを確認 |
CertificateChainPolicyを指定しているか | 指定なしなら.NET 11の既定変更を受ける | 中間証明書の供給方法を決める |
DisableCertificateDownloadsを明示しているか | falseならAIA取得を許可している | 性能・セキュリティ上の理由を再確認 |
| クライアントが中間証明書を送るか | 送らない場合、.NET 11で失敗し得る | クライアント設定を修正 |
| サーバー側に中間CAがあるか | 環境差があると本番だけ失敗し得る | 証明書ストアまたはExtraStoreで管理 |
X509ChainPolicy.DisableCertificateDownloadsは、AIA拡張を使って不明な発行者証明書を探すかどうかを制御するプロパティです。Microsoft LearnのAPIリファレンスでは、trueならAIA拡張の利用を無効化し、既定値はfalseと説明されています。つまり、カスタムX509ChainPolicyを使う場合は、.NET 11の内部既定に任せるのではなく、自分たちの意図として値を明示することが重要です。(Microsoft Learn)
推奨対応は「クライアントがフルチェーンを送る」こと
最も自然な対応は、クライアントがTLSハンドシェイクで必要な中間証明書をすべて送ることです。TLSの相手側に「足りない証明書はそちらで取りに行ってください」と任せるのではなく、クライアント証明書と中間証明書を含むチェーンを正しく構成します。
Microsoftの推奨アクションでも、クライアント側ではSslClientAuthenticationOptions.ClientCertificateContextと、フルチェーンを含むSslStreamCertificateContextの利用が示されています。SslStreamCertificateContext.Createは、渡された証明書から証明書チェーンの構築を試みるAPIで、追加証明書を指定できます。(Microsoft Learn)
概念的には、次のような実装です。
var clientCertificateContext = SslStreamCertificateContext.Create(
clientCertificate,
new X509Certificate2Collection
{
intermediateCertificate
},
offline: true);
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
{
TargetHost = targetHost,
ClientCertificateContext = clientCertificateContext
});
ここで大切なのは、証明書ファイルを単に読み込むことではなく、「相手が検証に必要な中間証明書まで渡せているか」をテストで確認することです。社内CAやデバイス証明書では、リーフ証明書だけを配布し、中間証明書の同梱が漏れているケースがあります。
サーバー側で中間証明書を用意する方法
クライアント側をすぐに修正できない場合や、複数のクライアント証明書発行元を受け入れる場合は、サーバー側のチェーンポリシーで必要な中間証明書を補う方法もあります。Microsoftの推奨アクションでは、X509ChainPolicy.ExtraStoreに必要な中間証明書を追加する例が示されています。プライベートルートCAを使う場合は、CustomRootTrustとCustomTrustStoreの利用も検討対象になります。(Microsoft Learn)
var chainPolicy = new X509ChainPolicy
{
DisableCertificateDownloads = true,
ExtraStore =
{
intermediateCertificate
},
TrustMode = X509ChainTrustMode.CustomRootTrust,
CustomTrustStore =
{
rootCertificate
}
};
await sslStream.AuthenticateAsServerAsync(new SslServerAuthenticationOptions
{
ServerCertificateContext = serverCertificateContext,
ClientCertificateRequired = true,
CertificateChainPolicy = chainPolicy
});
CertificateChainPolicyを指定すると、SslServerAuthenticationOptionsの一部プロパティよりも、指定したX509ChainPolicy側の設定が優先されます。たとえば、CertificateRevocationCheckModeはX509ChainPolicy.RevocationModeに置き換わるため、カスタムポリシーを導入するときは失効確認の方針も同時に見直す必要があります。(Microsoft Learn)
AIAダウンロードを再有効化すべきか
公式ドキュメントでは、DisableCertificateDownloadsをfalseにして以前の挙動へ戻す方法も示されていますが、性能とセキュリティのリスクがあるため推奨されていません。運用上の恒久対応としては、クライアントにフルチェーンを送らせるか、サーバー側で必要な中間証明書を明示的に持つ方が安全です。(Microsoft Learn)
dotnet/runtimeの関連PRでは、互換スイッチSystem.Net.Security.EnableServerAIADownloadsと環境変数DOTNET_SYSTEM_NET_SECURITY_ENABLESERVERAIADOWNLOADSによるオプトバックも説明されています。ただし、これは切り分けや一時的な互換確認に使う候補であり、本番運用で安易に既定化する対応ではありません。(GitHub)
判断基準は明確です。外部AIAサーバーへアクセスしない設計に直せるなら、直すべきです。どうしても一時的にAIAダウンロードを許可する場合は、対象システム、期間、通信先監視、ロールバック条件を決め、GitHubのIssueやPull Requestで理由を残してください。
テストで確認すべきシナリオ
移行テストでは、「正常系で通るか」だけでなく、「中間証明書が欠落したときにどう失敗するか」を確認します。これにより、.NET 11で偶然露出する問題なのか、証明書配布そのものの不備なのかを切り分けやすくなります。
| テストシナリオ | 期待結果 | 確認できること |
|---|---|---|
| クライアントがリーフ証明書だけを送る | .NET 11で検証エラーになり得る | 既定のAIAダウンロードに依存していないか |
| クライアントが中間証明書を含めて送る | ハンドシェイクが成功する | クライアント側のチェーン構成が正しいか |
サーバーのExtraStoreに中間証明書を入れる | ハンドシェイクが成功する | サーバー側補完で運用可能か |
DisableCertificateDownloads = falseにする | 以前の挙動に近づく可能性がある | 問題原因がAIA依存か |
| 失効確認を有効にする | CRL/OCSPの通信要件を確認する | AIA問題と失効確認問題を混同していないか |
注意したいのは、AIAによる中間証明書ダウンロードと、CRLやOCSPによる失効確認は別の論点だという点です。AIAダウンロードを無効にしても、失効確認の設定によっては外部通信が必要になることがあります。CertificateChainPolicyを導入する場合は、RevocationModeやネットワーク到達性もあわせて確認してください。
GitHubで移行準備を進める実務フロー
GitHub上でプロジェクトを管理している場合は、次の流れで進めると抜け漏れを減らせます。
| ステップ | GitHub上での作業 | 成果物 |
|---|---|---|
| 影響調査 | コード検索でSslStream関連箇所を抽出 | 対象ファイル一覧 |
| 方針決定 | Issueでクライアント側対応かサーバー側対応かを決める | 移行方針メモ |
| 実装修正 | Pull RequestでClientCertificateContextまたはCertificateChainPolicyを追加 | レビュー可能な差分 |
| テスト追加 | 中間証明書あり・なしのケースをCIに追加 | 再発防止テスト |
| 運用反映 | 証明書配布手順やRunbookを更新 | 運用ドキュメント |
| 本番確認 | ログ、メトリクス、TLS失敗率を確認 | 移行完了判断 |
特にPull Requestでは、「なぜDisableCertificateDownloads = trueを明示するのか」「なぜExtraStoreにこの中間証明書を入れるのか」をコメントや設計メモに残すと、将来の保守担当者が意図を理解しやすくなります。
よくある失敗パターン
この変更で失敗しやすいのは、コード修正よりも証明書運用の曖昧さです。次の対応は避けてください。
- 原因を確認せず、全環境でAIAダウンロードを再有効化する
- クライアント証明書検証そのものを弱める
- 開発環境の証明書ストアだけを直して、本番環境の設定を更新しない
- 中間証明書を手作業で配置し、IaCやRunbookに反映しない
- 失効確認の通信失敗を、AIAダウンロード無効化の問題と混同する
- 取引先やデバイス側に「中間証明書を送る」要件を伝えない
特にコンテナ環境では、ホストOSの証明書ストアとコンテナ内の証明書ストアが一致しないことがあります。ステージングでは成功し、本番コンテナでは失敗する、といった差分を避けるため、証明書の配置はイメージ、起動時マウント、シークレット管理、構成管理のどれで行うのかを明確にしてください。
技術判断者が確認すべき運用影響
開発者だけでなく、クラウド管理者、ソリューションアーキテクト、技術意思決定者は、次の観点で影響を整理しておくべきです。
| 観点 | 確認内容 |
|---|---|
| 対象範囲 | .NET 11へ移行するサービスのうち、mTLSやクライアント証明書を使うもの |
| 外部依存 | AIA、CRL、OCSPなど外部証明書関連エンドポイントへの依存 |
| 証明書配布 | クライアントに中間証明書を含める手順があるか |
| サーバー構成 | 中間CA、プライベートルートCA、信頼ストアをどこで管理するか |
| 障害時対応 | 証明書検証エラー発生時のログ、切り分け手順、連絡先 |
| セキュリティ | 外部HTTPリクエストを発生させない設計にできているか |
この変更は、ビルド時にすぐ分かるコンパイルエラーではなく、TLSハンドシェイク時に表面化する挙動変更です。そのため、.NET 11対応のスケジュールには、単体テストだけでなく、実際の証明書チェーンを使った結合テストを含める必要があります。
次に取るべき行動
最初にやるべきことは、SslStreamをサーバー側で使い、クライアント証明書を要求している箇所の洗い出しです。次に、クライアントが中間証明書を含むフルチェーンを送っているか、サーバー側に必要な中間証明書を明示的に用意しているかを確認します。
方針としては、クライアントにフルチェーンを送らせることを第一候補にし、必要に応じてサーバー側のX509ChainPolicy.ExtraStoreで中間証明書を補います。AIAダウンロードの再有効化は、原因切り分けや短期的な互換対応に限定し、恒久対策にはしないのが安全です。
GitHubで管理しているプロジェクトなら、今回の公式ドキュメント更新をきっかけに、Issueで影響調査、Pull Requestで修正、CIで証明書チェーンテスト、Runbookで運用手順更新まで進めてください。.NET 11移行時に「一部のクライアントだけ突然接続できない」という障害を防ぐには、証明書チェーンを暗黙の外部取得に頼らず、送る側・検証する側の責任を明確にすることが最も重要です。

コメント