跳转到内容

Cerf-Kahn 1974 — 用网关把异构网络拼成一个互联网

是什么

Cerf-Kahn 1974 是 TCP/IP 体系的起点论文——把”几个互不相通的分组网”变成”一个互联网”的原始设计图。两位作者后来因这篇文章和后续工作拿到 2004 年图灵奖。

日常类比:1974 年的局面像几个国家各自有自己的邮政系统——美国邮政有美国地址格式、信封大小、签收规则;法国邮政完全另一套;卫星邮局又是第三套。寄一封信从一国到另一国,要么不可能,要么走人肉转交。Cerf 与 Kahn 提出:在每两国边境放一个翻译柜台(gateway),统一信封外面再套一层”国际通用信封”,柜台读外层就够了,不用懂内部规矩。这层国际信封 + 端到端可靠协议,就是后来的 TCP/IP。

论文里描述的是单一协议 TCP(Transmission Control Program)—— 把”互联网寻址”和”端到端可靠性”放在一起。1978 年前后这一坨被拆成两层:IP 管寻址和路由TCP 管可靠流

为什么重要

不理解这篇论文,下面这些事都没法解释:

  • 为什么今天 ISP 之间互联只用一种协议(IP),而不是每对网络两两定制——Cerf-Kahn 给的答案是”统一外层信封 + 边界网关”
  • 为什么 IPv4 包头有那么多看似冗余的字段(fragmentation、TTL、checksum)——它们都对应论文里要解决的具体异构难题
  • 为什么 TCP 在 tcp RFC 793 里能假设”下面有一层会尽力把包送到目的地”——因为 IP 那层已经被这篇论文先想清楚了
  • 为什么互联网协议栈是”端到端可靠 + 中间尽力”,而不是”中间也保证可靠”——这是一个 1974 年就做出的工程取舍
  • 为什么 NAT、VPN、CDN 这些”看似在打破抽象”的东西能存在——因为 1974 留的接口允许中间盒子在某些层做特殊处理

核心要点

论文要解决的是一个具体问题:1973 年时全球已经有 ARPANET(美国本土主干,固定线路)、Packet Radio(无线,丢包高)、SATNET(卫星,长延迟),三个网各自有协议、地址、包大小。论文把跨网通信拆成 三件事

  1. 网关做边界翻译:在两个网络之间放 gateway,对外说统一的 internetwork 包头,对内翻译成各自子网的格式(地址、包大小、错误码)。类比:海关报关,外层用国际单据,内层各国自己玩。子网完全不用为了互联改造内部协议。

  2. 统一的 internetwork 包头:每个跨网包外层套一份固定字段——源/目的全局地址、序号、长度、校验。网关只读这层就能转发。类比:所有国际邮件都贴同一种地址条,柜员不需要懂里面写的什么语言。

  3. 端到端可靠性放主机,不放网关:丢包重传、顺序、流量控制是收发双方主机的事,网关只管转发不管可靠。类比:邮局只负责送,“信里少了一页” 是寄收双方对账的事,邮局不背这锅。这条决定后来叫 end-to-end argument,是互联网架构的灵魂。

三件事合起来:异构网络从此能拼成”一个网”,而且这个网可以无限长大——加一个新网络只要加一个网关,不要全网改协议。

实践案例

案例 1:今天的 IP 路由器就是论文里的 gateway

你家路由器从光猫拿到一个 IPv4 包,目的地是 8.8.8.8。它读 IP 头(外层信封),决定下一跳,把包丢出去。它不读 TCP 段里的内容,也不知道这是 HTTP 还是 SSH。这就是 1974 论文里 gateway 的现代化身——边界翻译 + 只看外层 + 不掺和可靠性

差别在于规模:论文里讨论的是几个网关连几个网络,今天全球有几十万个 BGP 自治系统、几百万台 IP 路由器,遵循的还是同一套抽象。这种”小规模设计能直接放大几个数量级”的特性极少见,是论文设计稳得住的核心证据。

案例 2:分片为什么要在目的主机重组

不同子网 MTU 不一样:以太网 1500 字节,早期 ARPANET 1008 字节,卫星网更小。一个大包过网关时可能要切几片。论文选了一个反直觉的方案:网关只切不拼,目的主机负责重组

源主机 ─[4000B]→ 网关A ─[切成 1500/1500/1000]→ 网关B ─→ 目的主机[重组回 4000B]

为什么不让中间网关重组?因为多片可能走不同路径到达,强制中间重组会要求所有片汇聚到同一个网关——这违背了”无状态尽力转发”的设计。代价是丢一片整个包白发,但换来网关可以无状态、便宜、并行。

案例 3:进程级寻址 = 端口

论文已经看到一件事:一台主机上跑着多个进程,“主机到主机”还不够,得”进程到进程”。它的解法是在 TCP 层加一个 port 字段——主机地址定到机器,端口定到进程。今天你写:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('0.0.0.0', 8080))

这个 8080 就是 1974 论文发明的概念。HTTP 默认 80、SSH 默认 22、PostgreSQL 默认 5432,源头都在这里。

案例 4:从论文设计到 IP 头字段的对照

打开 Wireshark 抓一个 IPv4 包,前 20 字节里能逐字段对应到论文里的设计意图:

字段论文里要解决的问题
Source / Destination Address跨网全局寻址(论文里叫 “internetwork address”)
Total Length不同子网包大小不同,需要显式长度
Identification + Flags + Fragment Offset分片重组,目的主机靠这三个字段拼回原包
TTL防止包在路由环里无限循环(论文里叫 “lifetime”)
Header Checksum子网内层校验不可信,外层独立校一遍

每一个字段都是 1974 年某个具体痛点的工程化答案——这就是为什么 IPv4 头看着复杂却几乎没有冗余。

踩过的坑

  1. 分片重组位置之争:论文里”目的主机重组”是反复辩论后定的。后来在 IPv6 里更激进——中间网关根本不允许分片,源主机自己做 Path MTU Discovery 提前切好。原因:分片是性能黑洞,丢一片重发整个包,攻击者还能用大量小片吃光重组缓冲。

  2. 流量控制窗口难调:论文给了基于窗口的流量控制,但没解决”RTT 怎么估”。1988 年 Jacobson 才用 SRTT + RTTVAR 算 RTO,在此之前互联网经历过几次大规模 congestion-collapse-1986——窗口设错,重传雪崩。

  3. 序列号回绕与延迟重复:32-bit 序列号在万兆网下大概几秒就回绕一圈;老的延迟到达副本可能撞上新连接。论文最初的两次握手不够鲁棒,后来才演化成三次握手 + ISN 随机化 + TIME_WAIT 等待 2MSL。

  4. 网关被假设”基本可信”:论文把网关当成基础设施,没想 BGP 劫持、源地址伪造这些攻击。今天互联网安全大半工作是在补这层洞——RPKI 给路由签名、BGPsec 验源,思路都是给 1974 设计补可信边界。

  5. 地址空间设计偏小:论文给 internetwork 地址留的位数有限,演化到 IPv4 是 32-bit 共 43 亿地址——1974 时代谁能想到全球会有几十亿台联网设备。NAT、CIDR、IPv6 都是后来给这个洞打补丁,IPv6 部署到今天还没超过半数。

适用 vs 不适用场景

适用

  • 异构子网互联(这正是 1974 要解决的)
  • 大规模、动态拓扑、节点不可控的场景——网关只转发不维状态
  • 上层愿意承担可靠性(TCP)或不需要可靠性(UDP)的应用
  • 需要”加新子网不改全网”的可演进场景

不适用

  • 需要中间节点保证可靠性的场景(ATM 试过,输了)
  • 严格实时、可预测延迟的工业控制网(用 PROFINET、TSN 这类专网)
  • 单一 owner、可统一改造的数据中心网(RDMA/RoCE 不走这套抽象)
  • 需要按内容计费/审计的网络(中间节点要拆开包看,与 end-to-end 哲学冲突)

历史小故事(可跳过)

  • 1973 年:Cerf 在 Stanford 教书,Kahn 在 DARPA,两人在斯坦福一间咖啡馆和 Cerf 家车库讨论几个月。当时 ARPANET 用 NCP 协议,不能跨网。
  • 1974 年 5 月:论文发表于 IEEE Transactions on Communications。原文里 TCP 是单一协议,包含今天 TCP + IP 的全部职责。
  • 1977 年 11 月:第一次三网联合演示——一个包从 SF Bay 区上车,经卫星到挪威,再回 USC 南加大,全程 94000 英里 0 丢包,证明跨网真的能跑通。
  • 1978 年前后:在多次实验(包括语音实验、卫星网测试)中发现”可靠流”和”尽力投递”应该分开——有些应用(实时语音)不要可靠,只要快。TCP 拆成 TCP + IP 两层,IP 单独可用就成了 UDP 的基础。
  • 1981 年:IPv4 标准化为 RFC 791,TCP 标准化为 RFC 793,由 Jon Postel 编辑。
  • 1983 年 1 月 1 日:ARPANET 完成 NCP → TCP/IP 的 “flag day” 切换。这是历史上最大规模的协议迁移之一。
  • 2004 年:Cerf 和 Kahn 共获 Turing Award,颁奖词:“For pioneering work on internetworking, including the design and implementation of the Internet’s basic communications protocols, TCP/IP, and for inspired leadership in networking.”

学到什么

  1. 抽象的位置决定生态:把”互联网寻址”放进网关、把”可靠性”放进主机,这一刀切对了,互联网才能长这么大。切错的反例就是 ATM——把太多东西塞进交换机,最后被 IP 干掉。
  2. end-to-end argument 是 1974 就埋下的种子——可靠性、安全性、应用语义,能放端就放端,中间只做不得不做的事。
  3. 协议设计要为”未知未来”留位:包头里 TTL、Protocol、Options 这些字段,是给 1974 还没出现的需求留的口子。后来的 NAT、IPsec、ECN 全是从这些字段缝里长出来的。
  4. 理论 → 工程 → 标准 → 全球部署,从 1974 论文到 1983 切换用了 9 年,到全球商用 Web 又过了 10 年。互联网的”快”是站在这 20 年慢工上的。
  5. “先单一、后分层”是常见的协议演化路径——TCP 最初一个协议干两件事,跑了几年发现不够用,才拆成 TCP+IP。真实工程里很少能一次想清楚正确分层,能允许后期拆分的设计更耐久。

延伸阅读

给初学者的读法建议

第一次读这篇论文不要逐行硬啃数学定义。先看图 1(gateway 拓扑图)和第 4 章的包格式,这两处把核心思想画清楚了;其余章节是把每个细节填实。读完后回头看 tcp RFC 793,会发现 RFC 几乎是这篇论文工程化版本的逐节展开——同一个人(Cerf)后来还参与了 RFC 793 的最终定稿。

关联

  • tcp —— 论文里 TCP 拆出来的传输层,今天大部分应用直接用的就是它
  • quic —— 用 UDP 重造 TCP,是对 1974 设计的一次”另起炉灶”实验
  • http-2 —— 跑在 TCP 上的应用层多路复用,撞上 TCP head-of-line 后催生 QUIC
  • [[tls-1.3]] —— 在 TCP 之上加一层端到端加密,仍然遵循 end-to-end 原则
  • dns —— 给 IP 地址起名字的服务,1974 论文只解决数字寻址,名字是后来的事
  • shannon-1948 —— 信息论奠基,物理层和分组网的共同祖先
  • ntp-mills-1991 —— 跑在 IP 之上的时间同步协议,依赖网关尽力转发的特性

反向链接

  • dns —— DNS — 把全球域名解析切成一棵可分布维护的树
  • http-2 —— HTTP/2 — 把 HTTP 从文本协议改造成二进制多路复用
  • jacobson-1988 —— Jacobson 1988 — 让互联网不再被自己塞死
  • ntp-mills-1991 —— NTP 1991 — 用四个时间戳和一组滤波器,让全网服务器的钟差几毫秒
  • quic —— QUIC — 把可靠传输从内核搬到用户空间
  • rtp-rfc-1889 —— RTP RFC 1889 — 让 UDP 也能跑实时音视频
  • shannon-1948 —— Shannon 1948 — 信息论的诞生
  • tcp —— TCP — 在不可靠的 IP 上凿出一条 reliable 字节流