摘要

  • ARIN 为每个客户 ASN 设置一个独立 ASPA,并允许资源持有人修改 Provider AS 集合。即使人的意图只是增删一家上游,系统动作仍是替换整套声明。
  • ARIN 文档分别描述了 RPKI 数据库立即生效、24 小时内进入公开仓库、仓库每隔几分钟更新,以及用独立验证器确认。它们不是同一个“成功”时刻。
  • 仍在推进中的 IETF 草案要求纳入全部提供商,包括非透明路由服务器,并区分 No Attestation 与 Not Provider+。漏掉提供商可能影响路径判断,但不能据此宣称所有相关路由都会自动无效。
  • 应当给每次修改生成一份保护隐私的差异回执,把经授权的前态、完整后态、原子事务、已发布对象和验证器观察连接起来,同时不公开合同、流量和内部拓扑。

网络变更单喜欢使用单数:新增一个转接提供商,撤下一条旧链路,启用一个备用出口。单数有利于安排工作,却会遮住 ASPA 的真实写入单位。依赖方消费的不是“新增了谁”这条指令,而是某个客户 ASN 在该时刻声明的完整提供商集合。

假设原集合是 {A, B}。一位工程师准备把它改成 {A, B, C}。在他提交之前,自动化系统已把非透明路由服务器 R 加进去,状态变成 {A, B, R}。工程师随后提交自己眼中的完整集合,R 就会消失。两次请求都可能格式正确,也都可能获得成功响应;错误来自第二个写入者依据的是过期前态。

ARIN 的产品结构已经体现了集合属性。其说明要求,一个组织若持有多个 ASN,就要为每个客户 ASN 创建独立的 ASPA 对象。在 ARIN Online 中,用户修改的是 Provider AS 集合。RPKI REST API 则用包含 customerAsId 和 providerAsIds 的 aspaDelete、aspaAdd 表达操作,并允许将 ASPA 与 ROA 放进同一个事务,全部成功或全部失败。

原子性解决了半套事务落地的问题。它不能解决整套请求已过时的问题,也不能证明对象已经被公开仓库观察,更不能证明某个依赖方已经获取并解释了新状态。一个绿色结果只回答“ARIN 是否接受了这一批操作”,并没有自动回答“互联网侧现在看见什么”。

列表界面掩盖了集合语义

管理界面把集合画成列表,是因为列表容易编辑:点一下增加一行,再点一下删除一行。人的注意力自然落在差异上。但密码学对象表达的是编辑后的状态,而不是编辑过程。

ASPA profile 的第 29 版 IETF 草案要求列出全部 Provider AS,包括非透明路由服务器。若同一客户存在多个有效 ASPA,依赖方会取它们的并集;草案同时建议避免多个对象,因为不同有效期可能带来竞态。verification 草案第 28 版也建议为客户注册一个包含全部提供商并集的 ASPA。

这两份文本目前都是 Internet-Draft,不是最终 RFC,后续仍可能变化。准确标明状态很重要。不过,它们已经清楚说明了当前工具面对的语义:声明是一个整体。遗漏一项,不是少写了一条备注,而是让完整集合表达了不同含义。

因此,安全写入的核心不应是“请添加 C”,而应是“我看到的前态哈希为 H,请把它替换成完整集合 S”。如果 H 已不再对应现态,服务就返回冲突和新集合,让人或自动化重新决策。ARIN 不需要猜 C 和 R 哪个代表真实商业关系;它只需阻止一次陈旧写入静默抹掉新变化。

这种 compare-and-set 机制会增加一点摩擦,却只在确有状态冲突时出现。与事故发生后在浏览器历史、API 日志、仓库快照和验证器缓存之间寻找旧集合相比,这点摩擦极其便宜。

“没有声明”不同于“声明中没有它”

ASPA verification 草案对缺失给出了两种不同含义。客户没有可用 ASPA 条目时,提供商授权结果是 No Attestation。提供商出现在可用集合中时是 Provider+。若可用集合存在而该提供商不在其中,则是 Not Provider+。

因此,删除 ASPA 与发布一个不包含某家提供商的非空 ASPA 不是同一动作。前者意味着没有可用声明,后者意味着已有可用集合,但它没有认可这对客户—提供商关系。只记录“修改成功”会把这个关键边界压平。

也不能从这里跨越到过度结论。完整 AS 路径验证还会考虑路径方向、分段和其他授权。草案警告,缺失提供商可能使路由后来被错误判为 ASPA Invalid;这不等于所有经过该提供商的路由都会在所有地点自动无效,更不是 ARIN 已发生此类事故的证据。

备用提供商让时间因素更明显。草案建议预先登记 standby 或 emergency provider。因为故障转移开始后再添加,ARIN 接受、仓库发布和各验证器刷新都会进入恢复时间。平时没有流量的关系恰恰容易被一次只看当前活跃链路的修改遗漏。

非透明路由服务器也容易掉出普通“上游”清单。它在商业合同中的称呼可能不是 transit,但依据草案语义,其 ASN 应进入集合。回执若只显示新增项,就无法提醒操作员确认这些安静却必要的保留成员。

一个成功提示背后有四只钟

第一只钟记录授权。谁在什么角色下看到了哪个前态,又批准了哪个完整后态。公开回执无需暴露个人姓名,可以记录授权角色类别与状态哈希;内部记录再保留更细的审批证据。

第二只钟记录事务。ARIN 何时收到、认证、校验并原子接受请求。若 ASPA 与 ROA 共用事务,回执应保存共同标识和全成全败结果,但公开层不必泄露与本文无关的前缀细节。

第三只钟记录发布。ARIN 说明修改会立即作用于其 RPKI 数据库,并在 24 小时内出现在公开 RPKI 仓库;同一页面又说仓库每隔几分钟更新。24 小时是外部上限描述,不能当作通常延迟。正确做法是记录已签发对象的哈希、仓库或 manifest 引用和首次实际观察时间。

第四只钟记录消费。验证器获取材料、验证证书链,再构造可用提供商集合。任何结果都属于某个观察点、某个软件版本和某个时间。它能证明该观察点看到了什么,不能自动证明全球依赖方已经收敛。

如果四只钟被压成“更新时间”,排障便无法判断问题落在哪个边界。可能是授权集合本就不完整,可能是提交发生冲突,可能是对象尚未被公开观察,也可能是验证器仍在使用旧缓存。每一种原因都需要不同负责人采取不同动作。

差异回执应当写什么

回执先标识客户 ASN 和签发证书或 CA 上下文。随后保存规范排序的修改前集合,或保存其哈希以及可追溯的旧对象引用。再保存完整提交集合。新增、删除和未变成员由两套完整状态计算得出;差异是解释,完整集合才是证据主体。

这条顺序十分关键。“新增 C”无法证明 B 仍在,“删除 A”也无法区分最终状态是空还是 {B, C}。只要完整状态都在,任何审计者都能重新计算差异,而不用相信界面生成的一句话。

请求部分应包括请求标识、认证主体类别、提交载荷哈希、前态比较条件、接受时间和结果。混合 ROA 事务可以只公开其关联存在与原子结果。状态冲突要明确返回,不能伪装成一般校验失败。

发布部分包括 ASPA 对象哈希、仓库或 manifest 引用,以及定义明确的监测点首次看到它的时间。验证部分包括验证器位置、软件及版本、获取时间、观察到的可用集合,以及测试路径对应的 No Attestation、Provider+ 或 Not Provider+ 变化。

回执自身也要有生命周期:被哪份回执取代、何时纠正、何时到期、回滚到哪个状态。回滚是另一项完整集合决策,不应把错误状态从历史中抹掉。保留关联,才能计算错误窗口,也才能知道纠正是否到达同一观察点。

可以在受限层标注普通 transit、非透明路由服务器和备用提供商等角色。这些标签不必写进签名对象,却能帮助审批者理解为何某个 ASN 必须留下。公共层只需呈现签名集合和必要哈希。

隐私不要求放弃谱系

ASPA 中的提供商 ASN 本来就是面向公开 RPKI 消费的声明。这不代表合同金额、流量规模、联系人、维护窗口、凭证或内部拓扑都要公开。公共回执可以只有集合、哈希、时间、角色类别和观察事实;会员侧或组织内部再保存更丰富的审批链。

验证器证据也要保持克制。写明“监测点 X 使用版本 Y 在时间 Z 观察到集合 S”是可复现事实;写成“整个互联网已更新”则超出证据。多个独立观察点能提高信心,但仍不是全局神谕。

ARIN 在 2026 年 3 月宣布 ASPA 已在 ARIN Online 全面可用。可用性不等于采用率,也不是无故障证明。ARIN 57 的公开讨论还明确区分了制度边界:ARIN 可以实现并解释 ASPA,但是否部署应由运营者决定,而不是注册管理机构下命令。

差异回执符合这条边界。它不替客户 ASN 选择提供商,也不根据 BGP 观测替客户补写关系。它只证明 ARIN 收到了哪项授权决策、该决策替换了什么、发布了什么,以及定义明确的外部观察看到了什么。

现有证据不证明 ARIN 丢失、重排、拒绝、延误或错误发布过真实集合,也没有任何具体路由被指称无效。本文讨论的是在事故之前保存控制证据。修改发生时保留前态很便宜;缓存滚动、会话结束之后再重建,既昂贵又未必可能。

工单里变的是一个提供商,签名里变的是整个集合。回执的任务,就是不让前一句话遮住后一句事实。

来源