需启用nginx debug级ssl日志(error_log ... debug)并确认--with-debug已编译支持,结合ssl_protocols、ssl_ciphers等配置,才能捕获tls版本不匹配、证书验证失败、sni缺失、alpn协商异常等底层握手错误。

Nginx 本身不直接记录 TLS 握手失败的详细原因(比如证书过期、协议不匹配、SNI 不支持、ALPN 协商失败等),因为握手发生在 OpenSSL 层,在连接被 Nginx 的 HTTP 模块处理前就可能已中断。但可以通过组合配置和外部工具,**间接捕获并定位 HTTPS 握手失败原因**。
启用 OpenSSL 错误日志(关键第一步)
Nginx 编译时若链接的是系统 OpenSSL 或启用了 --with-openssl,可通过设置 OpenSSL 日志级别,让其将握手错误输出到 Nginx error log:
- 在
nginx.conf的http或stream块中添加:
ssl_log_level warn;
(Nginx 1.19.4+ 支持;低于此版本需依赖 OpenSSL 环境变量或调试编译) - 确保
error_log级别至少为warn:
error_log /var/log/nginx/error.log warn; - 重启 Nginx 后,常见握手失败(如客户端发送不支持的 TLS 版本、无效 ClientHello、SNI 域名为空)会以
SSL_do_handshake() failed或类似提示出现在 error log,并附带 OpenSSL 错误码(如SSL_ERROR_SSL)和简要原因。
使用 stream 模块 + 自定义日志(捕获连接级异常)
对于更底层的失败(如 TCP 连接建立后立即断开、ClientHello 格式错误、无响应等),HTTP 日志完全不可见。此时应启用 stream 模块,把 TLS 流量当作原始 TCP 处理:
- 在
nginx.conf顶层启用 stream:
stream { include /etc/nginx/stream.d/*.conf; } - 新建
/etc/nginx/stream.d/https-fail-log.conf:
upstream backend_https { server 127.0.0.1:8443; }
server {
listen 443;
proxy_pass backend_https;
proxy_timeout 5s;
log_format tls_fail '$remote_addr [$time_local] $protocol $status $bytes_sent $connection $session_time';
access_log /var/log/nginx/tls_handshake.log tls_fail;
error_log /var/log/nginx/tls_error.log debug;
} - 该配置不会终止 TLS,但可记录连接是否成功转发、耗时、是否超时 —— 超时或状态码为
502/504往往对应握手卡死或后端未响应。
配合 tcpdump + OpenSSL s_client 做主动诊断
当线上偶发握手失败且日志信息不足时,需抓包分析:
- 在 Nginx 服务器上运行:
tcpdump -i any -w tls-fail.pcap port 443 and host [client_ip] - 用 OpenSSL 解析握手过程:
openssl s_client -connect yourdomain.com:443 -tls1_2 -servername yourdomain.com -debug &1 | grep -E "(SSL|error|Cipher)" - 对比成功/失败客户端的 ClientHello 差异(如 TLS 版本、扩展列表、SNI 内容),快速定位是客户端能力问题还是服务端配置限制(如禁用了 TLS 1.0、未配置 SNI 主机等)。
检查常见配置陷阱(预防性排查)
很多“握手失败”实际源于配置错误,而非网络或证书问题:
-
证书链不全:Nginx 只配了域名证书,没包含中间 CA,部分客户端(尤其 Java、旧 Android)会拒绝握手;用
curl -v https://yoursite或 SSL Labs 测试 验证。 -
ssl_protocols 和 ssl_ciphers 过于严格:例如只允许
TLSv1.3,但客户端仅支持 TLS 1.2;建议保留TLSv1.2 TLSv1.3并使用 Mozilla 推荐的 cipher list。 -
多个 server 块共用同一 IP:443 但缺少 SNI 支持:确认所有
server_name均有对应ssl_certificate,且 Nginx 版本 ≥ 1.11.0(SNI 支持稳定)。











