4、CRL 分发点(CDP)扩展:如何定位 CRL 下载地址
拿到一张证书,怎么知道它对应的 CRL 该去哪下载?答案就在证书的 CRL 分发点(CDP)扩展里。这个扩展就像是一张“导航地图”,告诉客户端去哪里取吊销列表。没它,CRL 验证就无从谈起。
我个人习惯,拿到证书先看 CDP。不是别的,因为绝大部分 CRL 下载失败,根源都是 CDP 写错了或者指向了不可达地址。你想想看,地址都找不到,后面所有步骤全是白费。
CDP 扩展长什么样?
CDP 是 X.509 v3 扩展中的一个标准项。它的结构其实挺简单——一个或多个分发点(Distribution Point),每个分发点里包含一组 URI 地址。证书里可以写多个地址,客户端按顺序尝试,直到拿到 CRL 为止。
用 OpenSSL 看 CDP 最方便。我常用的命令是:
openssl x509 -in certificate.pem -text -noout | grep -A 6 'X509v3 CRL Distribution Points'
输出大概长这样:
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.example.com/ca.crl
URI:ldap://ldap.example.com/cn=CA,dc=example,dc=com?certificateRevocationList;binary
URI:file:///var/crl/ca.crl
嗯,这里要注意。每个 URI 前面都有 URI: 前缀,协议可以是 http://、ldap://、file:// 甚至 ftp://。但现实中,HTTP 占多数,LDAP 偶尔见,文件路径基本只在内部用。
为什么要多个地址?
不是闲得慌。多写几个地址,是为了容错。我曾经遇到过,CA 给了一个 HTTP 地址,但那个 CDN 节点挂了,幸好证书里还配了一个 LDAP 地址,从域控里硬拉了下来。如果只写一个地址,那次巡检就要报异常了。
证书签发者会按优先级排地址顺序。大部分 CA 会把 HTTP 放在第一个,因为通用性好、防火墙兼容性强。LDAP 虽然有目录同步优势,但端口 389/636 在企业内网经常被自定义 ACL 拦截,外网更不用说了。
用工具解析 CDP——不只是 OpenSSL
OpenSSL 最基础,但信息展示不够结构化。我习惯在诊断时用 certutil(Windows)或 keytool(Java)做交叉验证。比如:
| 工具 | 命令示例 | 适用场景 |
|---|---|---|
| OpenSSL | openssl x509 -in cert.pem -text -noout | Linux / 通用 |
| certutil | certutil -v -urlfetch cert.cer | Windows 企业环境 |
| keytool | keytool -printcert -file cert.cer | Java 应用栈 |
用 certutil 有个好处——它会自动尝试下载 CRL,并告诉你哪个地址成功、哪个失败。我曾经在生产环境抓到一个诡异问题:OpenSSL 显示 CDP 是正常的,但 certutil 实际下载时报 404。
certutil -urlfetch cert.cer 时带上 -v 参数,会打印每一步的 HTTP 状态码。省得你手动去 curl 一堆地址。
常见 CDP 格式与坑点
地址格式写错了,比地址不可达更隐蔽。我简单列一下我会特别注意的几种:
- HTTP URL —— 最常见。注意路径是否包含
. 或.crl后缀?有些 CA 用application/pkix-crl响应,但 URL 写的是.der,客户端照样能处理。但如果你看到 URL 结尾是/没有文件名,那基本是错的。 - LDAP URL —— 结构复杂。标准格式是
ldap://host:port/baseDN?attributeName?scope?filter。我见过最坑的写法是:属性名写成了certificateRevocationList;binary但忘了写分号,导致 LDAP 返回不了二进制内容。 - file:// URI —— 只在本地验证有用。证书发布到客户端后,客户端根本访问不到 CA 本地的文件路径。要是 CDP 里只有 file://,CRL 分布必失败。
- AIA 扩展混用 —— 有人会把 CRL 地址放在 Authority Information Access 里,但 CRL 应该用 CDP。这不是标准做法,但有些 CA 自作聪明,你查时必须两者都看。
实战:从证书里拽出 CDP 地址
假设你现在有一张 DER 格式的证书 server.cer。我来演示一下完整的手动流程:
- 转成 PEM(方便文本查看)
openssl x509 -in server.cer -inform DER -out server.pem -outform PEM - 查看 CDP
openssl x509 -in server.pem -text -noout | grep -A 10 'X509v3 CRL Distribution Points' - 提取出 URI 列表(可能有多个)
用sed或awk简单清洗,或者直接用眼睛看。 - 逐个测试 HTTP 地址(最常用)
curl -I http://crl.example.com/ca.crl
返回200 OK且Content-Type: application/pkix-crl才算可用。
我实际遇到过,证书里写的 HTTP 地址是 http://crl.example.com/ca.crl,但 curl 返回 302 重定向到 https://。客户端如果没配置跟随重定向,就下载失败了。排查时你不去实际 curl 一下,光看 CDP 文本根本发现不了。
流程图:从证书到 CRL 下载地址
下面这张图帮你梳理整个逻辑链条。我习惯把它贴在排查文档第一页,看完就清楚下一步该干什么。
避坑指南:我曾经踩过的坑
讲几个真实教训,你碰到类似情况就别绕弯了。
- CDP 里写的是 IP 而不是域名 —— 不少内网 CA 图方便直接填了 IP。一旦发生网络规划变更,IP 被回收,CRL 瞬间全崩。我建议任何生产的 CDP 都要用域名,并且做 DNS 冗余。
- 多个 CDP 指向同一个域名但不同路径 —— 有些 CA 为了让负载均衡,写了好几个 URL,但实际解析到同一台服务器。一旦那台服务器挂了,所有地址都废了。最好保证不同地址在不同网络区域或 CDN 上。
- .crl 文件实际是 DER 格式但 URL 后缀是 .pem —— 大多数客户端在下载时根据 Content-Type 判断,不看后缀。但老旧设备(尤其是一些嵌入式系统)必须靠后缀来识别。我遇到过打印机只认
.crl后缀,给它.pem直接拒绝下载。
总结一句话: 定位 CRL 下载地址,核心就是找到 CDP 扩展里所有 URI,然后逐一验证可达性。不要只依赖 OpenSSL 文本输出,要实际发起 HTTP 请求或 LDAP 查询。地址格式哪怕错一个字符,CRL 分发就全盘卡死。