要在 HTTPS 代理中正确透传客户端证书信息,核心是启用双向 TLS(mTLS),让 Nginx 先完成客户端证书验证,再安全提取并转发关键字段——不能跳过验证直接读取变量,也不能用原始含换行符的证书内容直接塞进 HTTP 头。

必须开启并确保客户端证书验证成功
这是整个流程的前提。Nginx 不会自动解析或提供证书变量,除非明确要求且验证通过:
- 在
location块中设置ssl_verify_client on;(强制校验) - 指定可信 CA 证书路径:
ssl_client_certificate /path/to/ca-bundle.crt;(权限应为 644,不能含私钥) - 配置合理的链深度:
ssl_verify_depth 2;(一般 1–2 层足够) - 确认服务端证书已正确加载:
ssl_certificate和ssl_certificate_key已设置
用安全变量透传证书内容
$ssl_client_cert 含换行符和空格,直接设为 header 会导致截断或解析失败。应改用编码后变量:
- 使用
$ssl_client_escaped_cert(Nginx ≥ 1.19.7 支持):proxy_set_header X-Client-Cert-Escaped $ssl_client_escaped_cert; - 后端需解码还原:Python 用
urllib.parse.unquote(),Node.js 用decodeURIComponent() - 该变量仅在验证成功时有值,无需额外判空
同步传递身份标识与校验状态
光传证书不够,后端还需快速判断是否可信、是谁发起的请求:
-
proxy_set_header X-Client-Verify $ssl_client_verify;(值为 SUCCESS/FAILED/NONE) -
proxy_set_header X-Client-DN $ssl_client_s_dn;(主题名,已自动转义) -
proxy_set_header X-Client-CN $ssl_client_s_dn_cn;(仅 CN 字段,轻量无换行) - 可选加指纹用于白名单校验:
proxy_set_header X-Client-Fingerprint $ssl_client_fingerprint;(需 Nginx ≥ 1.19.0)
验证是否生效的简单方法
避免盲目调试,推荐两步确认:
- 临时把
proxy_pass指向一个 echo 服务(如 Python 的http.server或 nginx-demo 镜像),查看收到的所有 headers - 用 curl 携带有效客户端证书发起请求:
curl -k --cert client.pem --key client.key https://your-domain/api/test - 检查 Nginx error log,确认无
client SSL certificate verify error类报错


















