ssl_client_certificate 指令用于指定 PEM 格式的可信 CA 证书文件,Nginx 以此验证客户端证书是否由该 CA 或其下级合法签发;必须配合 ssl_verify_client on 使用,文件须为纯公钥、无私钥、无BOM/空格,支持单级根CA或合并的多级CA链。

ssl_client_certificate 是 Nginx 中用于启用 SSL 双向认证的关键指令,它的作用是指定一个 PEM 格式的 CA 根证书文件,Nginx 用它来验证客户端证书是否由该 CA(或其下级签发者)合法签发。
这个指令本身不“指定客户端证书”,而是指定信任的根(或中间)CA 证书——也就是你自建 CA 的 ca.crt(或包含完整信任链的 ca-bundle.crt)。客户端必须提供由该 CA 签发的有效证书,Nginx 才会放行。
✅ 正确配置 ssl_client_certificate 的要点
-
文件格式必须是 PEM(以
-----BEGIN CERTIFICATE-----开头,Base64 编码) - 内容只能是公钥证书(不能含私钥)
-
必须包含完整的信任链起点:通常是你的自签名根 CA 证书;若用了二级 CA,可把根 + 中间 CA 合并写入同一个
.crt文件(顺序:客户端证书的直接签发者在前,根 CA 在最后) -
路径需为绝对路径,且 Nginx worker 进程要有读取权限(如
chmod 644 /etc/nginx/ssl/ca.crt)
示例:
ssl_client_certificate /etc/nginx/ssl/ca.crt; ssl_verify_client on;
⚠️ 注意:
ssl_client_certificate和ssl_verify_client on必须同时存在才生效。只配前者不开启校验,等于没配。
? 文件内容怎么组织?常见三种情况
单级自建 CA(推荐测试用)
ca.crt就是你用openssl req -x509生成的那个根证书,里面只有一段BEGIN CERTIFICATE。-
两级 CA(生产常用)
把中间 CA 证书和根 CA 证书按签发顺序拼在一起(中间 CA 在上,根 CA 在下),保存为ca-bundle.crt:-----BEGIN CERTIFICATE----- (中间 CA 的 PEM 内容) -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- (根 CA 的 PEM 内容) -----END CERTIFICATE-----
使用公开 CA(不推荐用于双向认证)
Let’s Encrypt 等不签发客户端证书,所以不能用它们的根证书做ssl_client_certificate。双向认证必须用你自己控制的私有 CA。
? 验证配置是否生效的小技巧
-
检查语法:
nginx -t
-
查看 Nginx 错误日志(如
/var/log/nginx/error.log),常见报错:-
SSL_CTX_use_certificate_chain_file("/path/to/ca.crt") failed→ 路径错 / 权限不足 / 文件不是 PEM 格式 -
no certificate returned→ 客户端没发证书(浏览器未选、curl 没加--cert) -
unable to get local issuer certificate→ 客户端证书的签发者不在ssl_client_certificate指定的文件中
-
-
测试时用 curl 强制带客户端证书:
curl --cert client.crt --key client.key https://your-domain.com
? 补充:为什么不能直接写客户端证书路径?
因为 ssl_client_certificate 的设计目标是建立信任锚点(trust anchor),不是绑定某个具体客户端。
Nginx 不关心“谁来了”,只关心“这个人的证书是不是我信得过的 CA 发的”。
要限制具体客户端,需配合 $ssl_client_s_dn 或 $ssl_client_i_dn 在 if 或 map 中做进一步判断,或在应用层校验。
不复杂但容易忽略


















