SSL握手超时主因是Nginx与后端TLS连接缺失SNI或proxy_ssl_verify启用后未配proxy_ssl_trusted_certificate,而非证书链不完整;需检查proxy_ssl_server_name、proxy_ssl_name及trusted_certificate路径是否正确。

后端服务 SSL 握手超时,如果日志里出现 SSL_do_handshake() failed、SSL_connect() failed 或 tlsv1 alert internal error,且直连后端域名(如 curl -v https://api.example.com)能通,那大概率不是证书链不完整导致的——而是 Nginx 与后端建立 TLS 连接时缺失 SNI,或未正确配置代理层证书验证逻辑。
先确认是不是真由“证书链不完整”引起
证书链不完整通常影响的是客户端验证服务端证书的过程,比如浏览器报 NET::ERR_CERT_AUTHORITY_INVALID,或 Python requests 报 CERTIFICATE_VERIFY_FAILED。但这类问题不会让 Nginx 和后端之间的握手“超时”,只会触发明确的证书校验失败错误(如 certificate verify failed)。
真正导致 Nginx 与后端握手卡住/超时的常见原因有:
- Nginx 没发 SNI,后端无法选择对应证书,直接中断握手(表现为无响应或秒级超时)
- 启用了
proxy_ssl_verify on,但没配proxy_ssl_trusted_certificate,Nginx 等待 CA 验证却找不到可信根,最终超时 - 后端 TLS 协议或密钥交换方式过于老旧(如仅支持 TLS 1.0 / RSA key exchange),而 Nginx 默认禁用弱协议
重点检查 proxy_ssl_server_name 和 SNI 配置
若后端是多域名共用 IP、CDN 回源、或使用泛域名证书的微服务,必须确保 Nginx 主动发送正确的 SNI:
-
proxy_ssl_server_name on;—— 开启 SNI 发送开关 -
proxy_pass https://api.example.com/;—— 域名必须写全,不能写 IP;否则 SNI 值取不到 -
proxy_set_header Host "api.example.com";—— Host 头需与 SNI 值严格一致,避免网关类中间件拒绝
如果用了 upstream 块,且 upstream 中只写了 IP 或未带端口的域名(如 server api.example.com;),Nginx 解析后会丢失主机名信息,此时必须显式指定:
-
proxy_ssl_name "api.example.com";—— 值为双引号包裹的字符串,大小写敏感,须匹配后端证书的 SAN 或 CN
proxy_ssl_verify 开启时务必配好 trusted_certificate
如果你在代理配置中启用了证书校验:
proxy_ssl_verify on;- 就必须同步设置:
proxy_ssl_trusted_certificate /etc/nginx/certs/ca-bundle.crt;
该文件必须是 PEM 格式,包含后端证书所依赖的根证书 + 所有中间证书(顺序不限)。不能是空文件,也不能是只含私钥或域名证书的错误文件。缺失或路径错误会导致 Nginx 在握手阶段阻塞等待验证,最终超时。
补充:别把 ssl_trusted_certificate 当作“补链工具”
ssl_trusted_certificate 是给 Nginx 自己用的,用于验证客户端证书(mTLS)或 OCSP 响应签名,它完全不参与 Nginx 向后端发起连接时的证书链构建。修复后端握手问题,和这个指令无关。真正决定 Nginx 发什么证书给后端的,是 proxy_ssl_certificate 和 proxy_ssl_certificate_key(仅在需要双向认证时才用)。


















