ICMP 重定向与 VPN 路由:究竟改变了什么
重定向是路由器的建议,而不是路由变更。主机是否照做,取决于 IPv4 与 IPv6 各不相同的按接口策略。
一条本应走隧道的流量选了不同的下一跳,有人在抓包里发现了 ICMP 重定向。这是假设,不是结论。重定向是路由器关于更优下一跳的建议,主机是否照做,取决于因平台、接口和地址族而异的设置。
重定向只是路由器给出的建议
IPv4 的 ICMP 重定向有自己的报文类型和很窄的触发条件:路由器把数据包从它进来的那个接口再发出去,并且知道同一条链路上有一个更接近目的地的下一跳。随后它告诉发送方直接使用那个下一跳。报文会写出新的网关,并附带原数据包的一部分,以便发送方把它与某条流量对应起来。这是一条关于本地拓扑的礼貌性通知,并且假定发送方与建议的网关在同一条链路上。
发送方完全可以无视它。协议并不要求主机改表,抓到一条重定向只能证明某个路由器发过它。
大多数重定向排查出错,就出在这个区别上。
IPv4 与 IPv6 的投递方式不同
IPv6 的类似机制位于邻居发现之中,而不是 ICMPv4 里,报文格式和校验规则都不一样。概念相似,报文不同。为 ICMP 类型 5 写的抓包过滤器在 IPv6 网络里什么都看不到,有时这被误读成没有发生重定向的证据。
策略开关也是分开的,因此主机可以接受 IPv4 的重定向而忽略 IPv6 的,反之亦然。
如果涉及的流量可能走任意一族,两族都要检查。
是否接受是主机策略,不是网络事实
在 Linux 上,重定向的接受行为按接口和全局分别控制,默认值在主机角色与路由器角色之间并不相同。接受重定向的隧道接口是个奇怪的设计,因为点对点隧道内部并不存在同链路意义上的备选下一跳。所以这个设置值得读一读,而不是想当然。
安全重定向设置会进一步限制可以相信哪些网关。
如果你在加固主机,要复查的就是这些开关,它们也是同一网络里两台机器表现不同的原因。请把它们当策略来改,而不是当调试的捷径。
重定向解释不了的事
更具体的路由、策略路由规则和本地接口,不用任何重定向就能解释大多数异常路径。更具体的前缀、匹配源地址的规则,或另一张表里的第二条默认路由 都会覆盖你预期的路由。先检查这些,因为它们是确定且可见的。
过期的抓包是另一个陷阱,因为换过网络的客户端本地网关已经不同。
上一次接入留下的旧重定向对当前路径毫无解释力,所以要记录现在哪个接口在接收控制流量。
怪隧道之前先查路由
问内核它为目的地会选哪条路由,再与你预期的表做对比。若答案与表一致,说明没有任何重定向改变过什么,排查该去别处。若不一致,在认定隧道有问题之前,先找缓存的重定向、策略规则或第二张表。查表结果是事实,其余都是它如何变成这样的故事。
重定向绝不该成为受保护路径悄悄变成不受保护的原因,所以接受策略属于设计评审的一部分。RFC 792 的定义 仍是 IPv4 报文可以说些什么的参照。
把路由查询结果和抓包时间一起记下来,下一个人就能复现你的结论。