nginx原生仅支持下游mtls(client→nginx),需ssl_client_certificate与ssl_verify_client配置;上游mtls(nginx→backend)不支持,须用nginx plus、envoy、haproxy或降级方案。

要实现 Nginx 反向代理下的 HTTPS 双向认证(mTLS),核心在于:Nginx 既要作为 TLS 客户端向后端服务验证其证书(上游 mTLS),又要作为 TLS 服务端向前端客户端验证其证书(下游 mTLS)。这两层认证彼此独立,需分别配置,不能混为一谈。
明确双向认证的两个方向
很多人误以为“Nginx 开启 client_certificate 就完成了双向认证”,其实这只是完成了 前端到 Nginx 的认证(下游 mTLS)。而反向代理场景下,若后端服务(如 Spring Boot、gRPC Server)也要求客户端证书,Nginx 还必须以“带证书的 TLS 客户端”身份与之通信——即 上游 mTLS。OpenSSL 和大多数后端框架原生支持上游 mTLS,但 Nginx 官方版(截至 1.25)不支持向上游发起带客户端证书的 TLS 请求。
- ✅ 下游 mTLS(Client → Nginx):用
ssl_client_certificate+ssl_verify_client实现 - ❌ 上游 mTLS(Nginx → Backend):标准 Nginx 不支持;需改用 nginx-plus(商业版)、Envoy、HAProxy,或让后端降级为 HTTP+IP 白名单等替代方案
下游双向认证(前端到 Nginx)实操要点
这是 Nginx 原生可完整支持的部分。关键不是“开了 verify”,而是证书链可信、错误处理得当、路径传递准确:
- CA 证书必须是 PEM 格式且包含完整信任链(根 CA + 中间 CA),仅放终端用户证书无效
-
ssl_verify_client on|optional|optional_no_ca:生产环境推荐on;optional_no_ca仅用于调试(跳过 CA 验证,但仍收证书) - 用
ssl_client_certificate /path/to/ca-bundle.pem指向 CA 证书文件,不是用户证书 - 通过
proxy_set_header X-Client-Cert $ssl_client_cert可将 Base64 编码的证书透传给后端做二次校验(如提取 SAN 或 DN) - 错误页建议自定义:
error_page 495 496 = @clientcertfail;,避免暴露 Nginx 默认提示
替代方案:如何让 Nginx “模拟”上游 mTLS
若必须用开源 Nginx 且后端强依赖客户端证书,常见折中做法有:
-
后端改用 TLS 终止在 Nginx + HTTP 内网通信:关闭后端 TLS,改用 IP 白名单或 JWT/OAuth2 校验,由 Nginx 在
proxy_set_header中注入可信身份标识(如X-User-DN) -
用 Lua 扩展(OpenResty)调用 OpenSSL API:通过
lua_ssl_trusted_certificate和lua_ssl_ciphers配合 Lua 脚本,在 rewrite_by_lua* 阶段构造带证书的 upstream 请求(复杂度高,维护成本大) - 前置一层轻量代理(如 socat 或 goproxy):Nginx 反向代理到本地 socat 进程,由 socat 加载客户端证书并转发 TLS 请求至后端——适合临时过渡
调试与排错关键命令
不依赖日志猜问题,用工具直击链路各环节:
- 测试下游认证是否生效:
curl -v --cert user.pem --key user.key --cacert ca.pem https://domain.com - 检查 Nginx 加载的证书链:
openssl s_client -connect localhost:443 -servername domain.com -showcerts,确认返回的 server certificate 后紧跟 CA 证书 - 验证客户端证书内容:
openssl x509 -in user.pem -text -noout | grep -E "(Subject|Issuer|DNS|IP Address)" - Nginx 日志中关注
$ssl_client_verify和$ssl_client_s_dn变量输出,确认是否解析成功
真正落地 mTLS 反向代理,本质是权衡安全边界与技术栈能力。开源 Nginx 是优秀的 TLS 终结者,但不是万能 TLS 中继。理清“谁验证谁”,再选对工具,比强行魔改更可靠。










