摘要

  • Usenet 的取消本身也是一篇控制文章,通过新闻分发机制传播,以 Message-ID 指定目标,却没有中心节点替所有副本执行撤回。
  • 每个 serving agent 都按本地规则授权;请求可以被执行、忽略,也可以在原文到达前形成一条预取消记录。
  • 后来的 Cancel-Lock/Cancel-Key 把撤回凭证预先承诺在原文中,但它不证明全文完整或现实身份,也不迫使站点与档案删除副本。

三个服务器看见了三种事实

取消请求到达第一个服务器时,目标文章已经躺在 spool 中。管理员认可请求,读者随后看不到它。第二个服务器收到相同字节,却认为验证不足,什么也没改。第三个服务器先收到取消,原文仍在传播途中;它若只检查当前存储,就会得出“无事可做”,数小时后却把迟到的文章重新接纳。

三个结果都符合分布式新闻系统的基本现实:共享消息格式,不等于共享状态;能够送达请求,不等于拥有远端存储的执行权。

RFC 850 在 1983 年已经把控制消息放进普通 USENET 消息所用的分发机制。它没有规定所有站点必须自动执行,还允许实现者或管理员把控制消息排队交给人处理。取消因此不是从中央数据库撤销一条记录,而是一篇“关于另一篇文章应如何处理的新闻”。

这项安排看似绕远,却保留了 Usenet 的联邦结构。站点可以交换文章,同时继续掌握本地空间、审查风险和运维政策。协议协调请求的语法与目标,不能凭空创造对所有副本的管辖权。

Message-ID 能指出对象,不能证明来者是谁

早期语法 cancel <message ID> 解决了分散副本的指代问题。同一篇逻辑文章在不同机器上可能有不同路径和到达顺序,Message-ID 仍让请求明确指向它。RFC 1036 在 1987 年保留了这种本地取消,还规定不能执行取消的系统不应继续向邻居转发请求。

稳定标识符回答“要撤回什么”,却没有回答“谁有权撤回”。早期规则允许作者或本地超级用户操作,并比较控制文章与目标文章的 Sender 或 From。协作环境中,这种比较可以挡住一部分误操作;从安全角度看,它只是比较可复制的字段。任何人能写出相同字符串,并不等于原作者授权。

RFC 5537 后来明确删掉这项强制比较:它不能提供安全性,还可能鼓励隐藏信息。标准也没有用一个全球身份服务取而代之。站点可以使用本地、非标准或人工方法判断,且从未被要求一定对控制文章采取行动。

这段演进的价值,不是“新标准终于解决了身份”,而是停止把表头相等伪装成认证。Usenet 公开承认权限归属本地,也因此公开承认同一取消会产生不同结果。

预取消是对“尚不存在”的本地记忆

传播路径不同,事件就可能倒序。控制文章也许先穿过快速链路,原文仍在队列中。若服务器收到 cancel 时只尝试删除当前对象,请求完成后不留下痕迹,迟到副本就会像从未被撤回一样出现。

RFC 5537 允许 serving agent 记下目标 Message-ID;当原文稍后到达时直接拒绝。预取消记录是一种小型 tombstone:它保存的不是文章内容,而是一条关于缺席对象的负面状态。

它只能防止本地复活。另一站可能没收到 cancel,可能过早清理记录,也可能选择不采用预取消。让控制文章使用与原文相近的 Newsgroups,有助于覆盖相同服务器,却不能保证两次传播的集合完全一致。若涉及受管理组,Approved 字段还会引入该社区自己的门槛。

Supersedes 同样没有全局捷径。RFC 5536 定义这项指向旧文章的字段,RFC 5537 则要求按 cancel 的授权规则处理其撤回效果。新版本的存在只能表达“希望替代哪个 Message-ID”,本身并不是所有站点都承认的所有权证明。

自动取消把控制面变成攻击面

能够让另一篇文章消失的消息,对纠错者和攻击者同样有吸引力。伪造 cancel 可以压制正常内容;大范围自动取消能对付垃圾信息,也能越过不同社区的政策边界。

RFC 2635 记录了 cancelbot 对重复或大规模跨组发布的应对。这说明垃圾内容推动了运维自动化,但没有赋予任何 bot 全网权限。它发出的仍然是请求,落地仍由接收站点决定。

RFC 5537 也记录了现实后果:鉴权困难且曾遭滥用,不少站点干脆忽略 cancel 与 Supersedes。自动执行提高伪造的破坏力;全部拒绝又损失合法纠错和反滥用能力。开放联邦没有一条语法能消灭这种权衡。

锁先写进原文,钥匙后来才公开

RFC 8315 在 2018 年给出一项范围更窄的密码学机制。原始 proto-article 可以带 Cancel-Lock:它由秘密材料计算出的哈希构成,却不公开秘密。日后的 cancel 或含 Supersedes 的文章提交 Cancel-Key。参与的 agent 处理钥匙后,与原文里已存在的锁匹配。

关键不是名称像锁与钥匙,而是时间顺序。撤回能力在文章进入系统时就完成预承诺,不能等争议发生后只靠复制 From 临时制造。作者、posting agent、moderator 或 injecting agent 都可以拥有各自的锁;注入之后的 relay 不得改写它们。多个锁并存时,掌握其中一个合法秘密即可按验证流程批准撤回。

这份证明只回答一个精确问题:请求者是否展示了与原文某项撤回承诺相匹配的知识。RFC 8315 明确说它不保证整篇文章的完整性,其他内容仍可能被改动。它不证明现实世界身份,不要求本地站点执行,更不触及不参与机制的档案或服务器。

IANA Netnews 参数注册表 记录算法名称与用途状态。RFC 8315 要求 SHA-256;注册表还列有 SHA-512,以及已经 obsolete 的 MD5 和 limited-use 的 SHA-1。注册解决互操作命名,并不证明今天部署多少、撤回成功率多高。

“已撤回”的可信范围只能到执行者为止

完整流程至少包含五项记录:有人创建请求;请求指定 Message-ID;某站点收到请求;站点接受或拒绝证据;站点改变或保留本地可用状态。任何一项都不能代替其余四项。

Cancel-Key 验证通过,只说明这个参与者看见了与原锁匹配的撤回授权。服务器不再提供本地副本,只说明它控制的存储已改变。其他 peer、网关、档案和读者保存的副本仍在权限之外。开放协议中的 Archive 或 Distribution 请求字段,也无法强迫所有保管者服从。

所以,Usenet 留下的不是一个失败的“全网撤销”按钮,而是一套诚实的边界:标识符定位对象,控制文章传播意图,证据支持授权,本地政策分配执行,副本持有者决定保留。若产品只显示“撤回成功”,它应当继续回答:哪个请求、谁验证、哪些副本、还有哪些地方无法触及。

来源