关于一个lo接口IPv6 unreachable路由的细节

版权声明:本文为博主原创,无版权,未经博主允许可以随意转载,无需注明出处,随意修改或保持可作为原创! https://blog.csdn.net/dog250/article/details/89390386

皮鞋进水发胖之后怎样才会恢复原样?拥有八块腹肌的中国浙江温州小型皮鞋厂老板也没有办法。


今天花了太多时间聊一些形而上意义上的东西,所以本文形而下。


今天时间不多,直奔主题。

我准备两台虚拟机,设为主机A,主机B,分别用其eth0接口直连,配置如下:

# 主机A-eth0 直连 主机B-eth0
# 主机A
eth0:1111:1111::101/64

# 主机B
lo:1111:1111::110/64
eth0:1111:1111::123/64

如果如上述这般配置,那么协议栈显然会生成下面的相关路由(确实也是的):

# 主机A
1111:1111::/64 dev eth0 proto kernel metric 256

# 主机B (两种情况,1111:1111::/64 的链路层路由和unreachable路由的先后顺序取决于eth0口和lo口上地址的添加顺序!)
1111:1111::/64 dev eth0 proto kernel metric 256
unreachable 1111:1111::/64 dev lo proto kernel metric 256 error -101
# 或者
unreachable 1111:1111::/64 dev lo proto kernel metric 256 error -101
1111:1111::/64 dev eth0 proto kernel metric 256

现在,从主机A来ping主机B的lo口地址1111:1111::110,无论主机B的eth0口和lo口的地址添加顺序如何导致无论哪种路由表项顺序,都是可以ping通的。然而从主机B主动ping主机A的eth0地址1111:1111::101,两种路由表项顺序结果是不同的:

  • unreachable路由在链路层路由前面,则ping不通。
  • 链路层路由在unreachable路由前面,则能ping通。

有点儿意思。

这是为什么?

难道IP协议不是 无方向无连接无状态的 吗?答案当然是肯定的!那么为什么会出现上面不对称的结果?


仔细观察上述的两条路由:

unreachable 1111:1111::/64 dev lo proto kernel metric 256 error -101
# 和
1111:1111::/64 dev eth0 proto kernel metric 256

它们之间的不同点太多,但是仅有 metric 是标准IP路由认识的,遗憾的是,二者的metric相同,这让我们想不通的是:

  1. 在主机A ping主机B时,主机B收到主机A的ICMPv6 Echo Request的时候,Linux内核协议栈到底check了哪些字段致使无论哪种路由排列都能ping通呢?
  2. 在主机B主动ping主机A时,两条路由中又是哪些字段让数据包优先匹配第一条匹配到的路由呢?

长篇大论无益,以后再说,这里直接说结论,关键的字段就是 dev ,即 路由项的出口网卡 字段。

以下简单解释。


首先几条路由可以等价为:

1111:1111::110/128 dev lo IN local
1111:1111::/64 dev lo unreachable
1111:1111::/64 dev eth0 onlink

当从主机A去ping主机B的时候,Echo Request数据包从主机B的eth0进入,显然目标地址会在Local路由表命中,然后主机B协议栈会回复Echo Reply。

此时Reply的目标地址是 1111:1111::101 ,查询路由表。

如果按照目标地址为健值查询的话,即便从metric看,两条路由均将命中,那么到底选择哪一条呢?

这里,TCP/IP协议栈的实现者按照check source的原则,定制了默认规矩,即 数据包从哪个网卡进入,它的回包将会从哪个网卡出去!

于是乎,从过主机B接收到主机A的主动请求,无论是ping的Echo Request还是TCP的Syn,它们均将从eth0被收入,那么回复Echo Response或者TCP的Syn/ack时,它们就理应从主机B的eth0出去,于是乎,在回包查询路由表时,自然而然就会加上 “出口网卡是eth0” 这么一个约束!

这样答案不就明确了吗?如果是从主机A主动去ping主机B,那么回包的路由肯定会匹配到主机B关于 1111:1111::/64dev eth0 链路层路由 ,而不会匹配到unreachable路由,这也就解释了为什么A ping B总是通的。

那么从主机B主动去ping或者telnet 主机A呢?

很显然,此时在查询路由表之前,并不知道要从那块网卡出去,这个时候,关于1111:1111::/64的链路层路由和unreachable路由是完全等价的,当然是谁排在前面那就选谁咯!

更加细节且有趣的是,IPv6在Linux内核协议栈中的组织采用了Trie树数据结构,它不像链表那般稳定,因此两条路由的顺序,还真的不一定。这还只是Linux的实现,还没说BSD和Windows呢…


看下代码,便可安睡?嗯,对于我等码农而言,是的!不说ICMP,就说说更加激烈的TCP吧。

在一个TCP服务端收到TCP客户端主动的SYN报文的时候,会回复SYN/ACK报文,在这个SYN/ACK报文的回复前,需要查找路由,在初始化路由查找键的时候,就会把出口网卡给引入,它的值,便是SYN报文的入口网卡:
在这里插入图片描述

关于ICMPv6报文,请自行解析!


浙江温州皮鞋湿;
下雨进水不会胖。

猜你喜欢

转载自blog.csdn.net/dog250/article/details/89390386