nginx可通过$ssl_client_i_dn变量结合map指令实现基于ca机构的细粒度访问控制,利用正则提取issuer dn字段(如o、cn)构建白名单,在tls握手后即时拦截非法请求。

可以通过 Nginx 的 $ssl_client_i_dn 变量解析客户端证书的 Issuer DN(发证机构专有名称),结合正则匹配与 map 指令实现基于 CA 机构的细粒度访问控制,无需后端参与即可在 TLS 握手后立即拦截非法请求。
理解 $ssl_client_i_dn 的内容格式
$ssl_client_i_dn 是 Nginx 在启用客户端证书双向认证(mTLS)后自动提供的变量,值为 PEM 证书中 Issuer 字段的 RFC 2253 格式字符串,例如:
注意它不包含空格或换行,各属性用逗号分隔,顺序可能因 CA 签发习惯而异。关键是要按语义提取字段(如 O 组织名、CN 通用名),而非依赖固定位置。
用 map 指令构建可信 CA 白名单
避免在 if 中直接正则判断(易出错且性能差),推荐用 map 预定义可信 Issuer 规则:
- 在
http块中定义 map,将$ssl_client_i_dn映射为布尔标识或等级标签 - 使用正则捕获组提取关键字段,例如匹配
O=MyOrg或CN=Internal-CA - 未匹配项默认设为拒绝值(如
0),匹配成功设为允许值(如1)
示例配置:
map $ssl_client_i_dn $trusted_ca {
default 0;
~*O=Acme[[:space:]]+Corp 1;
~*CN=Prod-Internal-CA 1;
~*C=CN,ST=Beijing,O=Gov-CA 1;
}
在 server 或 location 中执行拦截
利用 $trusted_ca 变量配合 if + return 实现即时拦截:
- 确保已开启
ssl_verify_client on并配置了受信任的 CA 证书链(ssl_trusted_certificate) - 在需要保护的 location 内添加判断:当
$trusted_ca != 1时返回 403 - 可叠加其他维度,比如同时检查
$ssl_client_s_dn(主体 DN)做角色分流
示例片段:
location /api/admin {
if ($trusted_ca = 0) {
return 403 "Unauthorized CA";
}
proxy_pass http://backend;
}
增强可靠性的注意事项
仅靠 DN 字符串匹配存在绕过风险,需配合以下措施:
- 始终校验证书有效性(有效期、吊销状态),Nginx 默认只做签名和链式验证,建议启用 OCSP stapling(
ssl_stapling on) - 避免仅匹配 CN,优先使用 O(组织)、OU(部门)等更稳定的字段;多个 CA 可用不同正则覆盖
- 日志中记录
$ssl_client_i_dn和$ssl_client_serial,便于审计异常证书来源 - 若需更复杂策略(如按 OU 动态路由),可用 Lua 模块(如 lua-resty-openidc 扩展)进一步处理











