摘要

  • RRDP 的 session_id 与 serial 是同步坐标,不是全网一致性的证明。已经见过的同一增量序号如果后来对应另一份哈希,增量历史就失去了可重放性。
  • 发现突变后,验证器应告警并改从最新 snapshot 重建;但 snapshot 成功仍不等于 ROA 有效,更不等于路由器必须拒绝路由。manifest、证书、CRL、签名数据、验证载荷、路由策略与实际转发各有独立判定。

设想一个明确标注为演练、而非真实事故的场景。运营团队在两个站点运行相互独立的 RPKI 验证器。两者轮询同一个 RRDP notification 地址,显示同一个 session_id,下一轮又都看到最新 serial 已经前进。按常见监控逻辑,它们应当一致。

差异藏在监控没有保存的过去。站点甲先前记住:serial 1774 的 delta 哈希为 A。站点乙稍后收到的 notification 却说,同一会话中的 serial 1774 哈希为 B。每台机器下载到的文件都可能与自己当时看到的 notification 相符;两边日志也都可能显示“哈希校验成功”。然而它们重建出的本地仓库并非同一份,随后得到的 Validated Payload 也可能不同。

问题不在于哪台机器读错了当前 serial,而在于一个本应不可变的历史坐标出现了两份内容。

RFC 9697 专门处理这种 RRDP session desynchronization。验证器保存上一次成功 notification 中的 serial 与 hash 对;下一次拉取时,把新旧窗口中重叠的 serial 逐项比较。已经见过的 serial 如果换了 hash,就应报告异常,并从最新 snapshot 重新同步。

这条规则把“相信仓库”改成“验证仓库留下的结构”。仓库仍然负责发布,CDN 仍然负责分发,但验证器拥有拒绝继续沿一段自相矛盾历史前进的有限权力。

RRDP 交付的是变化历史,不只是文件目录

RFC 6480 描述的 RPKI 由资源证书、CRL、ROA 等签名数据以及分布式仓库组成。仓库让依赖方取得公开材料,是一个必要的交换层;它本身却不是这些材料的签发者,也不因保存字节而取得资源或路由的权力。

RFC 8182 让这个交换层可以规模化。稳定的 update notification URL 提供当前会话、serial、snapshot 地址,以及服务器仍保留的 delta 链。snapshot 是某一时点的完整 publish 集合;每个 delta 则只描述一个 serial 增量内的新增、替换与撤回。

验证器可以从 snapshot 建立本地副本,也可以在会话没有变化且缺失增量连续可得时,按 serial 顺序逐个应用 delta。下载后的 delta 必须与 notification 给出的哈希一致,会话必须一致,serial 必须恰好比上一次处理值大一。遇到撤回或替换时,还要确认目标最初来自同一个 repository server,防止一台恶意服务器删除别处取得的数据。

这些约束保证一次本地状态迁移可以复算,却没有创造全网同时提交。不同验证器的轮询时刻不同,缓存年龄不同,网络故障也不同。RFC 6811 因此承认全球 RPKI 视图会因抓取与更新时间产生松散一致性。

正常时间差与历史突变不能混为一谈。前者是甲已经走到第 1775 步、乙暂时还在第 1774 步;后者是两边对“第 1774 步究竟是什么”没有共同答案。时间最终可能追平第一种差异,却不会自动修复第二种分叉。

UUID 离开 notification 地址就失去边界

session_id 的外观很像全局身份,但 RFC 8182 明确要求把它与 update notification 的位置合用。随机 UUID 不能单独标识一个会话,因为另一台恶意服务器可以复用已有值。

位置限定 repository 的作用域,会话标识限定该位置的一次初始化历史,serial 排列这段历史中的变化,hash 则把每个 snapshot 或 delta 坐标绑定到具体字节。只看任意一项都会失真。

因此,舰队监控不能只保留“会话正常、最新 serial 相同”。真正有诊断价值的是 notification 的 origin 与完整 URL、当前会话、serial、snapshot hash、全部仍在窗口内的 delta serial/hash、上一次成功窗口中的重叠部分,以及本地应用结果。

当两台验证器产生不同 VRP 数量时,这套证据可以继续回答:分叉发生在 HTTP 分发、增量历史、manifest、证书验证、软件解释,还是下游缓存交付。一个绿色数字做不到。

不可变不是修辞,而是 CDN 能够复用工作的条件

RRDP 面对的是发布者较少、依赖方很多的非对称规模。RFC 8182 允许 snapshot 与 delta 经过 HTTP 缓存和 CDN,是因为文件一旦出现在 notification 中,URL 与内容就不再变化。一个边缘节点缓存一次,其他验证器才能把命中视为相同状态迁移的输入。

同一坐标换字节,损坏的不只是“完整性”。它还破坏了分发经济:不同 CDN 边缘可能各自保留一版,后来的验证器按到达时刻落入不同历史。会话若持续数月,分叉也可能持续数月,而最新 serial 看起来依旧相同。

RFC 9697 要求保留的并非无限历史。只需让上一次成功 notification 与下一次 notification 在若干 serial 上重叠,就能比较这些 serial 的旧 hash 与新 hash。有限记忆足以证明过去被改写。

告警也必须准确命名这一事实。它不是普通“下载失败”,也不是“发现新版本”,而是“同一 notification 位置、同一 session、同一既见 serial 现在声称另一 hash”。只有保留这个四元关系,修复团队才知道为什么不能继续应用增量。

Snapshot 重置的是传输历史,不是验证规则

delta 缺失或被拒绝时,RFC 8182 要求验证器处理当前 snapshot;RFC 9697 把这一恢复动作应用到历史 hash 突变。snapshot 直接提供当前完整 publish 集合,使验证器不再依赖有争议的增量路径。

重同步不是免责通道。snapshot 仍须通过格式检查,下载字节必须匹配 notification 的 hash,session_id 必须一致,serial 也必须符合处理规则。snapshot 自身被拒绝,就意味着 RRDP 不能提供新的可用状态。

把这个动作简单称为 fallback,还会掩盖容量风险。正常情况下只下载小 delta 的大量验证器,如果同时转向完整 snapshot,会把带宽、内存、CPU、源站与 CDN 压力同时放大。运营者需要退避、容量余量、分批执行与停止条件,不能把恢复做成无限重试风暴。

重置之前还应保存取证材料:新旧 notification 的字节或哈希、抓取时间、origin 检查、重叠 serial/hash、拒绝原因和受影响仓库。否则服务可能恢复,解释权却被清空,团队无法区分发布错误、CDN 不一致、软件缺陷或蓄意干预。

成功处理 snapshot 只证明本地副本与本次 notification 一致。它不证明这是全球最新状态,不证明其中每份签名材料都有效,也不证明其他验证器已完成收敛。

Same-Origin 限制谁能借验证器消耗别人的资源

RRDP notification 使用绝对 URI 指向 snapshot 与 delta。初版规范没有明确禁止跨 origin 引用和重定向。RFC 9674 后来要求这些 URI 与 notification 使用相同 scheme、host 与 port,并禁止跨 origin redirect。

这个限制让一台 repository server 不能通过验证器把负载导向另一台服务器,也让发布 notification 的主体承担提供所需文件的资源责任。验证器发现跨 origin 条件时,应拒绝该 RRDP session 并记录原因。

Same-Origin 仍然不是内容有效性。来自预期 HTTPS 主机的文件可能包含过期、撤销或不合规材料;传输证书出错也不代表中间人可以伪造有效 RPKI 签名。HTTPS 说明谁回答,RRDP hash 说明文件是否符合 notification,资源证书与签名规则才说明材料是否可用。

发布服务、CA 与依赖方拥有不同权力

写入侧也维持同样分工。RFC 8181 定义 CA engine 如何要求 publication service 新增、替换或撤回 RPKI 材料。两者可以属于不同机构,发布消息使用的 BPKI 与公开 RPKI 材料的认证体系彼此分开。

一次 publication success 只表示获准客户端完成了仓库操作,不表示依赖方一定接受其中的证书、CRL 或 ROA。反过来,CA 已经正确签发撤回意图,也不保证 RRDP/CDN 立即向每个依赖方呈现一致历史。

事故语言必须尊重这条边界。可以是 CA 意图正确、发布服务状态错误;也可以是分发历史一致、签名材料无效;还可以是验证器结果正确、RPKI-to-Router 未送达;甚至是路由器收到新状态,而本地策略有意不拒绝路由。把它们都叫作“RPKI 错了”,只会让修复打向错误层。

有签名不等于当前、完整或可用于路由

RFC 6488 规定 RPKI 签名材料的一般验证:CMS 结构、嵌入的 EE 证书、content type、message digest 与 signature 都须满足要求。规范同时指出,这些只是必要条件,每一类材料还需要自身的附加检查。

一份签名正确的文件仍可能已经被更新版本取代。攻击者或故障分发层也可以隐藏一份本来应当出现的文件。签名能揭示未授权修改,却不会独自揭示遗漏与重放。

RFC 9286 的 manifest 为一个 CA publication point 列出应存在的文件名及哈希。依赖方用当前 manifest 控制哪些 certificate、ROA 与 CRL 进入验证;无法取得全部列出文件时,fetch 视为失败,随后只能按有期限的缓存规则处理,而不能默默使用偶然到达的子集。

Manifest 还有自己的 manifestNumber、thisUpdate、nextUpdate、文件名连续性与哈希检查。RFC 9981 更新了 replay 相关的 manifest number 处理,包括受控 reset 情形。这些值都不是 RRDP repository serial。

RFC 6481 描述的 publication point 结构要求 CA 材料与 manifest 保持协调,尽量不让依赖方看到中间状态。RRDP 可以提供一致时点的传输,却不能替 CA 与仓库修复错误的发布顺序。

验证器的合法性来自可复算,而不是自称权威

RFC 8897 汇集了依赖方从证书、仓库、manifest、签名材料到 router cache 所承担的基本要求。取得数据与验证数据是两项工作;即使软件拆成多个组件,运营者仍需把“哪些字节产生了哪些 Validated Payload”串成一条可检查路径。

两台验证器不一致时,不应问“谁是权威机器”,而应逐层比较 notification、delta hash、snapshot、manifest、证书/CRL、被拒文件、信任锚输入和软件版本。能复算、满足当前规则、又有安全回退的路径,才值得暂时采用。

最后一层仍属于网络运营者。RFC 6811 规定 prefix-to-origin mapping 增删改变后,受影响路由要重新验证,并按需要运行 BGP decision process;实现也必须允许本地策略匹配 validation state。运营者可以拒绝 Invalid、降低优先级、观察或设置更窄例外。RPKI 提供来源授权证据,不验证完整 AS_PATH,也不发出全球统一命令。

因此,RRDP mutation 不应直接连到不可逆的批量撤路。先从 snapshot 重建,再检查 manifest、证书与签名材料,比较 Validated Payload,确认送达路由器,观察 RIB 与 FIB,最后用多地报文和服务证据确认后果。验证器变绿,只是这条链中的一站。

资料来源