TLS handshake failure 常见原因有哪些?线上 HTTPS 握手失败怎么排查?
简化版
TLS handshake failure 表示 TLS 握手没有成功建立安全连接。
常见原因包括协议版本不兼容、密码套件不匹配、证书过期或域名不匹配、SNI 缺失、客户端不信任 CA、mTLS 客户端证书错误、ALPN 协商失败、系统时间错误等。
排查要从客户端报错、服务端日志、证书链、TLS 版本、SNI、抓包和 openssl s_client 逐层定位。
详细版
常用排查命令:
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts
可以看到证书链、协商协议、密码套件、验证错误。
如果是老客户端访问新服务,可能只支持 TLS 1.0,而服务端只允许 TLS 1.2+。
如果是多域名 HTTPS,缺少 SNI 可能导致服务端返回默认错误证书。
如果启用了 mTLS,客户端没有提供证书或证书不被服务端信任,也会握手失败。
排查要先判断失败发生在 TCP 连接、TLS 握手,还是 HTTP 请求阶段。
完整版教学
1. 先定位失败发生在哪一层
用户说 HTTPS 访问失败,可能并不都是 TLS 问题。
要先分层:
DNS 解析 -> TCP 连接 -> TLS 握手 -> HTTP 请求 -> 应用响应
handshake failure 通常发生在 TLS 握手阶段。
但如果 TCP 都连不上,就不是 TLS 握手失败。
排查 HTTPS 问题第一步不是猜证书,而是确认卡在哪一层。
2. 常见原因总览
| 类别 | 典型原因 | 表现 |
|---|---|---|
| 协议版本 | 客户端只支持 TLS 1.0 | 服务端拒绝 |
| 密码套件 | 双方没有共同套件 | handshake failure |
| 证书链 | 缺中间证书或 CA 不可信 | verify error |
| 域名 | SNI 或 SAN 不匹配 | 证书错误 |
| mTLS | 客户端证书缺失 | 服务端拒绝 |
| 时间 | 客户端系统时间错误 | 证书未生效或过期 |
| ALPN | 协议协商异常 | HTTP/2 连接失败 |
这个表可以作为面试回答骨架。
3. 用 openssl 看证书和握手
常用命令:
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts
关注输出里的:
Verify return code- 证书链是否完整。
Protocol协议版本。Cipher密码套件。- 证书 Subject 和 SAN。
- 是否有 ALPN 协商结果。
如果不加 -servername,对启用 SNI 的站点可能拿到默认站点证书。
4. 协议版本和密码套件问题
老系统可能只支持旧协议。
例如客户端只支持 TLS 1.0,服务端出于安全要求只开启 TLS 1.2 和 TLS 1.3。
这时双方没有共同协议版本。
密码套件也类似。
如果服务端只允许现代 AEAD 套件,而客户端只支持旧 CBC 或 3DES,也会协商失败。
这类问题常见于老 Java、老 Android、老 OpenSSL。
5. 证书链和域名问题
证书链问题很常见。
服务端可能只配置了站点证书,漏掉中间 CA。
浏览器有时能自动补链,但某些客户端库不能。
域名问题包括:
- 访问域名不在 SAN 中。
- 通配符层级不匹配。
- CDN 回源 Host 和源站证书不一致。
- SNI 缺失导致返回默认证书。
证书错误不一定在所有客户端上表现一致,所以要看具体客户端环境。
6. mTLS 和客户端证书问题
如果服务端启用双向 TLS,客户端也要提供证书。
失败原因可能是:
- 客户端没有证书。
- 客户端证书过期。
- 客户端证书链不被服务端信任。
- 证书用途不对。
- 服务端 CRL 或 OCSP 校验失败。
这类问题通常在企业内网、网关回源、服务间调用里出现。
7. 常见误区与追问
- 误区:handshake failure 一定是证书过期。 协议版本、密码套件、SNI、mTLS 都可能导致。
- 误区:浏览器能访问就说明所有客户端都能访问。 不同客户端的根证书、TLS 版本和补链能力不同。
- 误区:TCP 443 通了就说明 HTTPS 没问题。 TCP 连接成功后,TLS 握手仍可能失败。
- 追问:为什么 openssl 要加 servername? 它会发送 SNI,让服务端返回对应域名证书。
- 追问:老客户端访问失败怎么办? 评估是否放宽 TLS 配置、升级客户端,或提供兼容入口。
- 追问:缺中间证书为什么有些浏览器不报错? 浏览器可能缓存或自动获取中间证书,其他客户端未必能。
8. 加强记忆
HTTPS 握手失败排查记成一条栈:DNS、TCP、TLS、HTTP、应用。
TLS 内部再看版本、套件、证书、SNI、mTLS。