摘要
- 1994 年的 RFC 1701 说,接收方“可以”用 4 字节 Key 认证来源,却没有规定值如何产生、交换、保护和验证。
- 2000 年的 RFC 2890 明确把 Key 定位为隧道内的逻辑流标识,并直说它虽名为 Key,却不参与任何安全机制;Sequence 只提供不可靠但有序的交付。
- 未受保护的攻击者可以注入任意 Sequence 值,抢先推进接收状态,让随后到达的合法报文被当成旧包丢弃。分类与排序要可信,必须另有机制同时保护 GRE 头和载荷。
名字先到了,权限却没有
看到 Key,人们很容易想到密码、凭据或开锁动作。协议字段一旦借用了这个词,运维规则往往会在不知不觉中给它添加权力:数值对上了,就认为对端可信;隧道能通,就认为报文受到保护。
RFC 1701 留下了一份很适合检验这种直觉的历史记录。1994 年,它用 GRE 解决“某种网络层协议如何装进另一种网络层协议”的通用问题。外层 delivery header 负责运送,中间是 GRE header,里面才是 payload。GRE 头可以携带校验和、路由信息、Key 与 Sequence Number。
文件说,4 字节 Key 可以由接收方用来认证报文来源,但认证技术不在本文范围内。这不是一套缺少参数的成熟方案,而是整段机制都没有定义:谁分配 Key,怎样绑定端点,如何防复制,何时失效,谁保护字段不被改动,验证失败又该如何处理,都没有答案。
Sequence 也停留在同一层。它可以帮助接收方确定发送顺序,但计数方法与接收语义都留给外部。报文格式留出了位置,互操作状态机却还不存在。
RFC 2784 先把共同部分缩小
2000 年 3 月的 RFC 2784 没有继续扩张这两个字段的含义。它选择记录多家厂商已部署 GRE 的交集,把一个较小的头部推上标准轨道。基础格式保留 Checksum present、Version 和 Protocol Type。Protocol Type 告诉解封装端里面装的是什么协议,却不决定什么流量有资格进入隧道。
旧版中的可选位被当成清晰的兼容边界。只实现 RFC 2784 的发送方把保留位写零;接收方若看到第 1 至 5 位非零,而自己又不实现 RFC 1701,就必须丢包。文件还单独说明新旧实现如何互通,没有假装早期格式从未存在。
这一步的价值在于拒绝猜测。接收方不能因为对端是熟悉的设备、地址在白名单中,或配置界面写着“GRE”,就自行推断那些位的语义。共同层只保留运行代码能够共同执行的规则。
Key 的价值来自降权
同年 9 月,RFC 2890 更新了基础规范。K 位表示后面有 4 字节 Key,S 位表示后面有 4 字节 Sequence Number,位置与 RFC 1701 兼容。但这一次,中心职责写清楚了。
Key 由封装端插入,取得这个数的方法仍不在 RFC 范围内。接收端用它在同一隧道中识别一股逻辑流。当内层报文本身没有足够的上下文,而解封装端需要据此选择路由或本地处理时,这个小数值就能补上分类信息。属于同一流的报文使用同一个 Key。
这是本地语境,不是全局身份。同一个四字节值只有放在特定外层端点、隧道配置和本地映射中才有意义。它不说明谁拥有这股流,也不说明封装者为什么有权选择它。任何能构造报文的人都能抄一个数。
RFC 2890 在安全章节把边界说到无法误读:Key 虽然叫 Key,却不参与任何形式的安全。历史修正没有改名,而是取消了名字可能暗示的权威。
Sequence 建立的是接收方记忆
S 位让顺序终于成为可执行规则。封装端从 0 开始递增,用 32 位无符号计数器并按 2^32 取模回绕。解封装端保存“最后一个成功解封装报文”的序号。若同时存在 K,这份记忆属于该 Key 所标识的流。
恰好前进一步的报文可以继续交付。明显落后的值被视为乱序旧包,应静默丢弃。前方有缺口时,接收端可以使用小型、按流划分的缓冲区,短暂等待丢失或迟到的报文;时间或容量用尽后,也可以跳过缺口,把已有报文按新的顺序交付。
标准把结果称为“不可靠但有序”。不可靠不是附带的小字。Sequence 不会重传缺失载荷,也不承诺每个编号都会到达。缓冲只是在“再等一下”和“承认缺口”之间做有限选择。
它也没有给整条隧道建立一个总时序。不带 S 的报文可以穿插其中;不同 Key 有各自的计数历史。因此,一个报文“更新”只表示它在选定逻辑流与接收状态中更新,不表示它比链路上所有 GRE 报文都新。
伪造一个未来,就能淘汰真实的现在
假设接收方最后接受了序号 40。攻击者复制正确的外层地址与 Key,却填入一个远在前方的 Sequence。如果 GRE 头没有受外部完整性保护,接收方可能先把这份伪造的未来写进自己的记忆。随后到达的合法报文全都显得过旧,被排序规则逐一丢弃。
RFC 2890 明确把任意序号注入列为拒绝服务风险,并要求用 GRE 之外的 IP 安全机制保护 GRE 头和隧道载荷。重点不是算法名字,而是保护范围:驱动流分类与接收状态的字段必须一同被认证。
因此,Sequence 不是天然的防重放。只有先证明报文属于一个受保护的安全关联,后续序号窗口才有可信输入。没有认证,攻击者可以替接收方书写那本用来审判合法报文的账。
加密同样是另一项职责。Key 不保密载荷,S 也不隐藏流量模式。实际部署可以选择只做完整性,也可以再提供机密性;K/S 本身没有替运营者作出这个决定。
后来的更新没有把 Key 变大
RFC 2784 的另一项正式更新来自 2024 年 RFC 9601。它讨论 GRE 作为 IP 头之间的 shim 时,内外层应如何传播 ECN,并给使用 IPv4 或 IPv6 外层的入口增加安全配置义务。
这与 RFC 2890 的职责彼此正交。ECN 传递拥塞信息,Key 选择逻辑流,Sequence 维护该流的接收顺序,外部保护层负责来源与完整性。一个隧道可以同时需要四者,但不能把其中一个字段的意义借给另一个。
RFC 9601 还提醒,GRE 本身没有动态建立和配置隧道的机制。静态配置或其他控制协议可以创建关系。抓包能看到 Key 与 Sequence,却无法单凭这些字节还原谁分配了 Key、谁授权了端点,或控制面为何把该值映射到某股业务。
运行代码应该回答什么
审计不能止于“Key 是否相同”。还要问:这个数属于哪一对外层端点与哪一个命名空间;本地把它映射到什么流;此处是否必须带 S;最后接受的序号是什么;缺口、回绕与重启如何处理;以及 GRE 头是否真的落在认证保护范围内。
乱序丢弃计数上涨也不是攻击结论。原因可能是网络重排、重复包、缓冲不足、端点重启、两端配置分歧或恶意注入。计数器证明接收方执行了什么判断,不会自动证明为什么。
RFC 2890 最耐久的贡献,是让两个听起来很强的字段只承担可验证的小任务。Key 提供上下文,Sequence 提供局部顺序,安全则必须由能真正验证来源和完整性的机制负责。字段的名字没有运行权力,接收方实际执行的验证才有。
来源
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
