Nginx的ssl_certificate文件须按“域名证书→中间证书(逐级向上)”顺序拼接,不含根证书;段数需匹配grep结果,OpenSSL测试应显示多行subject,且SSL Labs链检测须标绿。

核心就一点:Nginx 的 ssl_certificate 文件必须包含从你的域名证书开始、逐级向上直到最靠近根证书的全部中间证书,顺序不能颠倒,且绝对不包含根证书。
多级证书链的正确拼接顺序
当 CA 提供了不止一级中间证书(例如:Root → Intermediate A → Intermediate B → 你的域名证书),你需要按“信任路径反向”拼接,也就是从你的证书出发,一路向上追加中间证书:
- 第一段:你的域名证书(
example.com.crt) - 第二段:直接签发你证书的中间 CA(如
Intermediate B.crt) - 第三段:签发 Intermediate B 的上一级中间 CA(如
Intermediate A.crt) - ……依此类推,直到最后一级中间证书(最接近根证书的那个)
- 不包含根证书(Root CA)——它已预装在客户端,Nginx 发送反而可能引发兼容问题
验证拼接是否成功
执行命令检查文件内容是否符合要求:
grep -c "BEGIN CERTIFICATE" fullchain.pem
返回值应等于你拼入的证书段数(至少为 2)。再用 OpenSSL 实测握手时是否真能发出完整链:
openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null | grep "subject="
输出中应清晰看到多行:
• 一行含 CN=example.com
• 后续几行分别对应各中间 CA 的名称(如 CN=Let's Encrypt R3、CN=ISRG Root X1 等)
配置中必须避开的坑
常见错误不是技术不会,而是配置逻辑混淆:
-
ssl_certificate_key 仍指向原始私钥文件(如
privkey.pem),和证书链无关,别动它 - ssl_trusted_certificate 对修复浏览器/安卓报错完全无效——它只用于 Nginx 自身验证(如 OCSP stapling 或双向 TLS),不参与发送给客户端的证书链
- 宝塔等面板的“自动补全”对多级链支持不稳定,务必手动检查
fullchain.pem内容,不能只信界面提示 - 两段证书之间不能有空行,不能混入私钥或注释,每段必须严格以
-----BEGIN CERTIFICATE-----开头、-----END CERTIFICATE-----结尾
线上验证与清缓存建议
改完重载 Nginx(nginx -t && systemctl reload nginx)后,别只信 Chrome 显示正常:
- 用 SSL Labs 测试,重点看 “Certificate Chain” 是否标绿、无 “Incomplete” 提示
- 安卓用户需清除 Chrome 的 HSTS 缓存(访问
chrome://net-internals/#hsts删除域名记录),再用无痕模式重试 - curl 或 Python requests 报
CERTIFICATE_VERIFY_FAILED时,大概率就是链缺失,而非服务端其他问题











