关键是要用含完整信任链的PEM文件(仅CA证书,按链顺序拼接)配合proxy_ssl_verify on、proxy_ssl_verify_depth和proxy_ssl_name三项启用验证,缺一不可。

要让 Nginx 在反向代理 HTTPS 后端时信任自签名证书,关键不是只写对 proxy_ssl_trusted_certificate,而是让它指向一个**含完整信任链的 PEM 文件**——这个文件必须把你的自签根证书(或中间 CA)明文拼进去,且顺序不能错。
证书文件必须包含哪些内容
该 PEM 文件不是后端服务自己的 .crt,也不是私钥,而是一个“信任锚点包”:
- 只放 CA 证书(公钥),不放任何私钥、CSR 或终端证书
- 如果是自建 CA,就放你当初用
openssl x509 -req -signkey ca.key ...自签出来的ca.crt - 如果用了中间 CA(比如先签了 intermediate.crt,再用它签 backend.crt),则需按链顺序拼接:intermediate.crt 在前,ca.crt 在后
- 所有证书都必须是 PEM 格式(以
-----BEGIN CERTIFICATE-----开头),可合并进同一个文件,用换行隔开
配置中必须同步启用验证机制
proxy_ssl_trusted_certificate 单独存在无效,它必须配合以下三项共同生效:
-
proxy_ssl_verify on;—— 明确打开证书校验开关(默认是off) -
proxy_ssl_verify_depth 2;—— 设为实际证书链长度(例如:backend → intermediate → root = 3 层,这里填3) -
proxy_ssl_name "backend.internal";—— 指定期望的主机名,用于匹配后端证书中的Subject Alternative Name (SAN);若proxy_pass写的是 IP 地址,这一步必不可少
常见错误与绕过陷阱
很多内网部署失败,其实卡在细节上:
- 误把后端的
server.crt当作信任证书填入 —— 它只是终端证书,Nginx 验证时找不到签发者,直接报SSL certificate problem: unable to get local issuer certificate - PEM 文件里混入了空格、Windows 回车(
\r\n)、注释或多余文本 —— OpenSSL 解析失败,日志里可能只显示SSL_do_handshake() failed,无明确提示 - 没开
proxy_ssl_server_name on;—— 当后端是多域名虚拟主机(如用 SNI 区分不同服务),Nginx 握手时不传域名,后端返回默认证书,导致 SAN 不匹配 - 路径权限不对 —— Nginx worker 进程用户(如
www-data)读不到该文件,检查ls -l /path/to/ca-bundle.crt和所属组
快速验证是否生效
改完配置后,不用重启 Nginx,先用测试命令确认语法和路径:
-
nginx -t -c /etc/nginx/nginx.conf—— 确保配置加载无误 -
openssl x509 -in /path/to/ca-bundle.crt -text -noout | grep "Subject:"—— 查看是否真包含你预期的根或中间 CA 信息 - 发起一次请求,查看 error log:
tail -f /var/log/nginx/error.log,成功时不应出现certificate verify failed类报错











