nginx证书验证失败若由内网代理mitm导致,需确认是否被拦截、检查代理根证书是否已导入系统或proxy_ssl_trusted_certificate文件,并通过openssl抓包验证证书subject是否被替换为代理域名。

企业内网代理(如上网行为管理设备、SSL解密网关、DLP系统)常会主动拦截并重写 TLS 流量,导致 Nginx 作为上游客户端或服务端时出现证书校验失败。这类问题不是 Nginx 配置错误,而是流量在传输路径中被中间设备“Man-in-the-Middle”(MITM),Nginx 收到的是代理伪造的证书而非真实后端证书。排查需从协议层穿透到设备策略,重点验证证书来源与信任链是否被篡改。
确认是否被内网代理拦截
先排除 Nginx 自身配置问题,聚焦“外部干预”迹象:
- 同一后端地址,在办公网访问报
certificate verify failed或SSL_do_handshake() failed,但直连服务器(如跳过代理走专线/手机热点)正常 → 强烈提示中间代理介入 - 用
openssl s_client -connect backend-ip:443 -servername backend.example.com -showcerts抓到的证书 Subject 不是后端域名,而是类似CN=proxy-ssl-gateway.internal或OU=SSL Interception→ 证书已被替换 - Nginx error.log 中出现
unable to get local issuer certificate,且proxy_ssl_trusted_certificate已包含全部根/中间 CA,仍失败 → 说明收到的证书签发者不在你信任的 CA 列表中 - 抓包(tcpdump 或 Wireshark)发现 TLS 握手过程中 Server Hello 后紧接 Certificate 消息,但证书链里第一张证书的 Issuer 并非你预期的 Let’s Encrypt 或内网 CA,而是未知机构 → 实锤 MITM
检查代理设备是否注入了自签名根证书
内网代理要完成 SSL 解密,必须在终端(包括 Nginx 所在服务器)上预装其自签名根证书。若未安装或未生效,Nginx 就无法信任它签发的中间证书:
- 登录 Nginx 服务器,检查系统信任库是否已导入代理根证书:
trust list | grep -i "proxy\|security\|intercept"(RHEL/CentOS)或awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' /etc/ssl/certs/ca-certificates.crt | grep -i proxy - 若未找到,需将代理厂商提供的
RootCA.crt(PEM 格式)追加进系统 CA 包:sudo cp RootCA.crt /usr/local/share/ca-certificates/sudo update-ca-certificates - 若使用
proxy_ssl_trusted_certificate指定独立 CA 文件,务必把该 RootCA.crt 显式加入其中,不能只依赖系统默认信任库
绕过或适配代理的 TLS 解密策略
不是所有业务都允许被解密(如金融、密钥交换类接口)。可按安全等级分级处理:
- 对高敏感后端(如支付网关、KMS 接口),联系网络安全部门,在代理设备上配置“SSL 解密豁免规则”,基于目标 IP/域名/端口跳过 MITM
- 若必须走代理解密,且代理支持 SNI 透传(如 FortiGate、Palo Alto),确保 Nginx 开启 SNI:
proxy_ssl_server_name on;proxy_ssl_name "backend.example.com";
否则代理可能因无法识别目标域名而返回默认伪造证书 - 某些代理强制要求 Client Hello 中带特定 ALPN 协议(如
http/1.1而非h2),可在 upstream 块中限制:proxy_ssl_alpn h2 http/1.1;(需 OpenSSL ≥ 1.0.2) - 临时验证:在测试环境关闭代理 SSL 解密功能,观察 Nginx 是否恢复 → 快速定位责任边界
日志与错误码精准对应代理行为
不同代理设备触发的 OpenSSL 错误码有特征,可辅助判断拦截阶段:
-
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed→ 代理证书未被信任(最常见) -
error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed→ 证书链不完整(代理只发了终端证书,漏中间 CA) -
error:14094410:SSL routines:ssl3_read_bytes:ssl handshake failure→ 代理拒绝握手(SNI 不匹配、ALPN 不支持、TLS 版本被禁) -
error:1408F10B:SSL routines:ssl3_get_record:wrong version number→ 代理返回了 HTTP 明文响应(如拦截失败降级为 302 重定向),Nginx 当作 TLS 流解析











