Nginx验证自建私有CA签发的客户端证书,核心是配置ssl_client_certificate指向PEM格式根CA证书(含CA:TRUE),并配合ssl_verify_client on和ssl_certificate等指令成套启用mTLS;客户端需提供对应证书与私钥。

要让 Nginx 用 ssl_client_certificate 验证由你自建私有 CA 签发的客户端证书,核心是让 Nginx 信任你的根 CA 证书,并在 TLS 握手时要求并校验客户端出示的有效证书。整个过程不依赖公网 CA,完全可控,但需注意证书链、格式和配置细节。
准备自建私有 CA 和客户端证书
先确保你已生成并妥善保管以下三类文件:
- CA 根证书(ca.crt):这是你自建 CA 的公钥证书,必须 PEM 格式,且不能带密码;Nginx 只读取它来构建信任锚点。
- 客户端私钥(client.key):PKCS#1 或 PKCS#8 格式均可,但推荐无密码保护的 PEM 格式(Nginx 不支持加载加密私钥用于 client cert 验证)。
-
客户端证书(client.crt):由你的 CA 签发,PEM 格式;建议包含完整证书链(即 client.crt + 中间 CA 证书,如有),但 Nginx 的
ssl_client_certificate只需根 CA,不处理中间链。
配置 Nginx 启用双向 TLS 认证
在 server 块中启用 SSL 并强制验证客户端证书:
server {
listen 443 ssl;
server_name example.com;
<pre class="brush:php;toolbar:false;">ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
# 指向你自建的根 CA 证书(不是客户端证书!)
ssl_client_certificate /etc/nginx/ssl/ca.crt;
# 必须开启此指令,否则不请求客户端证书
ssl_verify_client on;
# 可选:设置验证失败时返回的错误码(如拒绝未认证请求)
ssl_verify_depth 2;
location /api/ {
# 可将验证结果透传给后端(如通过 header)
proxy_set_header X-Client-Verify $ssl_client_verify;
proxy_set_header X-Client-DN $ssl_client_s_dn;
proxy_pass https://backend;
}
}
注意:ssl_client_certificate 的值必须是 PEM 格式的根 CA 证书文件路径;若使用中间 CA,应把中间证书合并进 ca.crt(根在前,中间在后),或直接用根 CA——只要客户端证书能被该根 CA 直接或间接签发即可。
客户端调用时正确携带证书
客户端(如 curl、Postman 或应用代码)需在 HTTPS 请求中提供自己的证书和私钥:
curl --cert client.crt --key client.key \
--cacert ca.crt \ # 此处是告诉 curl 信任哪个 CA(用于验证服务端)
https://example.com/api/
关键点:
-
--cert是客户端证书(含或不含链均可,但需能被服务端的ca.crt验证) -
--key是对应私钥 -
--cacert是用于验证服务端证书的 CA(与 Nginx 的ssl_client_certificate无关,仅用于客户端信任服务端)
若客户端证书由私有 CA 签发,但未被系统或客户端信任,--cacert 可省略(因为只影响服务端校验,不影响 Nginx 对客户端的校验)。
调试与常见问题
验证是否生效,可检查 Nginx 错误日志(error_log /var/log/nginx/error.log debug;)和响应头:
- 若收到
400 Bad Request或495 SSL Certificate Error,说明客户端未提供证书或证书不可信 - 查看
$ssl_client_verify变量值:SUCCESS、FAILED或NONE(未提供) - 确认
ca.crt内容无误:用openssl x509 -in ca.crt -text -noout检查是否为根 CA(Subject == Issuer,且有CA:TRUE) - 客户端证书必须包含
Extended Key Usage: TLS Web Client Authentication,否则 Nginx 默认拒绝(可通过ssl_verify_depth和 OpenSSL 配置放宽,但不推荐)











