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.crl
  • ldap:///CN=%7%8,CN=%2,CN=CDP,CN=Public Key Services,CN=Services,%6%10
  • file://\\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 与 CRL 交互流程图 CDP 与 CRL 交互流程 客户端获取证书 解析 CDP 扩展 选择 CDP 地址 HTTP 下载 CRL LDAP 查询 CRL 验证 CRL 签名与时效 完成吊销验证 说明 客户端按 CDP 地址顺序 尝试下载,失败则换下一个

这张图里,客户端先解析证书里的 CDP 扩展,拿到一个地址列表。然后按顺序尝试——HTTP 不行就换 LDAP。一旦成功下载 CRL,还要验证 CRL 本身的签名和有效期。全部通过,才算完成吊销验证。