2つのバックエンドサーバー間でHTTP通信を使用するプロジェクトに取り組んでいます。サーバーは認証にX509証明書を使用しています。言うまでもなく、サーバーA(クライアント)がサーバーB(サーバー)への接続を確立すると、使用される証明書は信頼できる第三者機関からのものではないため、SSL/TLS検証エラーが発生します。
通常、それを処理する方法は、次のようなServicePointManager.ServerCertificateValidationCallback
を使用することです。
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, error) =>
{
return cert.GetCertHashString() == "xxxxxxxxxxxxxxxx";
};
理想的ではないことを除いて、このアプローチは機能します。基本的には、アプリケーションによって実行されるすべてのhttp要求の検証手順をオーバーライドします。そのため、別のクラスがHTTP要求を実行しようとすると、失敗します。また、別のクラスがServicePointManager.ServerCertificateValidationCallback
を独自の目的でオーバーライドすると、突然通信が失敗し始めます。
頭に浮かぶ唯一の解決策は、個別の AppDomain を作成して、クライアントHTTP要求を実行することです。それは機能しますが、実際には、HTTPリクエストを実行できるようにするためだけにそれを行うのはばかげています。オーバーヘッドは驚異的です。
それを念頭に置いて、他のWebクライアントに影響を与えずにクライアントのSSL/TLS検証を処理しながら、Webサービスにアクセスできる.NETでより良いプラクティスがあるかどうかを誰かが調査しましたか?
.NET 4.5+で動作する許容可能な(安全な)方法論は、HttpWebRequest.ServerCertificateValidationCallback
。リクエストの特定のインスタンスにそのコールバックを割り当てると、他のリクエストに影響を与えることなく、リクエストの検証ロジックのみが変更されます。
var request = (HttpWebRequest)WebRequest.Create("https://...");
request.ServerCertificateValidationCallback +=
(sender, cert, chain, error) =>
{
return cert.GetCertHashString() == "xxxxxxxxxxxxxxxx";
};
HttpWebRequestを使用しないコード、および証明書ストアに信頼できる証明書をインストールできない環境の代替手段:コールバックのエラーパラメーターを確認します。これには、コールバックの前に検出されたエラーが含まれます。この方法では、特定のハッシュ文字列のエラーを無視できますが、検証に合格した他の証明書を受け入れます。
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, error) =>
{
if (cert.GetCertHashString() == "xxxxxxxxxxxxxxxx")
{
return true;
}
else
{
return error == SslPolicyErrors.None;
}
};
これは、同じappdomain内の他のWebクライアントインスタンスにも影響しますが(指定されたハッシュ文字列はすべて受け入れます)、少なくとも他の証明書はブロックしません。
このシナリオの簡単なアプローチは、クライアントマシンの信頼されたルートストアに2つの自己生成証明書をインストールすることです。これを行うとセキュリティ警告が表示されます。これは、Thawteなどで証明書を認証できないため、その後は通常の安全な通信が機能するはずだからです。 IIRCでは、これを機能させるために、信頼されたルートにフルバージョン(公開キーと秘密キーの両方)をインストールする必要があります。