从一次黑客攻击说起2011 年荷兰证书颁发机构 DigiNotar 遭到入侵。攻击者利用这次入侵伪造了*.google.com的证书并用它冒充 Gmail对伊朗用户实施中间人攻击试图窃取个人信息。这件事之所以被发现是因为 Google 在自己的服务中使用了证书固定Certificate Pinning技术能够检测到与预期证书不符的情况。但证书固定本身并不适合大规模推广——你不可能给每一个网站都预先内置它应该使用哪张证书。这次事件以及类似的一系列攻击推动 Google 的一个团队在 2013 年提出了**证书透明度Certificate TransparencyCT**机制。其核心思想很简单所有公开颁发的证书都必须记录在一个任何人都可以审计的公开日志里。从此CA 机构的每一次颁证行为都留下了公开可查的痕迹。截至今天全球已有超过170 亿张证书被记录在 CT 日志中CT 机制也于 2024 年荣获互联网安全领域的重要奖项 Levchin Prize。先搞清楚这个生态里有哪些角色CT 生态由四类参与者构成理解它们的分工是读懂后续内容的前提。证书颁发机构CA受信任的组织代表网站运营者签发证书。浏览器的根证书列表里有 150 多个 CA理论上任意一个都可以为任意网站签发证书——这正是问题所在。CT 执行客户端主要是浏览器如 Chrome、Safari、Firefox。它们只接受符合 CT 策略的证书例如要求证书必须提交到至少两个独立运营的 CT 日志。日志运营商运行 CT 日志的组织。日志是一个只增不减的公开列表CA 向日志提交证书后会得到一个签名证书时间戳SCT用来向浏览器证明该证书已被记录。监控方Monitor持续爬取 CT 日志、验证其行为是否正确的第三方机构同时帮助网站运营者发现被错误颁发的证书。Cloudflare 本身同时扮演了其中两个角色运营 Nimbus CT 日志以及通过 Merkle Town 仪表盘提供 CT 监控服务。运营一个 CT 日志到底有多难CT 日志对运营者的要求极为苛刻核心体现在两个维度完整性和可用性。完整性容错率为零CT 日志的设计是追加式的任何历史记录都不能被篡改或删除。更关键的是日志不能对不同客户端呈现不同的视图——它必须在整个生命周期内保持完全一致。这种完整性要求几乎不留任何余地。历史上一次硬件故障导致的单个比特翻转就足以让一个 CT 日志产生错误输出进而被 CT 程序取消资格。即便是软件更新如果引入了破坏正确性的变更也无法简单回滚——因为日志一旦发出的承诺SCT就必须兑现。最常见的致命故障是日志已对某张证书签发了 SCT却在将其写入持久存储之前崩溃导致无法将该证书纳入日志——这是对承诺的违背后果是直接失去资格。可用性99% 在线率说来容易做到很难Chrome 的 CT 日志策略要求每个 API 端点在 90 天滚动周期内的平均在线率不低于 99%。此外日志必须在 24 小时内称为最大合并延迟MMD将已签发 SCT 的证书纳入日志。然而旧版 CT APIRFC 6962的读取接口是动态的、难以缓存的。客户端可以请求任意范围的日志条目服务端需要实时构造各种包含证明Inclusion Proof。为了服务这些请求CT 日志服务器背后需要维护 5 到 10 TB 规模的数据库每天处理数千万次请求带宽成本和运维复杂度都极高。Cloudflare 自己的 Nimbus 日志也曾因这些原因遭遇过重大故障。最近一次是 2023 年 11 月数据中心完全断电导致日志长时间中断。正是这些运营门槛导致全球目前只有包括 Cloudflare 在内的六家机构在运营 CT 日志。如果其中一两家退出整个 CT 生态的稳定性就会受到严重威胁。下一代设计Static CT API2024 年 5 月Let’s Encrypt 发布了 Sunlight这是基于十年 CT 运营经验设计的下一代 CT 日志实现对应的规范被称为Static CT API。它从根本上改变了 CT 日志的数据组织方式。静态分块Tile让缓存变得自然Static CT API 将日志数据组织为一系列静态的、可缓存的瓦片Tile。日志运营商可以直接用 S3 兼容的对象存储服务如 R2、S3提供这些文件并通过 CDN 加速不再需要专门的 API 服务器来处理动态查询。这一改变从根本上解决了高可用的问题——静态文件的服务可靠性远高于动态 APICDN 缓存也能大幅削减带宽成本。去重中间证书节省存储空间全球受信任的中间证书和根证书数量有限数量级在数千级别。旧版设计中每条日志条目都会完整存储一遍证书链大量重复。Static CT API 只存储颁发者证书的哈希值客户端通过哈希从单独的端点查找完整证书显著降低了存储开销。SCT 内含索引消除合并延迟旧版设计中日志会在接收到证书后立即返回 SCT然后在后台异步将其写入日志。这个先承诺、后写入的机制是合并延迟MMD问题的根源——如果写入失败承诺就无法兑现。Static CT API 改变了这个流程日志只有在条目真正被写入并排序之后才返回 SCT且 SCT 中直接包含该条目在日志中的索引位置。延迟由此从随时可能超过 24 小时变为通常只有几秒同时也消除了承诺无法兑现的风险。有了索引SCT 审计也变得更高效客户端无需再通过哈希反查直接根据索引下载对应的分块数据即可验证。AzulCloudflare 在 Workers 上构建的 CT 日志基于上述规范Cloudflare 开发并开源了自己的实现命名为Azul取自葡萄牙语和西班牙语中的彩色陶瓷砖azulejos呼应了 Static CT API 的分块概念。项目地址github.com/cloudflare/azul设计原则部署在 Cloudflare 自己的全球网络上。2023 年 11 月的数据中心故障让团队深刻意识到依赖单一集中式数据中心的方案脆弱性太高。将日志部署在全球分布的高可用网络上是应对这一问题的根本思路。用 Rust 实现完全跑在 Workers 上。Cloudflare 有着用自己产品的文化传统——Azul 完全基于 Cloudflare 的 Developer Platform 构建包括 Workers、Durable Objects、R2 和 KV。这样做的额外好处是开发过程中发现的 SDK 缺陷和产品痛点可以直接反馈给内部团队改进同时也确保了任何外部开发者都能用同样的方式部署自己的 CT 日志。架构拆解监控 API读取Cloudflare R2静态分块文件天然适合放在对象存储里。R2 提供全球强一致性读取支持海量数据并可配置缓存和压缩策略不限读取次数。这部分几乎没有什么设计难度。提交 API写入Workers Durable Objects写入流程是真正的挑战所在。流程设计如下Frontend Worker接收来自 CA 的证书提交请求进行初步验证查询去重缓存然后将条目发送给后端排序。SequencerDurable Object是日志的核心状态机。每个 CT 日志对应一个 Durable Object 实例负责定期每秒一次将待处理的条目批量写入 R2更新日志的最新检查点Checkpoint并向等待响应的前端 Worker 发出信号。Durable Objects 的强一致性事务存储完美契合锁后端的需求——保存当前检查点这一关键状态。告警Alarm机制则用来每秒触发一次排序任务类似于传统服务器中的定时任务。去重缓存内存 Workers KV去重缓存需要在 50 GB 以上的规模下高效运作。Durable Objects 的存储上限和 D1 单库容量都无法满足直接从排序循环中远程读写又太慢。最终方案是分两层短期内存缓存固定大小处理分钟级别内的重复提交速度极快长期缓存Workers KV一个全局低延迟、最终一致的键值存储没有存储量限制用于跨会话的长期去重。性能瓶颈与突破初版架构上线后性能测试显示日志每秒只能处理 20-30 个新条目而目标是 70 个以上参考 Nimbus2025 日志的实际水位。根本原因在于单个 Durable Object 是单线程的。它必须同时处理来自前端的提交请求、每秒一次的排序任务、向 R2 写入十几个分块文件、向 KV 写入去重记录……任务数量远超单线程的调度能力导致排序任务频繁被延误。解决方案是引入一个中间层Batcher。前端 Worker 通过一致性哈希将请求分配到多个 Batcher DOBatcher 负责将多个请求缓冲后批量发送给 Sequencer减少 Sequencer 的直接请求数量。同时去重缓存的写入也交由 Batcher 处理进一步释放 Sequencer 的资源。这一架构将 CT 日志的吞吐量从 20-30 req/s 提升到了500 req/s 以上同时保持了每次排序只需 1-2 秒的低延迟。已经快了但未来的挑战更大CT 生态正在面临两个即将到来的重大压力Static CT API 和 Azul 的出现恰逢其时。证书寿命大幅缩短。CA/B Forum 正在推进一项提案计划到 2029 年将公开 TLS 证书的最长有效期从 398 天压缩至 47 天。Let’s Encrypt 走得更快计划在 2025 年底前提供有效期仅为 6 天的短期证书。根据 Merkle Town 的数据粗算这些变化将使 CT 生态中需要记录的证书数量增加16 到 20 倍。后量子证书的体积膨胀。现有的 P-256 ECDSA 证书体积不到 1 KB而换用后量子算法如 ML-DSA44后同一张证书的体积将膨胀到 4.6 KB 左右——意味着每条日志条目需要存储的数据量约是现在的4 倍。将这两个因素叠加CT 日志面临的存储和带宽压力将比今天高出数十倍。Static CT API 的分块缓存架构和运营成本的显著下降让更多组织有条件参与到 CT 日志运营中来从而将压力分散到更多节点上。总结Azul 这个项目表面上是 Cloudflare 开源了一个证书透明度日志的实现但它背后展示的东西更值得关注一个关键基础设施如何从少数玩家把持走向更广泛的参与。全球只有六家 CT 日志运营商这是一个高度脆弱的现状。降低运营门槛让更多组织能够以合理的成本加入是 CT 生态健康发展的必要条件。Static CT API 和基于 Workers 的实现正是为这个目标服务的。Cloudflare 的产品哲学在工程实践中的体现。自己先用、遇到 Rust SDK 缺陷就提 PR、把实际痛点反馈给产品团队——这种从内部压测开始的迭代方式比单纯的 beta 测试更接近真实负载。两个即将到来的挑战的预警。短寿命证书和后量子证书不是遥远的议题它们正在以可预期的时间表向 CT 生态逼近。现在开始建设能够应对 20 倍流量增长的基础设施不是超前而是刚好够用。代码已开源测试日志已上线。如果你有兴趣深入了解可以直接前往github.com/cloudflare/azul查看。参考来源Cloudflare Blog — “A next-generation Certificate Transparency log built on Cloudflare Workers”