2. CRL的更新机制:完整CRL与增量CRL的区别

聊CRL巡检,得先搞清楚CRL是怎么更新的。很多人觉得CRL就是一份黑名单,定期拉一下就行了。其实没那么简单。

我见过不少运维兄弟,巡检脚本写得挺溜,每天定时下载CRL。可一到真出问题时,发现证书明明被吊销了,业务系统却还在信任。查了一圈,问题出在——他们根本没搞清楚自己拉的是完整CRL还是增量CRL。

这两种CRL,更新频率、数据量、依赖关系完全不一样。巡检策略如果没对应上,很容易漏检。

一句话总结:完整CRL是全集,增量CRL是补丁包。两者配合使用,才能兼顾带宽和实效性。

2.1 CRL的两个面孔

PKI体系里,CA签发的CRL有两种形态:

  • 完整CRL(Full CRL):包含当前CA所有已吊销证书的序列号。体积通常比较大。
  • 增量CRL(Delta CRL):只包含自上次完整CRL签发以来,新吊销或状态变更的证书。体积小很多。

说白了,完整CRL是「全集」,增量CRL是「增量更新」。我个人习惯把完整CRL比作一本电话号码本,增量CRL就是每周更新的几页纸。

增量CRL必须依赖一个对应的完整CRL或上一次增量CRL才能合并出完整状态。你想想看,如果只下载了增量CRL,没有基准的完整CRL,那这个增量信息根本没意义。

2.2 完整CRL(Full CRL)

完整CRL的特征很明显:

  • 完全独立:不需要依赖任何其他CRL,自己就是一个完整的撤销状态集合。
  • 更新周期长:常见的是24小时或7天更新一次。因为数据量大,签发和分发成本高。
  • 体积大:如果CA签发了百万级证书,完整CRL可能达到几十MB甚至上百MB。

我在项目中遇到过一家金融机构,他们的根CA下有30多万张用户证书。完整CRL每月发布一次,文件大小接近70MB。客户端每次下载都卡很久,甚至超时。

巡检时要特别关注完整CRL的 nextUpdate 字段。如果发现下次更新时间已经过了,CA还在用旧的CRL,说明更新流程出了问题。

我的巡检小技巧:用openssl命令查看CRL的生效时间。

# 下载完整CRL并用openssl查看
wget http://crl.example.com/root.crl -O root.crl
openssl crl -inform DER -in root.crl -noout -text | grep -E "Last Update|Next Update"

# 如果用的是PEM格式
openssl crl -inform PEM -in root.pem -noout -text | grep -E "Last Update|Next Update"

重点关注 Next Update 是否还在未来时间。如果已过期,立刻告警。

2.3 增量CRL(Delta CRL)

增量CRL就是为了解决完整CRL体积大、更新慢的问题而生的。

  • 轻量高效:只包含增量变化,通常只有几KB到几百KB。
  • 更新频率高:可以做到几分钟甚至实时更新。适合在线业务场景。
  • 必须关联基准CRL:增量CRL本身不完整,必须和对应的完整CRL或上一次增量CRL拼起来用。

我曾经排查过一个事故:某电商平台的SSL证书吊销后,用户访问仍然正常。他们用的是增量CRL,但客户端只下载了增量CRL,没有保存上次的完整CRL,导致撤销状态无效。

避坑提醒:增量CRL的 CRL Number 和 Delta CRL Indicator 是关键字段。我曾经遇到过CRL编号跳号的问题——增量CRL编号不连续,中间丢了一份,结果所有依赖这个增量的客户端都无法正确合并状态。

巡检时,我建议记录每次CRL的编号。如果发现编号跳跃,立刻排查CA是否漏签了CRL。

2.4 完整CRL vs 增量CRL

我把两者差异整理成了表格,日常巡检时可以对照着看。

对比维度 完整CRL 增量CRL
数据范围 全部已吊销证书 仅新吊销或状态变更的证书
体积 大(几MB~上百MB) 小(几KB~几百KB)
更新频率 低(小时级~天级) 高(分钟级甚至实时)
独立性 完全独立 依赖基准CRL
分发压力 大(每次全量传输) 小(增量传输)
客户端处理 简单,直接替换 需要合并缓存
巡检关注点 nextUpdate是否过期 CRL编号连续性、基准CRL是否仍有效

说白了,如果你的业务场景对实时性要求高,比如金融交易、即时通讯,那增量CRL是标配。但如果业务对实时性没那么敏感,比如内部系统每日同步一次,那完整CRL就够用了。

我个人见过不少中小企业在用完整CRL,因为简单、没依赖。但一旦证书量上去,完整CRL的体积会拖垮网络和客户端。这时候不得不考虑增量CRL。

2.5 巡检工作的关注点

既然区分了两种CRL,巡检时就要「对症下药」:

  1. 如果只发布完整CRL:检查 nextUpdate 是否在合理范围内。如果过期了,立刻拉警报。
  2. 如果有增量CRL:除了检查完整CRL的过期时间,还要检查增量CRL的编号是否连续,有没有缺号、跳号。
  3. 配合检查CRL分发点:同一CA下,完整CRL和增量CRL通常放在不同URL路径。确保两个路径都能正常下载。
  4. 注意客户端缓存策略:我记得有个案例,客户端缓存了完整CRL,增量CRL也正常下载,但因为合并逻辑写错了,导致撤销状态混乱。巡检时要确认客户端的处理方式是否正确。

我的巡检命令模板:

# 检查完整CRL
curl -I http://crl.example.com/crl/full.crl | grep -i "last-modified\|content-length"

# 检查增量CRL的编号
openssl crl -inform DER -in delta.crl -noout -text | grep "CRL Number"

# 验证增量CRL是否与完整CRL同属一个CA
openssl crl -inform DER -in delta.crl -noout -text | grep "Issuer"

把这几条命令加到巡检脚本里,每天跑一遍。一旦发现异常,立刻人工介入。

2.6 核心流程

下面这张图展示了CRL更新的核心流程,以及完整CRL和增量CRL各自的生命周期。

CRL更新机制核心流程 CA服务器 证书吊销触发 完整CRL 包含所有吊销证书 长周期更新(小时/天) 增量CRL 仅包含增量变化 短周期更新(分钟) CRL分发点 CDP / LDAP CRL分发点 CDP / LDAP 客户端验证 合并状态 / 直接使用 巡检关注点 ⬆ nextUpdate / CRL编号连续性 ⬆ 分发点可达性

从流程图可以看出,CA签发两种CRL后,分别送入不同的分发点。客户端根据自己的策略选择拉取完整CRL还是增量CRL。巡检时,这两个路径都得覆盖到。

嗯,这里要注意:增量CRL的审计签名必须与完整CRL来自同一个CA。我在巡检时见过有人配错了增量CRL的签名密钥,导致客户端验证失败。