错误信息
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 缺失或未知
偶见只有在主机以名称形式给出或指定了 -servername 时,openssl s_client 才会发送 SNI;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)