排查Nginx SSL握手失败和证书加载错误,核心是先据日志关键词区分问题类型:含“SSL_do_handshake() failed”为TLS协商中断(如协议/套件不匹配、SNI缺失),含“cannot load certificate”“no start line”等为证书加载失败(如路径错、权限不足、链不全、私钥不匹配)。

排查 Nginx SSL 握手失败和证书加载错误,核心是分开处理两类问题:一类是 TLS 协商中断(如握手失败、协议不匹配),另一类是证书本身未正确加载或验证失败(如路径错、权限不足、格式异常)。两者日志表现不同,需针对性定位。
看日志关键词,先区分是握手失败还是证书加载失败
打开 /var/log/nginx/error.log,重点盯紧错误行前后的上下文:
- 出现 SSL_do_handshake() failed 或 ssl handshake failed → 属于 TLS 协商阶段问题,比如协议版本不兼容、密码套件无交集、SNI 缺失等
- 出现 cannot load certificate、no start line、PEM_read_bio_X509_AUX、SSL_CTX_use_PrivateKey_file 等字样 → 是证书或私钥文件加载失败,属于配置层或文件层错误
- 出现 SSL_CTX_use_certificate_chain_file 失败但没报路径错 → 往往是证书链缺失(中间 CA 没包含)或顺序颠倒(应为 server.crt + 中间证书,不能只放根证书)
证书加载失败的常见原因与验证方法
这类错误通常在 Nginx 启动或重载时就爆出,不依赖客户端请求。重点检查以下几项:
-
路径是否真实存在且可读:用
ls -l /path/to/cert.crt和ls -l /path/to/key.pem确认文件存在,且 Nginx 工作用户(如 www-data 或 nginx)有读取权限 -
文件格式是否为 PEM:执行
head -n 1 /path/to/cert.crt,应看到-----BEGIN CERTIFICATE-----;私钥应为-----BEGIN PRIVATE KEY-----或-----BEGIN RSA PRIVATE KEY-----。若开头是-----BEGIN CERTIFICATE REQUEST-----,说明误用了 CSR 文件 -
证书与私钥是否匹配:运行
openssl x509 -noout -modulus -in cert.crt | openssl md5和openssl rsa -noout -modulus -in key.pem | openssl md5,两个 md5 值必须完全一致 -
证书链是否完整:Nginx 要求
ssl_certificate包含服务器证书 + 所有中间证书(不含根证书)。可用openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout查看是否含多张证书
SSL 握手失败的日志线索与快速验证
这类错误多发生在请求到达时,需结合 OpenSSL 错误码判断根本原因:
-
error:14094410 (handshake failure) → 常见于客户端与服务端无共同 TLS 版本或密码套件。检查
ssl_protocols是否至少含 TLSv1.2,ssl_ciphers是否过度收紧(如禁用所有 CBC 套件,但老 Android/iOS 仍依赖它) -
error:1408F10B (wrong version number) → 大概率是协议错配:比如 Nginx 用
proxy_pass https://连一个实际只监听 HTTP 的后端;或客户端把 HTTP 请求发到了 HTTPS 端口 - tlsv1 alert unknown ca → 客户端不信任证书链中的某个 CA,多因中间证书缺失或自签名证书未被客户端预置信任
- 想确认实际协商结果?用命令直试:
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -showcerts,观察是否返回证书、是否有Verify return code: 0 (ok)
启用 debug 日志精准定位握手卡点
默认 error_log 级别太粗,抓不到关键细节。可在 server 或 http 块中临时加入:
error_log /var/log/nginx/ssl_debug.log debug;ssl_log_level debug;
重启后复现问题,ssl_debug.log 中会出现类似:SSL_do_handshake() failed (SSL: error:1417A0C1:SSL routines:tls_post_process_client_hello:no shared cipher)
这个 no shared cipher 就是明确提示:客户端通告的套件列表和服务端启用的套件完全无交集。











