内容简介:今天耽误了太多时间来说一些形而上意义上的东西,所以本文形而下。今天时间不多,直奔主题。我准备两台虚拟机,设为主机A,主机B,分别用其eth0接口直连,配置如下:
今天耽误了太多时间来说一些形而上意义上的东西,所以本文形而下。
今天时间不多,直奔主题。
我准备两台虚拟机,设为主机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相同,这让我们想不通的是:
- 在主机A ping主机B时,主机B收到主机A的ICMPv6 Echo Request的时候,Linux内核协议栈到底check了哪些字段致使无论哪种路由排列都能ping通呢?
- 在主机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::/64 的 dev 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报文,请自行解析!
浙江温州皮鞋湿;
下雨进水不会胖。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- hapi框架搭建记录(二):路由改造和生成接口文档
- vue路由篇(动态路由、路由嵌套)
- 小程序封装路由文件和路由方法,5种路由方法全解析
- Vue的路由及路由钩子函数
- gin 源码阅读(二)-- 路由和路由组
- vue router 路由鉴权(非动态路由)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。