エラーメッセージ
SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
別の表記
- Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
前後の例外チェーンは「The SSL connection could not be established」→「Authentication failed, see inner exception.」→ このメッセージ → OpenSSL の理由(たとえば OpenSSL 3.0 では「error:0A000410:SSL routines::sslv3 alert handshake failure」、3.3 以降では「ssl/tls alert handshake failure」)の順に続きます。Windows(Schannel)と macOS(Apple の TLS スタック)では、.NET はこうした失敗をプラットフォーム固有のメッセージで報告します。
.NET on Linux (SslStream over OpenSSL) — inner exception carrying the OpenSSL reason
このエラーの意味
Linux では .NET の SslStream はシステムの OpenSSL 上で動作し、ハンドシェイクは OpenSSL の内部で SSL_ERROR_SSL により失敗しました。この行は外側のラッパーにすぎず、次の内部例外(Interop+Crypto+OpenSslCryptographicException)に、サーバーからのアラートや拒否されたプロトコルバージョンなど、OpenSSL が示す実際の理由が含まれています。
発生する理由
共通の暗号スイートまたはプロトコルバージョンがない
よくあるRSA 鍵交換、3DES、TLS 1.0/1.1 にしか対応していない古いサーバーが該当します。OpenSSL の理由には、サーバーが送信したアラートが示されます。
サーバーがクライアント証明書を要求した
ときどき相互 TLS を使う TLS 1.2 のサーバーは、証明書が提示されないと handshake_failure アラートで応答します。
システムの OpenSSL ポリシーが、サーバーに必要なものを禁止している
ときどきディストリビューションの既定値(セキュリティレベル 2、最低 TLS 1.2)は Linux 上の .NET にも適用されます。同じアプリが Windows では動作し、Linux コンテナーでは失敗することがあります。
修正方法
- 1.
最も内側の例外にある OpenSSL の理由を読む
error:0A… で始まるエラーコードとそのテキストで問題を特定できます。例のように原因と対応付けてください。
text Interop+Crypto+OpenSslCryptographicException: error:0A000410:SSL routines::sslv3 alert handshake failure -> the server rejected the offered suites/versions (or wants a client certificate) error:0A00042E:SSL routines::tlsv1 alert protocol version -> the server only speaks TLS 1.0/1.1 error:0A00018A:SSL routines::dh key too small -> the server uses 1024-bit DH - 2.
サーバーとクライアントの対応状況を比較する
サーバーの暗号スイートと、ローカルの OpenSSL の既定値を列挙してください。
bash nmap --script ssl-enum-ciphers -p 443 legacy.example.com # what the server offers openssl ciphers -v 'DEFAULT' | head # what this system's OpenSSL offers - 3.
クライアントのポリシーではなくサーバーを直す
サーバーの TLS 設定を最新化してください。クライアントの OpenSSL ポリシーを緩めるのは、範囲を限った一時的な例外としてのみにしてください。
text Server side: enable TLS 1.2/1.3 with ECDHE + AES-GCM (or ChaCha20) suites. Lowering the system-wide OpenSSL policy (CipherString=DEFAULT@SECLEVEL=1 in openssl.cnf) affects every application on the host and should only be a short-lived exception for an isolated legacy peer.