Nginx实现mTLS客户端证书校验本质是TLS握手时服务端发起Certificate Request,依据ssl_client_certificate指定的PEM格式CA证书(需含CA:TRUE)验证签名、有效期及信任链可达性,不校验SAN/CN或吊销状态(除非配置ssl_crl),校验结果通过$ssl_client_verify等变量透传。

nginx 实现 mTLS 客户端证书校验,本质是在 TLS 握手阶段由服务端主动发起验证请求,并依据预置的信任锚(CA 证书)完成链式校验。它不依赖后端、不查 CRL(除非显式配置 ssl_crl),也不校验 SAN 或 CN 字段——只认签名有效性、有效期和信任链可达性。
客户端证书如何被 nginx 接收与触发校验
校验动作始于 TLS 握手第二步:ServerHello 后,nginx 发送 Certificate Request 消息,明确要求客户端提供证书。该行为由 ssl_verify_client on 指令驱动,且仅在已启用 HTTPS 监听(listen 443 ssl)并配好服务端证书的前提下生效。
若客户端未响应或发送空证书:
- 设为
on:TLS 握手直接失败,连接中断,返回 HTTP 400 错误(不是 403) - 设为
optional:握手继续,变量$ssl_client_verify值为NONE,后续逻辑可自行判断
nginx 实际执行的三项核心校验
一旦收到客户端证书,nginx 会立即在校验上下文中执行以下检查(全部通过才算 SUCCESS):
-
签名验证:用
ssl_client_certificate指定的 PEM 文件中任一 CA 公钥,验证客户端证书的数字签名是否合法 -
有效期检查:确认客户端证书的
Not Before和Not After时间范围包含当前系统时间 -
信任链构建:根据
ssl_verify_depth设置的层数(默认 1),尝试从客户端证书逐级向上回溯至根 CA;中间证书可内嵌在客户端证书中,也可合并进ssl_client_certificate文件
注意:nginx 不校验证书中的 Subject、SAN、OU 等字段内容;也不自动检查吊销状态(CRL/OCSP),如需此能力,必须额外配置 ssl_crl 指令并维护对应 CRL 文件。
CA 证书文件的关键要求
ssl_client_certificate 指向的文件必须满足:
- 仅含 PEM 格式 CA 证书(
-----BEGIN CERTIFICATE-----开头),不含私钥、不含服务端证书、不含客户端证书 - 每张证书需带
CA:TRUE的 Basic Constraints 扩展(可用openssl x509 -in ca.crt -text -noout | grep "CA:"验证) - 多级 CA 可合并为单个 PEM 文件,顺序不限(nginx 内部自动拓扑排序)
- 文件权限需确保 nginx worker 进程可读(如
644),路径需为绝对路径
校验结果如何透传与使用
校验完成后,nginx 生成一组只读变量,可在 location 块中直接引用或转发给后端:
-
$ssl_client_verify:值为SUCCESS、FAILED:reason或NONE -
$ssl_client_s_dn:客户端证书的完整主题 DN(如CN=api-client,OU=Services,O=MyOrg) -
$ssl_client_cert:Base64 编码的原始证书内容(含换行符,适合后端二次验签)
常用做法是在反向代理时透传:
proxy_set_header X-Client-Verify $ssl_client_verify;
proxy_set_header X-Client-DN $ssl_client_s_dn;


















