路由条目的意义
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
路由条⽬的意义
路由条⽬的意义
路由的设计远⽐⼀般的理解要复杂的多。
典型的路由条⽬包括了源IP,⽬的IP,⽹关IP,scope,dev和type六个要素。
⽹关IP就是在配置路由的时候指定的via后⾯的地址,在路由表中叫Gateway,这是说明这条路由的下⼀跳是这个IP地址。
这个IP地址之所以出现,是因为⽬的地址不是当前⾃⼰出⼝可以直接可达的,需要经过⽹关路由到下个⽹络才能投递。
也就是因此,如果这个via域配置为0.0.0.0,或者是⽤*表⽰,总之是代表⼀定的通配,那么就意味着这个路由的⽬的地和⾃⼰在⼀个⼆层的⽹络,到达那个⽬的地并不需要⽹关转发,只需要配置MAC地址从端⼝上发出去即可。
这个发送出去的过程显然是去查ARP表,通过IP地址查询⽬标的MAC地址。
很容易理解⽹关在路由条⽬中的意义,如果到达⼀个⽬标地址是需要通过⽹关转发出去的,via就要指定⽹关。
⼤部分的个⼈局域⽹中,都会指定⼀个默认⽹关,⽬的IP填写了0.0.0.0,也就是所有的⽬的地址(通常使⽤命令的时候,这个词语叫做default),via后⾯填写⽹关地址。
这样在其他的更精确的路由条⽬都不命中的情况下,就⼀定会命中这个默认路由条⽬。
因为这个条⽬的⽬的IP设置是通配。
使⽤ip命令设置这样的默认路由是例如ip route add default via 10.0.0.1。
假设⼀个路由条⽬指定了gateway,那么决策还需要知道这个gateway到底是从哪个⽹⼝发出去可达的,这就是dev的作⽤。
既然到⼀个gateway必然要从⼀个设备出去,⽽其他的地⽅并不能指定这个gateway和设备的对应关系,于是就在路由表这⾥就指定了。
通过dev可以到达该gateway。
如果gateway不指定,也就是该路由在同⼀个⼆层,那么仍然需要指定dev,因为即使是发送出去,也需要查从哪⾥发送出去。
因为在收到⼀个数据包的时候,进⼊系统的时候⽬的IP不是⾃⼰就需要根据⽬的IP来查找路由,这个路由会决定这个⽬的IP是要转发给哪个端⼝(通常通过⽬的IP和⽹关IP和dev来决定)。
Dev是相对于gateway的⼀个更⼩的约束。
同样起到约束作⽤的还有scope。
Scope是⼀个更⼩程度的约束,指明了该路由在什么场景下才有效。
也是⽤于约束⽬的地址的。
例如不指定⽹关的⼆层路由,通常对应的scope类型是scope link。
scope link的意义就是说明在同⼀个⼆层。
这个意义与⽹关不指定的效果是呼应的。
有四种scope,global是在任何的场景下都有效,link是在链路上才有效,这个链路是指同⼀个端⼝,也就是说接收和发送都是⾛的同⼀个端⼝的时候,这条路由才会⽣效(也就是说在同⼀个⼆层)。
Global则可以转发,例如从⼀个端⼝收到的包,可以查询global的路由条⽬,如果⽬的地址在另外⼀个⽹卡,那么该路由条⽬可以匹配转发的要求,进⾏路由转发。
Link的scope路由条⽬是不会转发任何匹配的数据包到其他的硬件⽹⼝的。
还有就是host,host表⽰这是⼀条本地路由,典型的是回环端⼝,loopback设备使⽤这种路由条⽬,该路由条⽬⽐link类型的还要严格,约定了都是本机内部的转发,不可能转发到外部。
Site则是ipv6专⽤的路由scope。
源IP是⼀个路由条⽬的重要组成部分,这个源IP的意义在于⼀个补充作⽤。
匹配还是根据⽬的IP进⾏匹配,但是由于在查找路由条⽬的时候很可能源地址还没有指定。
典型的就是没有进⾏bind的发送情况,通常是随机选择端⼝和按照⼀定的规则源地址。
这个⼀定的规则就是在这⾥的路由条⽬的src域可以影响。
也就是如果进程没有bind⼀个源地址,将会使⽤这⾥src域⾥⾯的源地址作为数据包的源地址进⾏发送。
但是如果进程提前bind了,命中了这个条⽬,就仍然会使⽤进程bind的源地址作为数据包的源地址。
所以说这⾥的src只是⼀个建议的作⽤。
# ip route
default via 115.238.122.129 dev eth1
115.238.122.128/25 dev eth1 proto kernel scope link src 115.238.122.163
192.168.0.160/24 dev dpdk0.kni proto kernel scope link src 192.168.0.163
192.168.1.160/24 dev dpdk1.kni proto kernel scope link src 192.168.1.163
举⼀个例⼦,从本机发出的⽬的地址是192.168.0.160/24⽹段的数据包将匹配第三条路由,如果在查询路由表之前没有设置bind,这个查询路由表的操作就会把数据包的源地址设置为192.168.0.163 。
如果设置了bind,就保留bind的结果(所以你可以很容易的在Linux的主机上伪造原地址发送数据)。
src域在处理转发的数据包的时候,由于数据包是从外部收到的,外部进来的数据包也会查找路由表,也能命中同⼀个路由条⽬。
但是由于外部进来的数据包已经有了明确的源地址,这⾥的src源地址建议就不会起作⽤了。
所以关键就是理解src只是⼀个源地址的⼀个建议的作⽤即可。
对于路由表,是⼀个匹配的过程。
⼀个数据包去查找匹配⾃⼰最能够匹配哪条路由表,然后就使⽤该路由条⽬指定的路由⽅法进⾏路由转发。
匹配的⽅法就是⿍⿍⼤名的LPM,简单的说,就是匹配最匹配的那⼀个。
所以整个过程可以看到,核⼼的是对⽬的地址的限制,其他的域都是⽤于辅助这个限制,甚⾄可以辅助决策。
我们看⼀个虚拟机⾥的默认路由表:
root@ubuntu:~/# ip route show
default via 192.168.142.2 dev ens33 proto static metric 100
169.254.0.0/16 dev ens33 scope link metric 1000
192.168.142.0/24 dev ens33 proto kernel scope link src 192.168.142.135 metric 100
跳过default,后⾯两条的第⼀个域都是⽬的地址,确切的说,这⾥指定的是⽬的⽹段,然后约束了设备,也就是ens33,这个路由条⽬是scope link的,也就是说当主机收到⽬标地址是169.254.0.0/16 这个⽹段的时候,通过ens33这个设备将包转发出去。
虽然理论上是如此,但是实际上,例如在linux中,这个dev ens33是没有在路由中起到任何作⽤的,也就是说你改了ens33的名字,⽽不改路由表,那这个路由表项⼀样命中,从改名后的⽹⼝发送出去。
所以dev的这个限制相当于不存在,也就是只是⼀个命名的作⽤。
但是并不确定在其他的实现中是否有限制的意义。
Default路由本质上就是⽬标地址填了0.0.0.0的路由。
Default路由有两种添加⽅式,⼀种是约束⽹关地址,另外⼀种是约束源IP。
因为要添加到⽹关地址的默认路由,是需要在添加的时候发⼀个arp请求到⽹络上,看这个⽹关的地址是否存在于⼆层的,但是这个arp请求也是需要⾸先经过路由的。
也就是⼀个鸡⽣蛋,蛋⽣鸡的问题。
所以⼀个空的路由表是不能直接配置默认路由是⼀个⽹关的。
但是明明⽹关确实是和当前的主机在同⼀个⽹段的。
如果要配置默认⽹关,⾸先需要先让这个⽹络通。
这个通的⽅法⼀个是配⼀个scope link的路由,也就是⽬的地址是该⽹段的发包,都可以匹配这个路由。
因为是link scope的,所有的请求都会⾛⼆层的路由表,这就解决了arp不能到达⽹关的问题。
Link scope的特点是所有的数据请求⾛⼆层arp,⽽不是⾛三层路由。
所以在配置了这条路由之后,再配置⽹关就可以了。
但是还有⼀个思路是使⽤源地址约束,我们要的只是这个查询能命中⼀个可以出去的路由,当我们使⽤源地址约束,不指定⽬标地址,也就是源地址是⾃⼰设备的IP的地址的包全部⾛link scope,同样也可以匹配,由于是link scope,也就可以触发arp请求了。
所以我们看到,整个过程的关键在于区分同⼆层和三层转发。
Link scope的作⽤是⽤在⼆层转发,命中该路由条⽬的可以触发arp查找,但是如果是⽹关式的,就是⼀个三层转发,虽然也会触发arp查找,但是⽬标MAC地址永远是⽹关的地址,这样下⼀跳就锁死了。
但是这⾥有⼀个问题是如果先添加了link scope的路由条⽬,然后⼜添加了gateway的路由,这个时候再把link scope的路由条⽬删除,那么gateway的路由条⽬仍然存在并且⽣效,这个时候,所有的转发都会匹配这个gateway的路由条⽬,包括本来应该⾛⼆层转发的数据包。
也就是说,原本应该在同⼀个⼆层传输⾛arp的数据包,在这种情况下,也会直接⾛⽹关,⽹关回复⼀个icmp redirect,但是⽹关仍然会把这个数据包转发到同⼀个⼆层的⽬标地址。
理论上,收到icmp redirect的主机应当更新⾃⼰的arp表,但是并不会更新路由表,⽽arp表是要先经过路由表查询的,所以这个icmp redirect相当于没有意义。
Arp表⾥⾯即使是有了IP到MAC的映射关系,但是由于路由没有命中link scope,所以永远不会查询ARP表。
另外linux下的路由条⽬还会有⼀个proto的域,⼀般有proto kernel和proto dhcp两种。
Proto表明的是这个路由条⽬是由谁添加,例如给⼀个linux设备添加⼀个IP的时候会⾃动添加⼀条有这个源IP约束的Link scope的路由。
前⾯说了,也正是有了这条路由才能够使得配置⽹关的路由条⽬可以进⾏。
这个内核⾃动添加的路由就是proto kernel了。
需要理解的是,路由表和⽹络设备是两个实体,路由表在决策的时候,由路由表看到的⽹络设备是独⽴于路由表存在的。
他们是并⾏的关系,先要查询了路由表,找到满⾜路由表的路由条⽬,才有可能按照条⽬约定的路由路径去找到对应的设备。
路由过程并不是发⽣在设备逻辑的内部,⽽是外部。
所以实际上给设备添加了⼀个IP地址的时候,同时⽣成的路由条⽬实际上是两个操作被在上层进⾏了组合。
技术上,完全可以分别的添加IP地址和路由条⽬,上⾯也说了这个添加的路由条⽬可以被删除,然后再次添加回去。