证书链在 nginx 里怎么组织
nginx 的 ssl_certificate 指向的 PEM 文件应当包含「服务器证书在前、中间证书在后」的完整链,私钥单独放在另一个文件里。链顺序与文件权限是部署后最先要确认的两件事:顺序错了严格校验的客户端会拒绝,权限过宽则等于把私钥交给本机所有用户。
基本信息
| 文件组成 | 服务器证书加一个或多个中间证书,服务器证书必须在最前 |
|---|---|
| 替代写法 | nginx 1.11.0 起可用多条 ssl_certificate 指令按顺序指定链 |
| 私钥 | 单独文件,不放进链文件;权限 600,属主与运行用户一致 |
| 根证书 | 通常无需下发,客户端信任库已内置 |
| 校验链 | openssl verify -untrusted intermediate.crt fullchain.pem |
| 常见故障 | 只配叶证书、顺序颠倒、续期脚本覆盖了链文件 |
典型使用场景
- 证书上线:把证书商提供的多个文件正确拼接后配置
- 续期后检查:确认自动续期脚本同步更新了链文件
- 多域名部署:每个 server 块各自维护独立的全链文件
- 客户端差异排查:浏览器正常但 App 报错时优先检查链顺序
- 权限加固:固定证书目录权限与属主,避免私钥可被读取
拼接全链并验证
拼接全链并验证
# 叶证书在前,中间证书在后
cat server.crt intermediate.crt > fullchain.pem
# 离线校验:-untrusted 提供中间证书,根证书来自系统信任库
openssl verify -untrusted intermediate.crt fullchain.pem
# 查看链文件里各张证书的主体与签发者,确认顺序正确
openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout
# 设置私钥权限并确认属主
chmod 600 /etc/nginx/ssl/example.com.key
ls -l /etc/nginx/ssl/nginx 引用与验证
nginx 引用与验证
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# 校验配置语法后平滑重载,不要直接 restart 中断连接
# nginx -t && systemctl reload nginx确认线上实际下发的链
确认线上实际下发的链
# 数服务端下发的证书张数:通常为 2 张(叶 + 中间)
echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null | grep -c 'BEGIN CERTIFICATE'
# 查看叶证书的主体与签发者,确认与预期一致
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -issuer常见问题与处置
| 现象 | 原因 | 处置 |
|---|---|---|
| error 20 链不完整 | 只配置了叶证书 | 拼接中间证书后重载 |
| 部分客户端拒绝 | 链顺序颠倒 | 按叶证书在前的顺序重排 |
| 续期后突然故障 | 脚本只替换叶证书 | 检查续期流程是否同步维护链文件 |
| 证书与私钥不匹配 | 文件错配 | 先用 openssl 比对公钥再重载 |
| 私钥可被其他用户读取 | 权限或属主错误 | 设置为 600 并确认属主与运行用户一致 |
链顺序颠倒时,部分客户端仍能校验成功,但严格校验的实现(部分 Java 运行时、移动端库)会直接失败,属于隐蔽故障。部署后应至少用命令行与目标客户端各验证一次,不要只看浏览器。
证书与私钥不匹配时,nginx -t 只有在加载证书阶段才会报错,配置阶段可能看不出问题。可用 openssl 分别输出两者的公钥指纹做比对,快速定位是不是文件配错。