该错误本质是ssl/tls握手阶段连接被提前中断,需通过日志组合(如“ssl peer shut down incorrectly”、access log缺失)、抓包分析(clienthello后rst/fin)及openssl逐版本实测定位协商失败点,而非测量响应时间。

这个错误本身不直接暴露响应时间,但它明确指向客户端在 SSL/TLS 握手完成前就中断了连接——问题不在“慢”,而在“断”。定位瓶颈的关键,是把“谁在什么时候断的”还原出来,而不是测耗时。
看日志组合判断是否真属握手阶段中断
单靠这一行错误无法下结论,必须结合上下文交叉验证:
- 错误消息是否伴随 “Connection reset by peer” 或 “SSL peer shut down incorrectly”
- 对应请求在 access log 中是否完全缺失(说明没走到 HTTP 层)
- error log 时间戳与 upstream 日志或抓包时间是否高度同步(误差
- Nginx error log 中是否同时出现 “SSL_do_handshake() failed (SSL: syscall: Connection reset by peer)”
用 tcpdump 抓 TLS 握手头确认中断位置
真正能定位“在哪一步断”的只有网络层数据。重点过滤 TLS 握手起始标识:
- 运行:tcpdump -i any -nn port 443 -w handshake.pcap
- 复现问题后,用 Wireshark 打开,过滤:tcp[((tcp[12:1] & 0xf0) >> 2):4] == 0x160301(TLS Record Header)
- 观察 Client Hello 后,是否出现 Server Hello;若只看到 Client Hello → RST/FIN,说明服务端根本没响应或立即拒绝
- 若看到 Server Hello → 紧接着 RST/FIN(无 Certificate、ServerKeyExchange),说明服务端协商失败后主动终止
查客户端真实支持能力而非假设版本
很多“超时”实为兼容性失败导致的快速放弃。不要依赖文档,要实测:
- 从客户端所在机器执行:openssl s_client -connect target.com:443 -tls1_2 -servername target.com
- 依次替换 -tls1、-tls1_1、-tls1_2、-tls1_3,观察哪条返回 Verify return code: 0
- 若某版本命令卡住数秒后报 handshake failure 或直接退出,说明该协议被服务端禁用,客户端因无法协商而放弃
- 特别注意 JDK 应用:JDK 7u111 以下默认不支持 TLSv1.2;JDK 8u60 以前微服务常强制 -Dhttps.protocols=TLSv1
检查中间链路是否静默干扰握手
企业环境中,WAF、代理、LB 常在不报错的情况下改变握手行为:
- Nginx 反向代理场景:确认是否设置了 proxy_ssl_server_name on(尤其当上游是 SNI 多域名共 IP 时)
- 负载均衡器(如 F5、AWS ALB):检查其 ssl_protocols 和 ciphers 配置是否比客户端支持范围更窄
- 出口代理/SSL Inspection 设备:它会终止原始 TLS 并重建,若其自身不支持客户端所选套件,就会在二次握手时失败
- 移动网络或运营商设备:部分老旧网关会截断 TLSv1.3 或含扩展的 Client Hello











