默认情况下,nginx 的 error_log 不会记录 tls 握手失败详情,仅当日志级别设为 info 或 debug 时才输出如“ssl_do_handshake() failed”及具体错误码(如 no shared cipher、version too low)等关键信息,warn 及以下级别通常无法捕获。

当 Nginx 在 TLS 握手阶段失败(如客户端不支持服务端配置的协议版本、加密套件不匹配、证书问题、SNI 不匹配等),error_log 默认**不会记录详细握手错误**,除非日志级别设为 info 或更高(如 debug)。
握手失败是否写入 error_log?
默认情况下(error_log ... error; 或更高级别),Nginx 仅在连接建立后、处理 HTTP 请求时记录错误;而 TLS 握手发生在 TCP 连接建立之后、HTTP 解析之前,属于 SSL 模块的底层交互。若握手失败导致连接立即关闭(如 “SSL routines:ssl3_get_client_hello:wrong version number”),该错误**只出现在 info 及以上级别日志中**。
-
error级别:通常不记录握手细节,可能仅出现极简提示(如 “client closed connection”)或完全无声 -
warn级别:仍不足以捕获大多数 SSL 握手错误 -
info级别:开始记录关键 SSL 错误(如协议不兼容、证书加载失败、SNI 不匹配) -
debug级别:输出完整握手流程(含 ClientHello 内容、协商参数、错误堆栈),但日志量大,仅用于排障
如何让 error_log 记录握手失败详情
需显式提升 SSL 相关日志级别,并确保 OpenSSL 错误被正确传递:
- 在
http或server块中设置:error_log /path/to/error.log info; - 确认 Nginx 编译时启用了 OpenSSL(运行
nginx -V 2>&1 | grep -o "OpenSSL"验证) - 避免在
ssl_protocols中禁用客户端唯一支持的协议(如只留 TLSv1.3,但客户端只发 TLSv1.2 Hello) - 检查证书链完整性与私钥权限(私钥不可读会导致
SSL_CTX_use_PrivateKey_file() failed,info 级可捕获)
常见握手失败对应日志特征(info 级)
启用 info 后,典型错误示例如下:
-
SSL_do_handshake() failed (SSL: error:1417B07B:SSL routines:tls_process_cke_dhe:bad ecpoint)—— 椭圆曲线协商异常 -
no suitable signature algorithm—— 客户端不支持服务端要求的签名算法(如仅配 RSA-SHA256,但客户端只支持 ECDSA) -
SSL alert number 40(handshake_failure)或47(unknown_ca)—— 客户端证书验证失败或 CA 不可信 -
client sent no required certificate—— 配置了ssl_verify_client on但客户端未提供证书
补充建议:结合 tcpdump 和 openssl s_client 快速复现
仅靠日志有时难以定位根本原因,建议组合使用:
- 抓包分析:
tcpdump -i any port 443 -w handshake.pcap,用 Wireshark 查看 ClientHello 内容与 ServerHello 响应 - 模拟客户端:
openssl s_client -connect example.com:443 -tls1_2(指定协议)或-cipher 'ECDHE-RSA-AES128-GCM-SHA256'(指定套件) - 检查 Nginx 配置是否启用
ssl_prefer_server_ciphers on,该设置会影响套件协商优先级











