Nginx 通过 ssl_crl 实现 mTLS 场景下客户端证书的实时吊销拦截,握手时检查 PEM 格式 CRL 文件,匹配即拒连;需启用 ssl_verify_client、CRL 由同源 CA 签发、定期更新并确保 Nginx 可读,推荐 ssl_crl_check all。

使用 Nginx 配合 ssl_crl 可以在 TLS 双向认证(mTLS)场景中,对已签发但因私钥泄露、设备失窃等原因需要立即停用的客户端证书进行实时拦截。其核心机制是:Nginx 在握手阶段主动检查客户端证书是否出现在指定的 CRL 文件中,若匹配则拒绝连接,无需等待证书自然过期或手动重载配置。
前提条件与准备要点
要让 ssl_crl 生效,需满足几个基础条件:
- Nginx 必须启用并正确配置双向认证(
ssl_verify_client on),否则不会校验证书链,CRL 检查不会触发 - CRL 文件必须由客户端证书的同一 CA 签发,且使用 PEM 格式(以
-----BEGIN X509 CRL-----开头) - CRL 文件需定期更新(如通过 cron + OpenSSL 命令生成),并确保 Nginx 进程有读取权限
- 推荐启用
ssl_crl_check all(Nginx 1.19.4+),强制检查整条证书链中的每一级是否被吊销(包括中间 CA)
配置示例与关键参数说明
以下为典型的 server 块配置片段:
server {
listen 443 ssl;
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
<pre class="brush:php;toolbar:false;">ssl_client_certificate /path/to/ca-bundle.crt; # 客户端信任的根+中间 CA
ssl_verify_client on;
ssl_verify_depth 2;
ssl_crl /etc/nginx/ssl/client-crl.pem; # 吊销列表路径
ssl_crl_check all; # 检查证书链中所有证书是否被吊销(可选,高安全要求时启用)
# 其他配置...}
注意:ssl_crl 路径必须是绝对路径;文件内容变更后,Nginx 不会自动重载 CRL —— 但无需 reload 或 restart,只要文件被替换(原子写入),下一次新连接握手时即生效。这是“准实时”的关键:封禁延迟 ≈ 下一个客户端建连时间。
生成与更新 CRL 的实用方法
CRL 不能手动生成,需依赖 CA 私钥和 OpenSSL 工具链。典型流程如下:
- 维护一个吊销记录数据库(如文本文件
revoked.txt,每行含序列号、吊销时间、原因) - 用 OpenSSL 命令生成新 CRL:
openssl ca -gencrl -keyfile ca.key -cert ca.crt -out client-crl.pem -config openssl.cnf
其中openssl.cnf需配置crl = crl/crl.pem和crlnumber = crl/crlnumber等字段 - 更新后建议用
openssl crl -in client-crl.pem -text -noout验证格式与吊销条目 - 生产环境建议将 CRL 生成封装为脚本,并配合 rsync 或 inotify 自动同步到 Nginx 服务器
常见问题与验证技巧
遇到 CRL 不生效,优先排查这几项:
- 客户端证书是否确实被 CA 吊销?用
openssl x509 -in client.crt -noout -serial查序列号,再比对 CRL 中的Revocation Date条目 - Nginx 错误日志是否出现
certificate revoked?这是最直接的证据;若无此日志,说明未触发检查(可能ssl_verify_client未开启,或客户端未提供证书) - CRL 文件是否包含完整证书链所需的全部吊销信息?例如:若客户端证书由中间 CA 签发,而 CRL 仅由根 CA 发布,则 Nginx 默认不检查中间 CA 是否被吊销(除非启用
ssl_crl_check all) - 确认系统时间准确 —— CRL 有
Next Update时间戳,Nginx 会跳过过期 CRL(日志提示error reading CRL file或静默忽略)


















