最准的方式是直接在 nginx 服务器上运行 openssl s_client 模拟真实 tls 握手,统计证书块数量并验证签发关系:输出 1 表示仅域名证书、链不完整;输出 2 为标准完整链(域名证+中间证);≥4 或含根证书字样属错误配置;再用 openssl verify -cafile 验证链是否可回溯至系统可信根。

最准的方式是直接在 Nginx 服务器上运行 openssl s_client,模拟真实 TLS 握手过程,看它实际发给客户端的是什么——不依赖浏览器、不经过缓存,安卓、Python requests、Java 等严格校验场景收到的内容就是它。
快速统计证书块数量,判断链深度
执行命令:
openssl s_client -connect your-domain.com:443 -servername your-domain.com -showcerts 2>/dev/null | grep "-----BEGIN CERTIFICATE-----" | wc -l
输出数字即为当前下发的证书块总数:
- 1:只发了域名证书 → 缺失中间证书,链不完整
- 2:域名证书 + 一级中间证书(如 Let’s Encrypt R3)→ 常见完整链
- 3:域名证书 + 多级中间证书(如 E1 → R3)→ 深度为 3,需进一步确认顺序
- ≥4 或含 ISRG Root X1 / DigiCert Global Root 等字样:混入了根证书 → 错误配置(Nginx 不该下发根证书)
验证每张证书的签发关系是否连贯
加过滤查看关键字段:
openssl s_client -connect your-domain.com:443 -showcerts 2>/dev/null | grep "subject\|issuer" | head -n 6
正常应呈现清晰的上下级关系:
- 第一段 subject=CN=your-domain.com → 你的域名证书
- 第一段 issuer=CN=Let's Encrypt R3 → 它由 R3 签发
- 第二段 subject=CN=Let's Encrypt R3 → R3 证书本身
- 第二段 issuer=CN=ISRG Root X1 → R3 由根证书签发(但该根证书不应出现在响应中)
用系统信任库主动验证链是否可回溯
这条命令能暴露“链虽全但中间证失效或不被信任”的隐性问题:
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /path/to/fullchain.pem
返回 OK 表示整条链可回溯到系统可信根;若报 unable to get issuer certificate,说明:
- 中间证书缺失或顺序错
- 本地 fullchain.pem 文件内容与线上实际下发不一致(比如 reload 没生效、文件被覆盖)
- 系统 CA 包未更新(尤其老系统可能缺新中间 CA)
顺便检查证书文件本身是否干净
有时问题不在配置逻辑,而在 PEM 文件被污染:
-
file fullchain.pem→ 应显示 ASCII text;若提示 UTF-8 Unicode (with BOM) 或 CRLF line terminators,需清理 -
grep -n "^$" fullchain.pem→ 有输出说明存在空行,必须删除 -
openssl x509 -in fullchain.pem -noout -text 2>/dev/null→ 报错则表明含非法字符、私钥、注释或结构断裂











