摘要

  • RFC 875 区分了两类“网关”:普通 Internet 网关保留双方共同认可的 IP 数据报,翻译/映射网关则必须替不同的地址、确认、流控和应用语义决定对应关系。
  • 当中间设备终止两边的协议并保存这种对应时,它会成为会话状态的单点;冗余、故障恢复和任一侧的升级都需要额外设计。

一张互联图最容易省略的,不是链路,而是动词。左边的协议说“已准备好”,右边的协议也有一个近似信号,于是设计者画出一条线,称之为转换。可左边究竟是谁准备好了?右边的信号又命令谁行动?两句话字面相似,并不意味着它们报告同一件事。

M. A. Padlipsky 在 1982 年 9 月发表的 RFC 875 Gateways, Architectures, and Heffalumps,专门拆解了这种图上的便利。它不是一份供实现的标准,也不是当时翻译网关的部署普查。它是一篇尖锐的架构批评:连接两套不兼容协议的翻译/映射网关,不能被当成一个能力更强的普通 Internet 网关。

普通网关之所以“薄”,是因为共同对象足够明确

RFC 791 为互联分组交换网络定义了 IP。Internet 地址和分片机制让一个数据报可以经过分组大小、帧格式和接入方式不同的本地网络。IP 明确不承担端到端可靠性、排序和流控。

这些“不承担”构成了边界,而不是等待每台网关补齐的缺陷。网关拆掉入口网络的本地封装,根据 Internet 地址选择下一跳,再用出口网络的封装承载同一个 IP 数据报。RFC 791 甚至明确指出,高层协议不必在网关中实现。

RFC 793 把连接状态、序列号、可靠交付、窗口和紧急指示放在主机上的 TCP 中。网络层和传输层承诺不同,但每项承诺都有可以辨认的所有者。普通网关并非工作简单;它能保持边界,是因为两边同意要保留什么。

所以 RFC 875 并不反对异构网络。IP 本来就是为跨越异构本地网络而建。它反对的是把“共同细腰之下的本地差异”与“细腰之上的语义不兼容”混为一谈。帧可以更换,因为其中的 IP 数据报仍是同一对象;一侧从未表达的保证,却不能靠改字段名称得到。

NCP 地址里没有“另一个网络”这一维

Padlipsky 选择 NCP 与 TCP/IP,是因为二者足够接近,缺口反而更清楚。NCP 的主机接口在 ARPANET 自身的地址空间里识别主机;IP 地址则同时包含网络部分和主机部分。NCP 的常规会话没有位置表达“另一个网络上的这台主机”。

翻译器可以寻找空闲位、修改初始连接协议,或让应用数据夹带 Internet 地址。但无论哪一种,都改变了号称无需改变的 NCP 环境。问题不是数字长得不同,而是一侧的契约没有另一侧所需的寻址范围。

RFC 875 给出了一种更诚实的退路:让中间设备成为一台真正的主机。用户先连到它,说明希望访问的外部系统,它终止第一条连接,再发起第二条连接。Padlipsky 把它称作“Janus Host”。这种双面中继对 Telnet 等交互场景可以实用,但它不再伪装成透明的同一条连接。

RFC 801 的 NCP/TCP 过渡方案把这条边界落到了操作上。Telnet 用户先登录中继主机的专用账户,再从那里建立另一侧的 Telnet 会话;FTP 文件需要经中继移动两次;邮件又有自己的中继办法。这里没有一种万能协议翻译,只有按应用明确承担的两段关系。

缓冲区能延后决定,不能制造端到端证据

NCP 的 Ready for Next Message 由目标 IMP 发出。有翻译器时,这个“目标”可能只是翻译器旁边的 IMP,而不是另一协议世界里的最终主机。信号证明了附近边界发生的事件,却不必然证明远端接收、传输层交付或应用消费。

翻译网关可以扣住信号,把数据存进缓冲区。随后它必须回答:远端的哪个事件足以释放下一批数据?本地网络接受、远端传输接收,还是应用已经读取?如果另一套协议根本不暴露所需事实,等待更久不会让局部确认变成端到端确认。

流控也不只是速率算法。它指定谁应停下、保护哪项资源,以及什么证据允许继续。当两边把这些边界放在不同位置,中间设备便接管了矛盾。增加内存只能扩大它持有的状态,不能补出不存在的证明。

“紧急”两个字可能指向不同的行动者

NCP 在控制链路上有中断命令。TCP 有连接内的 Urgent 机制,Telnet 有 Interrupt Process,另一些协议族有加急数据。名称都像是在说“优先处理”,但它们未必要求同一个组件做同一件事。

RFC 793 对 TCP 边界的描述很具体:紧急机制应促使接收用户处理紧急信息,并维护进入和离开紧急模式的变化。让协议解释器优先工作,不等于命令目标进程中断当前任务。

若一侧没有另一侧要求的动作,翻译器就没有中性的映射。丢弃信号会损失功能;把加急交付解释成进程中断会发明权力;终止应用并执行本地策略,则至少承认决定来自中介而非原协议。

RFC 875 还提到 University College London 的一个终端网关,它连接 ARPANET Telnet 与 X.25/X.28/X.29 系列。文中报告数据可以通过,但只有回显选项跨过了边界。这个材料不能被扩大成对该系统的完整审计。它能证明的范围更窄,也更重要:字符能到达,并不等于围绕字符的选项语义也被保存。

冗余暴露了矩形内部的私有状态

假设翻译器真的解决了所有对应,它将同时保存两套连接标识、序列空间、流控状态、地址绑定、选项和应用假设。在旁边再安装一台相同设备,并不会自动把这些活的事实交给它。

RFC 875 把这种中介称作“singularity point”,即状态的奇点。分组层路由可以绕开故障链路,却无法重建翻译器私有的会话历史。真正的接管需要状态复制、冲突处理和所有权转移协议。图上的一个盒子,已经变成了分布式系统。

时间也会放大依赖。A 与 B 的翻译器不能自动解决 A 与 C;任何一侧改变地址、选项或应用行为,相关的成对翻译器都要重新检查。原本看似便捷的边界,逐步汇集了两边的发布节奏与歧义。

后来的 IP 路由器仍然需要大量适配

RFC 1009 后来把 Internet gateway 定义为 IP 层路由器。它需要处理各网络的帧、MTU、本地地址映射以及本地流控或错误指示,还要选路、管理缓冲并参与路由协议。

这不是一项微不足道的工作。不过,所有本地适配之间仍有同一个 IP 数据报。路由器不承诺把外国应用的确认重新造出来,也不必把一种协议对解释器的指令变成另一种协议对进程的命令。“薄”描述的是共同契约有清晰边界,不是设备代码少。

后来的中间设备重现了问题,而非重复同一段历史

RFC 2775 后来指出,地址翻译会破坏端到端地址透明性;在负载里携带地址的应用需要应用网关或代理理解它。每出现一种依赖地址的新应用,中间设备就可能需要新的知识。

RFC 3234 系统整理了 middlebox,既承认它们的用途,也列出新的故障面:改道后的流量可能遇到没有旧状态的设备,中间盒崩溃会影响会话,诊断需要跨多层进行。应用网关之所以保存状态,是因为它已经参与应用语义。

RFC 4966 因一组具体的技术与运维问题把 NAT-PT 移到 Historic:嵌入地址、IPv4/IPv6 语义差异、分片状态、映射寿命、DNS-ALG 扩展性,以及故障或攻击集中点。这些文档不能证明所有翻译都会失败,也不意味着 RFC 875 直接预言了每一种现代中介。它们只是重复了同一项审查纪律:不能用“改写分组”代替完整规格。

缺失的含义必须变成可见决定

审查一张互联图时,可以对每条穿过中间设备的箭头追问四件事:进入的主张是什么,出去的主张是什么,谁判定二者对应,故障后还能拿到什么证据。

若两边共享一个最小协议,网关可以在保留共同对象的同时适配本地执行。若两套协议不相容,就只能明确选择:把服务缩到交集、终止后重新发起、给端点增加新语义,或接受某项能力不能跨越。

字节到达、地址改写、终端回显,都是有价值的可观察成果。但它们不证明确认仍指向同一端点、紧急信号仍命令同一行动者、应用选项完整保留,或另一台设备能够继续原会话。网关可以承载双方已经定义的东西。任何一侧从未作出的保证,只能由某个可见的权力主体新增、降级或拒绝,不能被假装从字节中翻译出来。

来源