代理中转链路出现SSL handshake

代理中转链路里的 SSL handshake failed 报错,最常见原因是中转服务与上游服务器支持的 TLS 版本不一致,比如服务端只开了 TLS 1.2,而客户端默认尝试 TLS 1.3,或者反向代理把低版本 TLS 拒掉了。
本文会带你从报错日志入手,逐步定位 TLS 版本兼容问题,并给出 Nginx、HAProxy 两种常见中转场景的调优配置和验证方法。
整个过程不需要很深的基础,照着执行即可。

先确认报错来自哪一段链路

中转链路通常分两段:客户端到中转服务器、中转服务器到上游。SSL handshake failed 可能发生在任一段。
建议先把日志级别调高,再分别测试。

以 Nginx 为例,检查错误日志:

tail -f /var/log/nginx/error.log

看到类似 SSL_do_handshake() failedtls_process_client_hello:no suitable signature algorithm 时,说明是客户端与 Nginx 之间握手失败。
如果日志里写的是 upstream SSL certificate verify failed,则问题出在 Nginx 与上游之间。

再用 OpenSSL 命令直接验证上游支持的 TLS 版本:

# 替换成你的上游域名和端口
openssl s_client -connect upstream.example.com:443 -tls1_2
openssl s_client -connect upstream.example.com:443 -tls1_3

如果某条命令报错或超时,说明该 TLS 版本没有被上游支持。
这是判断兼容范围最快的方式。

调整 TLS 版本策略,优先用现代版本

确认哪一段出问题后,调整对应服务端的 TLS 协议版本。
注意不要盲目关闭旧版本,先擦清客户端是什么系统、什么库发的请求。

Nginx 中在 server 块里配置:

server {
    listen 443 ssl;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;
}

如果客户端比较老,必须兼容 TLS 1.0/1.1,可以临时加上,但建议只在内部链路使用:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

HAProxy 中转场景则在 bind 行指定 TLS 版本范围:

frontend relay_in
    bind *:443 ssl crt /etc/haproxy/certs/relay.pem alpn h2,http/1.1
    ssl-default-bind-options no-sslv3
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384

修改配置后,务必先检测语法再重载服务:

nginx -t
systemctl reload nginx

haproxy -c -f /etc/haproxy/haproxy.cfg
systemctl reload haproxy

避开这几个容易踩的坑

调 TLS 版本时,很多人改了 ssl_protocols 却没重启服务,或者只改了中转服务器,忽略了上游服务也限制 TLS 版本。
还有几种情况特别容易误判:

  • 证书链不完整:上游返回的证书缺少中间证书,也会导致握手失败,但不一定是 TLS 版本问题。用 openssl s_client -showcerts 检查证书链。
  • SNI 缺失:某些中转配置没有转发 SNI,导致上游无法匹配证书。Nginx 里需要设置 proxy_ssl_server_name on;,HAProxy 里用 use-server 或确保 req.ssl_sni 生效。
  • OpenSSL 版本过老:系统自带的 OpenSSL 如果太旧,即使配置了 TLSv1.3 也不生效。运行 openssl version 确认支持情况。
  • 防火墙或安全组放行:中转服务器如果只放行了 80 端口,443 握手包被丢弃也会报同样的错。用 telnet 域名 443nc -vz 域名 443 测试连通性。

高频疑问快速排查

有读者问:为什么两边都开了 TLS 1.2,还是握手失败?
这种情况通常是密码套件不匹配。
服务端启用了 ssl_prefer_server_ciphers on,但客户端不认列表里的加密套件,就会握手失败。
可以用 openssl ciphers -v 'ECDHE-ECDSA-AES128-GCM-SHA256' 验证本地是否支持该套件。

也有人问:能不能直接关闭 TLS 1.0 和 1.1 来避免老版本漏洞?
可以。
如果业务客户端都是新版系统或浏览器,关闭 TLS 1.0/1.1 是安全基线要求。
判断方法很简单,观察日志里客户端所用的版本,或者用抓包工具确认。

还有一类情况是上游源站是 CDN,CDN 边缘节点 TLS 策略频繁调整。
此时建议把中转配置里的 TLS 版本范围放宽一点,先用 TLSv1.2 TLSv1.3 测试,再逐步收紧。

用真实请求验证调优结果

配置完成后,不要只看日志为空,直接用实际请求验证。

如果你用的是 curl,可以指定 TLS 版本测试:

curl -I --tlsv1.2 https://your-relay-domain.com
curl -I --tlsv1.3 https://your-relay-domain.com

两条命令都返回 HTTP/2 200 之类的状态码,说明对应 TLS 版本握手正常。

如果某个版本失败,再执行:

curl -v --tlsv1.2 https://your-relay-domain.com 2>&1 | grep -i error

同时关注 Nginx 错误日志是否还出现 SSL handshake failed
持续观察 5-10 分钟,确认没有新的报错后,再把它加入监控告警。

代理中转链路出现 SSL 握手失败并不可怕,多数原因是 TLS 版本或密码套件配置不一致。
按本文步骤先分段定位,再调整 ssl_protocolsssl_ciphers 和相关 SNI 参数,最后用 curl 验证,就能稳定解决。
如果你在处理过程中遇到其他异常,优先查看中转服务器与上游的完整握手日志,通常都能找到明确提示。

分享到:
上一篇
中转服务监控面板Prometheus+Grafana指标模板
下一篇
sub2api大规模部署,多实例负载均衡会话共享Redis方
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意