当前位置: > 虚拟化 Virtualization > oVirt >

漫谈ovirt网络配置(二):Linux IP Routing

时间:2020-01-11 18:24来源:linux.it.net.cn 作者:IT

与路由器一样,一台普通的linux主机的网络层也维护着一张用于转发数据的路由表,与路由器不同的是 普通linux主机不会像路由器那样在不同端口之间转发数据。

我们首先简单描述一下使用路由表如何来转发数据:

  1. 对于目的地址属于同一子网的数据包,通过查看arp表在链路层帧中将目标ip对应的mac地址携带上,从指定端口发送出去就可以了。
  2. 对于目的地址不属于同一子网的数据包,需要通过路由表找到网关地址,然后在链路层帧中携带的是 这个网关地址对应的mac,这样通过指定端口发送出去的数据包首先会到达 这个网关,网关所在的设备我们可以简单地认为是一个具有路由器功能的设备,这样在网关设备接收到这个数据包后,通过查询自己的路由表,决定出从哪个端口继续转发这个数据包,进一步修改源mac和目标mac地址,然后从相应端口转发出去。如果路由表中找不到对应的转发出口,我们往往就会得到一个 host unreachable 或者 network unreachable 的ICMP响应。
  3. 前面两条都首先需要同路由表中找到相应的 转发规则,如果找不到任何匹配的规则,那么就使用路由表中的default规则(默认路由)。

我们一开始的实验环境是一个只有一张网卡的linux主机,使用 route -n命令查看路由表规则如下(也可以使用ip route show或者netstat -rn),

我们看到当前路由表有两条规则,第一条规则是默认的路由规则,第二条规则对应 目的地址属于 192.168.104.0/24子网内的数据包。在这个最简单的环境中,我们很容易想明白如何使用这张路由表转发数据。 我们可以做一个小实验,分别在删除了第二条规则前后两次ping 192.168.104.60,看看所发送的ICMP Echo Request中目的mac地址的变化。

到此我们介绍了最简单的环境中路由规则的使用,现在我们给测试环境增加一个网卡,并将它连接到另一个子网中,现在的环境如下:

 

此时我们再次查看路由表

现在的路由表增加了一个 192.168.105.0/24子网的规则和另一个指向 105.254的默认路由,但是由于105.254的metric比104.254的metric大,所以这个默认路由此时是不会被匹配到的,我们后面会证明它。

现在我们大致描述一些此时的路由规则,对于目的地址是105.0/24的发送到eth1,对于目的地址是104.0/24的发送到eth0,其他所有的数据包通过eth0发送到104.254这个默认网关。我们做两个实验证明一下。

第一个实验我们 首先在另一个104网段的设备里ping 192.168.104.100,然后在另一个105网段的设备里ping 192.168.105.102, 同时我们在上面配置的机器里分别监听 eth0和eth1,我们可以正确监听到正确的数据包。

这里刷了个小把戏,因为我实验的这台机器是ovirt上的虚拟机,在ovirt环境中我建立了两个逻辑网络,分别是104网段和105网段,然后使用这两个逻辑网络给这台实验虚拟机分配了两个虚拟网卡,我这里实际上并没有真正另外再创建两台其他的虚拟机,而是直接在运行这台虚拟机的宿主机上执行ping的,当然由于已经正确配置了路由规则,所以如果我ping 192.168.105.100 ,那么此时的 echo request肯定是从 105的那块网卡发送出去的,当然我们也可以ping -I 来指定网卡。

这个实验就不做演示了,实验的结果是可以正常发送接收的。

第二个实验我们从一个属于第三个子网的设备(192.168.4.14)分别ping 104.100和ping 105.102, 前一个ping 104.100没有什么问题,但是当ping 105.102时结果可能与你想象的不太一样,如下。

我们现在来分析一下为什么为这样,从4.14发送来的ICMP echo request首先被 eth1(105.102)接收,向上传递到操作系统,ICMP协议相关的系统组件处理完成后产生了ICMP echo reply,问题的关键就在于这个操作系统产生的ICMP echo reply会被如何路由出去。 回想一下上面的路由表,对于既不属于104子网也不属于105子网的数据包(这个echo reply的目的地址是4.14,显然符合)会被匹配到104.254这个默认路由上来,然后通过eth0路由出去,但是当eth0接收到这个数据包时会发现源地址时105.102(eth1),此时遇到不属于自己的数据包,就直接将其摒弃(discard)了。这样之后自然4.14不会接收到任何echo reply了。

对于为什么eth0会直接摒弃源地址不是自己的echo reply,我可能理解的不对,如果你们知道具体细节,希望能告诉我。

到这里我们就遇到了一个大问题,那就是上面的路由表好像不能够充分满足我们的需求,我们除非在105网段内否则都无法连接上105.102。 为了解决这个问题,我们可以使用 策略路由(policy routing)。

简单的来说,就是Linux允许我们定义多张自定义的路由表(route table),并且允许我们针对这些路由表定义相应的路由规则(route rule),当需要路由数据包时,首先根据路由规则找到相应的路由表,然后在遍历这些路由表最终找到相应的匹配规则,以此来实现灵活的路由策略。

配置策略路由可以通过命令行直接配置,但是会在重启后失效,我在这里给出一个使用配置文件持久化配置的例子,如下:

  1. 配置/etc/iproute2/rt_tables

2. 在/etc/sysconfig/network-scripts 目录下需要 针对每个网卡增加一对文件 rule-ethX 和 route-ethX,所有配置文件如下:

在按照上面设置完成后,我们可以使用下面的命令查看规则和路由

ip rule show all / ip rule show table table_name

ip route show all / ip route show table table_name

这样就可以解决之前的问题了,回想一下刚才的问题关键在哪里, echo reply只要能被转发到eth1 就可以了,而echo reply的source ip为192.168.105.102, 会被

from 192.168.105.0/24 lookup sub105

这条规则匹配到,所以会使用路由表 sub105,然后会被eth1转发,问题也就不存在了。

 

最后我们看一下ovirt中是如何使用策略路由的,就跟上面说的那样,我的测试虚拟机使用的两个虚拟网卡是使用ovirt的两个逻辑网络建立的,主机上的网络配置如下:

这样在主机上就建立了两个名字分别是 ovirtmgmt和net105的网桥,我们查看一下就会发现在/etc/sysconfig/network-scripts目录下面存在着

route-net105   route-ovirtmgmt   rule-net105  rule-ovirtmgmt 四个文件,而我上面例子中的配置内容也是模仿着这四个文件编写的。使用ip route和ip rule规则查看应该跟上面的例子基本相同。

不过这里我有一个疑问,在ovirt主机的/etc/iproute2/rt_tables 文件中并没有像我那样配置 自定义的路由表,我不知道为什么,如果你知道,请在评论区告诉我。 

 

这样关于 Linux IP Route的内容基本上就说完了,最后再记录一个问题,我上面的那个实验中两个网卡分属两个不同的子网,如果它们属于同一个子网的话,即便向上面那样配置了,依然是不可以的,原因在于 操作系统对于arp的处理策略,我们查看ovirt主机上的

/proc/sys/net/ipv4/conf/default/arp_announce 和/proc/sys/net/ipv4/conf/default/arp_ignore的话,会发现并没有使用默认配置 0,而是分别为2和1。具体的分析已经补充到文章的最下面。

刚刚实验了一下将主机上一个空闲的网卡配置到与ovirtmgmt同一个网段中,该如何访问。做一个简单的记录。

这样配置完成之后,两个同网段的地址都可以访问到这台主机设备了,当然这样做完全是为了实验学习目的,好像没有什么实际意义。

 

==对arp_ignore和arp_announce补充==

当一台主机拥有位于同一子网中的两个网卡时,可能会出现称作为ARP Flux的问题,如下:

 

HostB拥有位于同一子网的两个网卡,当我们在同一子网的另一台主机HostA中获取HostB两个ip对应的mac地址时,会出现两个ip对应到同一个mac的情况,被称作是ARP Flux。

我们在HostA中查看ARP结果如下:

这样以后,实际上我们在HostA中即使是尝试与HostB的107.115通信,走的还是eth0,而不是eth1。

要解决这个问题,就要配置arp_ignore和arp_announce这两个内核参数。

sysctl w net.ipv4.conf.all.arp_ignore=1

sysctl w net.ipv4.conf.all.arp_announce=2

这是跟ovirt主机上的配置一样的

对于具体参数含义我其实也没能完全弄明白,就不多做解释了,可以参考内核参数文档 https://sysctl-explorer.net/net/ipv4/

配置完成之后,手动清空hostA中的arp缓存(arp -d)之后会发现只能够访问107.114,而不能够访问107.115了,原因与我们上面所讲的多网段多网卡是一样的,我们需要配置策略路由。

配置过程与上面的多网段的情况基本一样,就不列出了。

这样都完成后,我们就可以正常的去访问107.114和107.115了。

 

疑问:

当有源地址不是当前网卡地址的数据包被路由到当前网卡后,会转发出去还是丢弃掉? 为什么?

例如网卡eth0的ip地址为192.168.107.114,那么如果有一个数据包的源ip地址为192.168.107.115,被路由到了eth0,会怎么处理呢?

在ARP_Flux的情况下,上面这种情况,eth0会正常转发源ip为107.115的数据包,而当我们解决了ARP_Flux后,eth0好像就不会转发了,而是直接丢弃了,这也是我们没配置策略路由的时候为什么无法访问到107.115的原因,大家有时知道具体的原理,或者相应的知识点,请告诉我^_^。

 

参考:

https://opensource.com/business/16/8/introduction-linux-network-routing

https://blog.scottlowe.org/2013/05/29/a-quick-introduction-to-linux-policy-routing/

https://access.redhat.com/solutions/30564

http://www.linuxhorizon.ro/iproute2.html

https://unix.stackexchange.com/questions/365380/how-to-persist-ip-rule-and-route-whenever-server-rebooted

 




(责任编辑:IT)
------分隔线----------------------------