TLS 报错怎么定位
TLS 报错几乎都发生在握手阶段,客户端与服务端各掌握一半信息:客户端提示比较笼统(handshake failure、certificate verify failed、unknown ca),服务端日志(nginx error.log、Java 的 SSLHandshakeException)更接近根因。正确顺序是先确定卡在握手的哪一步,再判断属于协议与套件不兼容、证书链不完整、有效期问题还是域名不匹配,最后只改一端做对照验证。
五类高频报错
| 报错 | 根因 | 处置 |
|---|---|---|
| handshake failure / protocol version | 两端协议版本或密码套件没有交集 | 放开服务端支持到 TLS 1.2 或升级客户端,用 -tls1_2 单独验证 |
| unable to get local issuer / unknown ca | 服务端没下发中间证书,或客户端信任库缺根 | 服务端配置 fullchain;内网自建 CA 要导入到客户端信任库 |
| certificate has expired / not yet valid | 证书超期,或校验方时钟偏差 | 及时续期并按叶证书在前的顺序部署,同时检查系统时间与 NTP |
| hostname mismatch | 证书 SAN 里没有访问用的是域名或 IP | 签发含正确 SAN 的证书,或改用证书里的名字访问 |
| self signed certificate | 自签证书不在信任链中 | 内网统一导入自建根,对公网使用受信 CA 证书 |
定位卡在哪一步
定位卡在哪一步
openssl s_client -connect bad.example.com:443 -servername bad.example.com -state </dev/null 2>&1 | tail -30 # 输出里的 >>> <<< 就是握手阶段,停在哪一步就查哪一步
openssl s_client -connect h:443 -servername h -showcerts -brief </dev/null 2>&1 | head -20 # 一次看协议版本、套件与证书链
curl -sv https://h/ 2>&1 | grep -iE 'ssl|tls|certificate|verify' | head # 客户端视角给出的原因
openssl s_client -connect h:443 -servername h -CAfile /etc/ssl/certs/ca-certificates.crt </dev/null 2>&1 | grep -i verify # 用系统信任库复核校验结果按现象选切入口
- 只有部分客户端报错:优先怀疑证书链不完整、SNI 配置,或双栈与多后端里有一条链路在用旧配置
- 全部客户端同时报错且刚改过服务端配置:先回滚再逐项放开协议与套件,不要在错误配置上继续叠加
- 毫秒级就失败:基本是握手被拒;几十秒才超时:更像网络拦截或后端无响应
- 服务端日志有握手失败而客户端无报错:多为反向代理到后端这一段的问题,例如 upstream 走 https 时的校验
- 浏览器报 ERR_CERT_* 而命令行正常:先对比两侧信任库,再确认企业代理是否替换了证书
TLS 1.2 及更早版本,抓包能看到 SNI 与证书明文;TLS 1.3 把证书放进加密的握手消息里,只会暴露 SNI。本地自测时可给客户端加 -keylogfile 导出密钥,再用抓包工具解密查看。
证书类错误在续期后仍然出现,要先确认负载均衡或 CDN 边缘是不是还挂着旧证书;多节点部署必须逐个节点核对。