配置隧道把一整份 IPv6 包放进 IPv4。外层协议号是 41,外层地址是隧道两端,内层地址不变。静态隧道 MTU 应当是 1280 字节,并且不得把隧道看成 64KB 的接口。规范是 2005 年 10 月的 RFC 4213,它取代 RFC 2893。这份封装不加密载荷。
外层 IPv4 头没有选项
一个可独立引用的定义句:配置隧道的端点地址来自封装器为每条隧道保存的配置。IPv6 包送进隧道时,外层 IPv4 的目的地址是隧道终点,源地址是封装器的一个 IPv4 地址:由管理员配置,或取外出接口的地址(RFC 4213 第 3 节、第 3.5 节)。
哪些包进入隧道,通常由封装器上的路由决定。解封装器把收到的协议 41 包对到自己配置的隧道上,并且只接受 IPv4 源地址与所配置隧道相符的包。原文要求运营者保证两端的 IPv4 地址配置一致。本文不提供填写这些地址的步骤。
第 3.5 节把外层头写成没有 IPv4 选项,头长因此是 5 个 32 位字。
| 字段 | 第 3.5 节写的取值 |
|---|---|
| Version | 4 |
| 头长 | 5。封装头里没有 IPv4 选项 |
| 服务类型 | 0,除非另有规定。原文指向 RFC 2983 和 RFC 3168 第 9.1 节 |
| 总长度 | IPv6 载荷长度,再加上 IPv6 头和 IPv4 头,也就是载荷长度加常数 60 |
| 标识、分片偏移 | 按本系统发送任何 IPv4 包的方式生成;需要分片时设置 |
| DF | 按第 3.2 节。静态 MTU 时不得置位 |
| 协议 | 41。原文注为分配给 IPv6 的载荷类型号 |
| 头校验和 | 只算这个 IPv4 头 |
| 源 / 目的 | 入口的 IPv4 地址 / 隧道终点的 IPv4 地址 |
总长度用内层载荷长度加 60,是因为 IPv6 头 40 字节、无选项的 IPv4 头 20 字节,而 IPv6 载荷长度本身不含 IPv6 头。扩展头若存在,算在 IPv6 载荷长度里。原文没有把 40 和 20 分开印出。
应当能够以管理方式指定隧道的源地址。这是 SHOULD。自动选择在多地址、多接口或路由经常变化时,可能在一段时间内选出不同结果;解封装器只接受配置好的那一个源。
IP-in-IP 与 GRE 写的是另一组号码:RFC 2003 的协议号是 4,中间没有别的头;用 IPv4 投递 GRE 时协议号是 47。该文写明 RFC 2003 的头部格式不含 IPv6。2026 年 10 月 20 日没有重读 RFC 2003 和 RFC 2784,因此不把协议 41 的头字段补进那一篇。
登记表引用的是又一份文档。2026 年 10 月 20 日检索 IANA 协议号登记 的 CSV,十进制 41 的关键字是 IPv6,协议是 IPv6 encapsulation,参考文献是 RFC 2473。该 CSV 的 Last-Modified 是 2026-10-13。同日阅读的 RFC 2473 第 5 节把外层写成 IPv6:没有隧道扩展头、内层仍是 IPv6 时,下一头设为十进制 41。RFC 4213 的外层是 IPv4,协议字段同样写 41。同一个号码,外层版本不同。2026 年 10 月 20 日没有重读 RFC 2473 的解封装,因此不把下面的 IPv4 源地址核对写成那一份的规则。
静态 MTU 应当是 1280
一个可独立引用的定义句:封装器不得把隧道当成 MTU 为 64KB 的接口。它必须改用固定的静态 MTU,或者使用可选的、基于到隧道终点的 IPv4 路径 MTU 的动态确定。把隧道当成约 65535 减 20 字节的链路,是必须不得使用的做法(RFC 4213 第 3.2 节)。
静态方案把隧道接口看成固定 MTU。默认值必须落在 1280 到 1480 字节之间,含两端,但应当是 1280 字节。若默认不是 1280,实现必须有一个能改这个值的配置旋钮。使用静态 MTU 时,封装用的 IPv4 头不得设置 DF。原文因此说,封装器不应因为自己封装出去的包而收到 ICMPv4「包太大」。
更大的固定 MTU,若超过第 3.6 节那些重组和接收要求所能支持的范围,就不得配置,除非已经用管理手段确认解封装器能够重组或接收那个尺寸。这句原文是小写 must not。
动态确定是可选的。若实现了,应当具有第 3.2.2 节描述的行为。IPv6 层把隧道看成一条链路,其 MTU 等于 IPv4 路径 MTU 减去封装用的 IPv4 头长。该节把这个头长按 20 字节用于下面的判断:
| 条件 | 包长 | 动作 |
|---|---|---|
| IPv4 路径 MTU 减 20 小于 1280 | 包大于 1280 | 发送 ICMPv6「包太大」,MTU 填 1280,并丢弃 |
| 同上 | 包不大于 1280 | 封装,但不置 DF。IPv4 层或路径上的路由器可能再分片 |
| IPv4 路径 MTU 减 20 不小于 1280 | 包大于该差值 | 发送 ICMPv6「包太大」,MTU 填这个差值,并丢弃 |
| 同上 | 包不大于该差值 | 封装,并设置 DF |
IPv6 要求每条链路的 MTU 至少 1280 八位组。RFC 4213 把这句话引向 RFC 2460。2026 年 10 月 20 日在 RFC 8200 第 5 节看到同样的最低链路 MTU,没有重读整份 RFC 8200,因此不把 RFC 2460 的其他句子改写成 8200 的条文。
动态方案依赖路径上的 ICMPv4「包太大」。该节注明,防火墙丢掉这些消息或路由器不产生它们时,会出现 IPv4 路径 MTU 黑洞。它引用 RFC 1435 和 RFC 2923。2026 年 10 月 20 日没有重读这两份。路径 MTU 探包 讨论的是少依赖这条 ICMP 的另一套方法。本文不把两套探法合成一步。分片在哪一层重组,见 IP 分片。
差分服务标记 讨论的是服务类型字节后来的读法。第 3.5 节仍把这个字节默认写成 0,除非另有规定。2026 年 10 月 20 日没有重读 RFC 2983 和 RFC 3168 第 9.1 节,因此不把「默认写 0」改写成必须复制或必须清除 DSCP。
解封装先核对源地址
一个可独立引用的定义句:解封装器在进一步处理之前,必须验证隧道源地址是正确的。做法是核对源地址是否为解封装器上配置的封装器 IPv4 地址。源地址不符的包必须丢弃,并且不应当产生 ICMP;若实现平时会对未知协议回显错误,则可以发送,例如 ICMPv4 的协议 41 不可达(RFC 4213 第 3.6 节)。
这条核对也适用于交给本机传输协议的包。副作用是:错误源地址,以及不是直接发给本节点的包(例如广播),会被静默丢弃。
独立于管理员可能已经配置的其他 IPv4 入口过滤,实现还可以做严格反向路径一类的检查。若做了,建议默认关闭,因为隧道可能经过多条链路。被这条检查抓住的包应当丢弃,默认不应当产生 ICMP。
重组发生在解封装之前。解封装器必须能够重组这样一个 IPv4 包:重组之后的长度是 1500 字节和本机最大 IPv4 接口 MTU 二者中的较大者。隧道接口上的 IPv6 最大接收单元,必须至少是 1500 字节和本机最大 IPv6 接口 MTU 二者中的较大者。实现可以配置更大的重组缓冲,但不得把它设到上述数目以下。
解封装时不修改 IPv6 头。随后若再转发,跳数减一。IPv4 头被丢弃。重建 IPv6 包时,长度必须取自 IPv6 载荷长度,因为 IPv4 包可能有填充,从而长于「IPv6 包加上被去掉的 IPv4 头」。
交给 IPv6 层之后,节点必须静默丢弃 IPv6 源地址无效的包。应当至少包括:全部多播地址 FF00::/8、环回 ::1、全部 IPv4 兼容 IPv6 地址 ::/96(不含重复地址检测用的未指定地址 ::/128),以及全部 IPv4 映射地址 ::ffff:0:0/96。这份清单引用 RFC 3513。2026 年 10 月 20 日没有重读后来的地址架构是否改写「兼容地址」的定义,因此不把清单改成另一份 RFC 的表。
从 IPv6 看,隧道是一跳
一个可独立引用的定义句:IPv6-over-IPv4 隧道在 IPv6 看来是单跳。封装器和解封装器在转发 IPv6 包时把跳数减一,如同转发到任何其他数据链路。始发节点和最终目的地不减(RFC 4213 第 3.3 节)。
外层 IPv4 的 TTL 由实现选择。原文说当前建议值发布在 Assigned Numbers RFC(RFC 3232),实现可以按 IP Tunnel MIB(RFC 4087)提供管理员配置。2026 年 10 月 20 日没有重读 RFC 3232,因此不写一个具体的 TTL 数字。路由跟踪 能看到的是外层这一跳,看不到隧道里面的 IPv6 转发跳。这是第 3.3 节「诊断工具察觉不到」的同一句话,不是对某一 traceroute 实现的测量。
配置隧道是 IPv6 接口,因此必须有链路本地地址。接口标识可以基于底层接口的 32 位 IPv4 地址,也可以用别的办法,只要相对另一端有相当高的概率唯一。若用 IPv4 地址来构成,接口标识就是这个 IPv4 地址,前面补 0;链路本地地址是把该接口标识接在 FE80::/64 之后。原文注明,此时 Universal/Local 位为 0,表示接口标识不是全球唯一的。图示是 FE80::/64 后面 32 位 0,再跟上 32 位 IPv4 地址。
邻居不可达检测的探针,实现必须至少接受并回应。实现也应当发送这种探针,以便发现配置隧道失败。邻居发现允许在路由器到路由器的链路上省略发送,如果路由协议已经跟踪双向可达。就邻居发现而言,这种隧道被假定没有链路层地址,尽管作为链路层的 IPv4 其实有地址。因此发送方不应当在隧道链路上放入源或目标链路层地址选项;接收方在其他方面照常处理时,必须静默忽略这些选项的内容。一般的邻居发现报文见 邻居发现与 ARP。2026 年 10 月 20 日没有重读 RFC 4213 所引的 RFC 2461,因此不把该文的跳数检查改写成本节的新规则。
同一份 RFC 还规定了双栈。地址如何在两个版本之间挑选,不在第 3 节的封装字段里,见 源地址选择。
2026 年 10 月 20 日查阅的 RFC 元数据把状态标成 PROPOSED STANDARD,写明它取代 RFC 2893,没有把它标成已被取代,updated_by 为空。同日的 勘误 只有 2172 一条,状态为 Held for Document Update,类型为编辑性,改的是第 4 节一个冠词,不改协议号、MTU 或源地址核对。本文不把它写进上面的规则。
核对清单
- 协议字段是 41,外层是 IPv4:头长为 5,总长度为 IPv6 载荷长度加 60。登记表把参考文献写成 RFC 2473,那一份的外层是 IPv6;
- 不得当成 64KB 接口:静态 MTU 应当是 1280,且必须落在 1280 到 1480。静态时不得置 DF。动态方案可选;
- 先核对再拆:IPv4 源地址必须是配置中的封装器,否则必须丢弃,并且不应当回 ICMP。长度取 IPv6 载荷长度,因为 IPv4 可能有填充;
- IPv6 看是一跳:转发时内层跳数减一。外层 TTL 的建议值在 RFC 3232,本文没有重读,不写具体数字;
- 必须有链路本地地址:用 IPv4 地址构成时,接口标识是 32 位 0 再加该地址,前缀是
FE80::/64。本文不提供建立这种隧道的步骤。