3. CRL分发点:CDP扩展的作用、配置与多级CA策略
好,咱们进入第三讲。CRL 本身是个文件,但客户端怎么知道去哪儿下载它?这就是 CDP(CRL Distribution Point)扩展要解决的问题。说白了,CDP 就是证书里写的一个 URL 地址,告诉客户端:“嘿,我的吊销列表在这儿,去那儿拉。”
我见过不少团队,证书配好了,OCSP 也搭了,唯独 CDP 写错或者没写。结果证书一吊销,客户端根本不知道上哪儿查。嗯,这种坑踩过一次就记住了。
3.1 CDP 扩展到底长什么样?
CDP 是 X.509 证书标准里定义的一个扩展项,属于 CRL Distribution Points。它不是一个简单的字符串,而是一个结构体。我拆开给你看:
- distributionPoint:核心字段,里面包含一个或多个 URI。常见的有 HTTP、LDAP 协议。
- reasons:可选字段,标明这个分发点只负责哪些吊销原因。比如有的 CDP 只管“密钥泄露”,有的只管“CA 泄露”。
- cRLIssuer:可选字段,如果 CRL 不是由颁发该证书的 CA 签发,而是由另一个实体签发,这里就填那个实体的 DN。
你可能会问:“一个证书里能写多个 CDP 吗?” 当然可以。而且我建议你至少写两个。一个挂了,客户端可以尝试另一个。我在生产环境里就遇到过,主 CDP 的 Web 服务器宕机,全靠备用 CDP 撑住了验证流程。
核心要点:CDP 扩展不是可选项,而是 PKI 合规的必需品。没有 CDP,CRL 就是一纸空文。
3.2 如何配置 CDP?
配置 CDP 取决于你用什么 CA 软件。我拿 OpenSSL 和 Microsoft AD CS 举例,这两个我都在项目里折腾过。
3.2.1 OpenSSL 中的 CDP 配置
OpenSSL 的 CA 配置文件(通常是 openssl.cnf)里,通过 crlDistributionPoints 字段来定义。看一个实际例子:
[ crl_ext ]
crlDistributionPoints = @cdp_section
[ cdp_section ]
fullname = URI:http://crl.mycompany.com/ca.crl
URI.0 = http://crl2.mycompany.com/ca.crl
URI.1 = ldap://ldap.mycompany.com/cn=CA,o=MyCompany,c=US?certificateRevocationList
这里我配了三个地址。第一个是主 HTTP 地址,第二个是备用 HTTP,第三个是 LDAP。OpenSSL 签发证书时,会自动把这些 URI 塞进证书的 CDP 扩展里。
个人习惯:我一般把 HTTP 地址放前面,因为 LDAP 查询在某些防火墙环境下会被拦截。HTTP 最通用,兼容性最好。
3.2.2 Microsoft AD CS 中的 CDP 配置
AD CS 的 CDP 配置在 CA 管理控制台的“扩展”选项卡里。你可以添加多个路径,比如:
http://pki.company.com/CRL/%3%8%9.crlldap:///CN=%7%8,CN=%2,CN=CDP,CN=Public Key Services,CN=Services,%6%10file://\\server\share\CRL\%3%8%9.crl
注意那些 % 开头的占位符。AD CS 用它们来动态生成路径:
| 占位符 | 含义 |
|---|---|
%1 |
CA 的 DNS 名称 |
%2 |
CA 的短名称 |
%3 |
CA 的密钥哈希 |
%8 |
CRL 序列号(十六进制) |
%9 |
CRL 序列号(十进制) |
举个例子,%3%8%9.crl 最终会变成类似 a1b2c3d4.123.456.crl 的文件名。这样每个 CRL 都有唯一文件名,不会覆盖。
我曾经踩过的坑:在 AD CS 里配 CDP 时,LDAP 路径的占位符大小写搞错了。结果客户端解析失败,CRL 下载不了。后来我养成了习惯,配完后一定用 certutil -f -url 命令测试一下 CDP 是否可达。
3.3 多级 CA 下的 CRL 分发策略
到了多级 CA 环境,事情就复杂了。根 CA、二级 CA、企业 CA……每一级都有自己的 CRL。客户端验证一个终端实体证书时,需要把整条链上的 CRL 都拉下来。你想想看,如果每个 CA 的 CRL 都放在不同地方,客户端得发起多少次 HTTP 请求?
我参与过一个大型政务 PKI 项目,三级 CA 结构,总共 5 个 CA。一开始每个 CA 的 CRL 都独立发布,结果客户端验证一个证书要下载 5 个 CRL,慢得离谱。后来我们优化了策略,核心思路就两条:
策略一:集中式 CRL 分发点
所有 CA(根、二级、三级)的 CRL 都发布到同一个 HTTP 服务器上。客户端只需要知道这一个服务器地址。根 CA 的 CDP 指向 http://crl-hub.company.com/root.crl,二级 CA 指向 http://crl-hub.company.com/subca1.crl,以此类推。
好处是管理简单,客户端配置也简单。坏处是单点故障——这个 Hub 挂了,所有 CRL 都拿不到。
策略二:分层级联 CRL 分发
每个 CA 只发布自己的 CRL,但父 CA 的 CDP 里包含子 CA 的 CRL 地址。举个例子:
- 根 CA 的 CDP:
http://root-ca.company.com/root.crl - 二级 CA 的 CDP:
http://sub-ca.company.com/subca.crl - 三级 CA 的 CDP:
http://leaf-ca.company.com/leaf.crl
客户端验证时,顺着证书链逐级下载。这种方式分散了负载,但客户端需要解析多个 CDP 地址,网络开销大。
我个人更推荐 混合策略:根 CA 和二级 CA 的 CRL 集中发布,终端 CA 的 CRL 独立发布。这样既保证了关键 CA(根、二级)的高可用,又避免了终端 CA 的 CRL 成为瓶颈。
实战建议:不管用哪种策略,一定要给 CRL 分发点加 CDN 或负载均衡。我在一个金融项目里,CRL 服务器被客户端轮询打到过载,加了 CDN 之后,压力瞬间降下来了。
3.4 CDP 配置的常见误区
我整理了几个我亲眼见过的翻车案例,你对照着检查一下自己的配置:
| 误区 | 后果 | 正确做法 |
|---|---|---|
| CDP 只配了一个 HTTP 地址 | 服务器宕机后 CRL 不可用 | 至少配 2 个不同协议的地址 |
| CDP 地址写成了内网 IP | 外网客户端无法下载 | 使用公网可解析的域名 |
| LDAP 路径格式错误 | 客户端解析失败 | 用工具验证 LDAP URI 语法 |
| 多级 CA 下 CDP 指向了错误的 CRL | 客户端拿到错误的吊销列表 | 每个 CA 的 CDP 指向自己的 CRL |
3.5 CDP 与 CRL 的完整交互流程
为了让你更直观地理解,我画了一张流程图。它展示了从客户端拿到证书开始,到最终完成吊销验证的完整路径。
这张图里,客户端先解析证书里的 CDP 扩展,拿到一个地址列表。然后按顺序尝试——HTTP 不行就换 LDAP。一旦成功下载 CRL,还要验证 CRL 本身的签名和有效期。全部通过,才算完成吊销验证。