エラーメッセージ
SSL routines:ssl3_read_bytes:ssl/tls alert handshake failure
別の表記
- SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
- SSL alert number 40
OpenSSL 3.3 以降は「ssl/tls alert handshake failure」、それより前のバージョンは「sslv3 alert handshake failure」と出力します(コードはどちらも 0A000410。1.1.1 では 14094410)。行の末尾には、出力元のソースコードの位置と「SSL alert number 40」が付きます。
OpenSSL (client side) — TLS alert 40 (handshake_failure) received from the server
このエラーの意味
サーバーが TLS アラート 40(handshake_failure)を送信して接続を閉じました。これは汎用的な拒否で、ClientHello に受け入れ可能な暗号スイート、鍵交換グループ、署名アルゴリズムのいずれかが含まれていなかった場合、サーバーがクライアント証明書を要求した場合、要求されたサーバー名をサーバーが拒否した場合に送られます。クライアントはアラートから理由を知ることができません。理由はサーバーのログに記録されています。
発生する理由
共通の暗号スイートがない
よくあるRSA 鍵交換、3DES、RC4 のいずれかを使う暗号スイートしか使えない古いサーバーや、古いクライアントが持っていない少数の暗号スイートしか許可しない厳格なサーバーが該当します。
クライアント証明書が要求されている(TLS 1.2)
よくあるTLS 1.2 では、多くのサーバーが、クライアント証明書がない場合や受け入れられない場合に handshake_failure で応答します。TLS 1.3 のサーバーは、代わりに certificate_required(アラート 116)を使います。
SNI がない、または不明な名前が指定されている
ときどきopenssl s_client が SNI を送信するのは、ホストが名前で指定されている場合か、-servername が指定されている場合だけです。CDN やマルチテナントのプロキシは、既知の名前を含まないハンドシェイクを中止します。
共通の鍵交換グループまたは署名アルゴリズムがない
まれ単一の鍵交換グループ(たとえばポスト量子ハイブリッド)や RSA-PSS 署名だけに制限されたサーバーは、そのどちらも提示しないクライアントとの接続に失敗することがあります。
修正方法
- 1.
サーバーのログを確認する
サーバーは実際の理由(たとえば「no shared cipher」や「peer did not return a certificate」)を記録しています。
bash # The server knows why; with openssl s_server or nginx the log says e.g. # ...:tls_post_process_client_hello:no shared cipher # ...:tls_process_client_certificate:peer did not return a certificate sudo tail -n 50 /var/log/nginx/error.log | grep -i ssl - 2.
クライアント側から原因を絞り込む
SNI、プロトコルバージョン、暗号リスト、クライアント証明書の有無を変えて試してください。成功した組み合わせから、何が欠けているかがわかります。
bash h=api.example.com echo | openssl s_client -connect $h:443 -servername $h -brief # with SNI echo | openssl s_client -connect $h:443 -servername $h -tls1_2 -cipher 'ALL:@SECLEVEL=0' -brief echo | openssl s_client -connect $h:443 -servername $h -cert client.pem -key client.key -brief # mTLS - 3.
サーバー管理者:現行の暗号スイートを提供する
TLS 1.3 に加えて、ECDHE と AEAD の暗号スイートを使う TLS 1.2 を提供すれば、保守されているすべてのクライアントで動作します。
text # nginx: modern suites for TLS 1.2 plus TLS 1.3 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
関連するエラー
SSL routines:tls_post_process_client_hello:no shared cipherOpenSSL (server side: nginx, Apache, Postfix, openssl s_server)SSL routines:tls_process_client_certificate:peer did not return a certificateOpenSSL (server side, mutual TLS)curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handsh…curl (OpenSSL backend)[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] ssl/tls alert handshake failurePython ssl module (OpenSSL)