摘要

  • RFC 2784 把一个隧道数据包分成外层交付头、GRE 头与内层载荷。最小四字节 GRE 头可以声明载荷协议,却不决定隧道用途、使用资格、访问政策或安全属性。
  • Tony Li 同时共同署名 1994 年的 GRE 文档和 2000 年的 Standards Track 规范。后续 RFC 划清了运营债务:名为 Key 的字段只是流量语境标记,序号会引入状态与拒绝服务风险,IPv6 载荷则要求端点持续验证 MTU、完整性与错误反馈。

一个包拥有两套地址之后

在入口处,原数据包先变成载荷。设备在它前面加入 GRE 头,再加一层交付协议头。底层网络只需读取外层目的地址,把整套结构送到出口;出口剥去外层,再按内层目的地址继续转发。

这不是一项单纯的包装动作,而是三份互不替代的记录。交付头回答“隧道端点在哪里”;GRE 头回答“里面是什么协议、用了哪些可选行为”;载荷仍保存自己的源、目的、寿命与上层语义。外层路由可达,只证明信封能到出口,不证明内层目的可达,也不证明解封后的流量获得授权或经过了正确的安全检查。

2000 年 3 月发布的 Standards Track RFC 2784,作者是 Dino Farinacci、Tony Li、Stan Hanks、David Meyer 与 Paul Traina。它接替了 1994 年由 Hanks、Li、Farinacci 与 Traina 共同撰写的 Informational RFC 1701IETF Datatracker 的 Tony Li 档案提供人物身份、RFC 索引与冻结时点的公开职务。证据支持的是集体署名,不是单独发明、当前雇主或对实际隧道的个人控制。

真正有意义的人物线索更窄:Li 同时出现在一项通用封装的早期描述与后来缩小共同核心的规范中。GRE 的耐久性不来自替所有网络做决定,而来自拒绝把那些决定塞进共同头部。

用一只共同信封拆掉协议配对矩阵

如果每一种载荷协议跨越每一种交付协议都需要专用方法,新增协议就会扩大整个配对矩阵。RFC 2784 将问题称为 O(n²),并试图用“载荷—共同封装—交付”三层关系把它降到可管理范围。

文档没有把通用性包装成万能。它明说,为了适用于更多组合,许多协议特有细节被忽略;已有专门 X over Y 方案时,GRE 可能反而不合适。更关键的是,规范刻意不回答“何时应该封装”。它提供语法,不提供正当性。

因此,一家企业可以用 GRE 连接两个私网,一家运营商可以承载某项服务,实验室也可以运输底层暂不认识的协议;但没有哪种用途会仅因报文格式正确就自动获得授权。端点、负责人、允许载荷、容量、安全边界与退出条件,仍要由部署者逐项说明。

共同信封降低了实现与协调成本,却不会替使用者承担黑洞、泄露、审计盲区或长期依赖。谁因复用 GRE 节省成本,谁就仍然承担使用它的后果。

四字节只写下对端必须共同理解的事实

未启用可选校验和时,RFC 2784 的基础头只有两个 16 位字。第一个字包含 checksum-present 位、保留位与版本;第二个字是表示内层协议的 Protocol Type。基础格式的版本值为零。

这里没有全局隧道 ID、所有者、路线、权限、加密声明或服务承诺。它只告诉对端如何解释后面的字节。未知 Protocol Type 应被丢弃;保留位由发送方置零。若接收方没有实现旧版含义,却收到某些非零扩展位,也必须丢弃,而不是猜测布局。

启用校验和会增加四字节。它以普通 Internet checksum 覆盖 GRE 头与载荷,能发现一定范围的意外损坏,却不能证明端点身份、隐藏内容或建立权限。一个抓包若只能证明 checksum 正确,仍不能回答是谁被允许发送。

最小共同规范的价值正体现在这里:每个共同位都回答一个互操作问题;没有回答的事项,就没有被协议夺走本地决定权。

解封之后,路线重新归载荷所有

当载荷是 IPv4 时,RFC 2784 要求出口依据内层目的地址转发,并递减内层 TTL。外层目的地址完成交付任务后,不会取代载荷的路由语义。

规范也明确指出一种环路:若解封后的内层目的正是另一端封装器,数据包可能再次进入同一隧道,必须被丢弃。隧道可以隐藏一部分拓扑,却不能取消环路的因果关系。

因此,外层 traceroute 到达出口,不等于内层路径存在;隧道接口显示 up,也不等于载荷在解封后被接受。反过来,应用故障也未必源自 GRE,可能是 underlay 路由、回程、过滤或 MTU。诊断必须分别观察三层记录,再把它们连起来。

标准化过程缩小了共同头,而不是不断加功能

RFC 1701 的头部更宽:Routing、Key、Sequence、Strict Source Route 与递归控制都可能出现。RFC 2784 选择多个厂商已经共同实现的交集,把这些字段从基础规范中弃用。没有声明支持旧行为的接收方,见到对应非零位就拒绝。

这段历史不是“新版本功能更多”。共同核心反而变小,让独立实现用更少含义达成更确定的一致。可选需求可以由后续文档重新定义,而不是藏在谁都可能误读的保留位中。

兼容性因此是一条可解释的拒绝边界。两端若对扩展能力认识不同,正确修复不是宽松接收未知字节,而是确认双方能力、只启用已经约定的 profile,并保留恢复旧解析契约的回滚路径。

名为 Key,不代表它是一把安全密钥

后来由 Govindan Dommety 撰写、并非 Tony Li 署名作品的 RFC 2890,重新定义了可选 Key 与 Sequence Number。四字节 Key 用于标识端点之间的流量或语境;这个值怎样取得,不在规范范围内。

文档特别警告:尽管名称是 Key,该字段不参与安全。它可以按本地约定区分租户、服务或流量,却不会阻止能够构造 GRE 的参与者复制或伪造该数字。把它当密码,会把一枚语境标签误升格为信任边界。

Sequence Number 则带来另一类成本。它可以提供“不可靠但保序”的交付:接收方保存上一个成功解封值,丢弃更旧的值,也可用受限缓冲处理小范围乱序。对于依赖顺序的载荷有用,但每条流因此产生状态。攻击者注入一个很高的序号,可能让后续合法包都像旧包一样被丢弃。

RFC 2890 针对这种攻击要求用 IPsec AH 或 ESP 保护 GRE 头与载荷,并提醒:若高层已经保序或能够容忍乱序,就不应重复启用这一机制。一个可选位改变的是内存、缓冲、日志与攻击面,不是免费赠送的功能。

安全检查必须移动到看得见内层含义的位置

RFC 2784 认为普通路由过滤仍可沿用 IPv4 路由逻辑,但数据包过滤必须检查 GRE 内部,或在隧道端点执行。underlay 可以正确限制外层两地址之间的 GRE,却完全不知道内层协议、地址与端口。

责任常在这里断裂。传输团队说外层路线受到限制,安全团队说防火墙只允许两个端点之间的 protocol 47,服务团队便以为内层继承了两种许可。实际上,这两个外层事实都没有定义解封后哪些载荷可以进入。

可审计设计要记录内层允许前缀与协议、解封位置、哪个设备在解封前后检查、IPsec 是否认证或加密交付包。GRE up 不是安全状态。证据必须来自两层实际生效的政策,以及真正穿过它们的数据包。

IPv6 把基础规范遗漏的事项变成上线门槛

后来由 Carlos Pignataro、Ron Bonica 与 Suresh Krishnan 撰写的 RFC 7676,规定 IPv6 如何作为 GRE 载荷或交付协议。它不属于 Li 的署名记录,却能说明薄基础契约遇到新网络层以后,运营责任如何出现。

当载荷是 IPv6 时,隧道必须让一个 1280 字节 IPv6 包从入口到出口,且不分片内层载荷。入口要在激活前以及之后定期验证,不满足就停用。可用 GRE MTU 等于端点路径 MTU 减去外层交付头与 GRE 头开销。超过该值的载荷在相应条件下要被丢弃,并向源返回携带可用数值的 ICMPv6 Packet Too Big。

薄头部没有让包长问题消失,只让开销能够计算,并把测试与反馈责任交给端点。若 PTB 消息被过滤,小包和 ping 可以正常,大流量却停滞;控制面仍可能保持绿色。这是隧道最有欺骗性的故障之一。

完整性也有精确边界。关闭 GRE checksum 能减少重复计算,但 IPv6 外层头本身没有校验和,GRE checksum 即使存在也不覆盖它。RFC 7676 分析了一个概率很低却有明确后果的情形:外层目的地址损坏后,报文误达另一台 VPN PE;若两边有重叠私有地址与相符状态,载荷可能被送进错误 VPN。规范要求运营者只有在接受该风险时才部署 GRE over IPv6,并指出端到端载荷认证可作缓解。

RFC 没有证明某个生产网络一定存在这种问题。它建立的是上线前必须有人回答的问题。通用运输能力从不等于通用安全。

共同层越薄,边缘证据越要厚

Lu Heng 后来的 Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption为 Sofia Ren 提供了观察 GRE 的框架:共同层只固定布局、版本、载荷类型、可选字段和拒绝行为;每个网络保留也承担隧道理由、端点、载荷准入、安全与退役决定。

Running-Code Primacy则提高举证标准。配置对象只是意图。真实证据要把外层路线、线上 flags、Protocol Type、实际开销、Key 语境、security association、内层转发、过滤决定、MTU 反馈、计数器与应用结果连成一条链。

这些 Heng 文本是后来的编辑分析,不证明 Li 的私人意图,也不代表 RFC 之外的 IETF 共识。它们帮助划分责任:标准负责共同信封,实现负责正确解析与状态,运营者负责信封为何被允许存在。

GRE 之所以持久,正因为它拒绝统治载荷。这种克制带来了可移植性,也意味着四字节头里没有任何机构能替粗心部署收拾后果。它几乎可以承载一切;只有端点能证明它应当承载什么。

来源