当一台机器有超过1块网卡,并且配置的IP地址不在一个段里的时候,会出现在外部只有一个IP地址能够ping通的情况,举个最简单的例子:
一个有2块网卡的机器:
[root@test]# ip addr
2: enp24s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 11:11:11:11:11:11 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.10/24 brd 192.168.100.255 scope global enp24s0f1
valid_lft forever preferred_lft forever
3: enp24s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 22:22:22:22:22:22 brd ff:ff:ff:ff:ff:ff
inet 192.168.200.10/24 brd 192.168.200.255 scope global enp24s0f1
valid_lft forever preferred_lft forever
可以看到两块网卡,分别配置了192.168.100.10
和192.168.200.10
这两个IP,再看看机器的默认路由:
[root@test]# ip route
default via 192.168.100.1 dev enp24s0f0
192.168.100.0/24 dev enp24s0f0 proto kernel scope link src 192.168.100.10
192.168.200.0/24 dev enp24s0f1 proto kernel scope link src 192.168.200.10
从路由可以发现这机器的默认网关是192.168.100.1
,那么,如果跨越网关去ping这台机器的话,会出现只有192.168.100.10
能通的情况:
[root@test2]# ping 192.168.100.10 -c 2
PING 192.168.100.10 (192.168.100.10) 56(84) bytes of data.
64 bytes from 192.168.100.10: icmp_seq=1 ttl=56 time=1.84 ms
64 bytes from 192.168.100.10: icmp_seq=2 ttl=56 time=0.804 ms
--- 192.168.100.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.804/1.319/1.835/0.515 ms
[root@test2]# ping 192.168.200.10 -c 2
PING ping 192.168.200.10 (ping 192.168.200.10) 56(84) bytes of data.
^C
--- ping 192.168.200.10 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1062ms
可以看到只有第一个IP能通。那么,如果想让两个IP都能通信需要怎么做呢?我们简单分析一下:
假设ping的源主机IP地址是192.168.1.20
,那么ping包会首先到达192.168.200.0/24
的网关,在这个场景是192.168.200.1
,然后网关把包转发给机器的第二块网卡,从接收的这条链路来说,是没有问题的。
那么回包的链路呢?因为发起通信的源IP不在同网段,所以会查询路由表,会根据路由表发给默认网关,而测试机器的默认网关是192.168.100.1
,需要将流量从第一块网卡出去。
从回包的链路考虑就会有一些问题,相当于流量从一块网卡进来,但是又从另外网卡出去。默认情况下,Linux会通过一个Reverse Path Filtering (rp_filter)的机制,限制这种情况发生。
那么要修改也很简单:
[root@test2]# echo "net.ipv4.conf.all.rp_filter = 0" >> /etc/sysctl.conf
[root@test2]# sysctl -p
配置rp_filter=0
之后,再去测试,发现第二块网卡已经可以正常被外部访问了。
到这里,网络通断问题算是解决了,但是呢,流量路径并不是最优解。目前这个情况,所有出去的流量全都走网卡1,一方面网卡2的出方向带宽浪费了,另外一方面如果网卡1出现一些问题导致中断,那网卡2的IP地址也无法访问了,可用性并没有提升。
针对两块网卡的机器,一个很自然的想法,是不是可以某一块网卡进来的流量,也从同一块网卡出去呢?
这里就需要策略路由的帮助了,其实这个问题,可以转化成根据source地址选择不同的路由,因为从这台机器发出去的网络包,源地址不是192.168.100.10
,就是192.168.200.10
,那需求就很简单了,如果发现源地址是192.168.100.10
,那就走网卡1的默认路由出去,如果源地址是192.168.200.10
,那就走网卡2的默认路由出去。这样的话,相当于机器上有两个默认路由了,这样可以么?
答案是可以的,不过需要将这两个默认路由分到两张不同的路由表上。根据这篇Routing Tables文章可以看到Linux支持很多张路由表,其实默认我们用ip route
命令操作的就是main
这张表。通过加表id或者名字的方式,可以让ip命令操作不同的路由表。
[root@test]# ip route add default via 192.168.200.1 dev enp24s0f1 table 101
[root@test]# ip route show table 101
default via 192.168.200.1 dev enp24s0f1
这里添加了一条新的默认路由default via 192.168.200.1 dev enp24s0f1
到编号为101的表里。现在有了路由表,还需要一个策略,来让对应源地址的流量查找这张路由表就行了:
[root@test]# ip rule add from 192.168.200.0/24 table 101
[root@test]# ip rule show
0: from all lookup local
32765: from 192.168.200.0/24 lookup 101
32766: from all lookup main
32767: from all lookup default
这里加了一条规则,如果源地址在192.168.200.0/24
内,就使用101这张路由表,而这张路由表就上面加的以网卡2为出口的。这样就实现了网卡流量同进同出的需求。
其实可以通过ip rule show
看到,默认有几条规则,优先级最高的规则是local这张表,其次是刚添加的规则,然后是main这张表,最后是default这张表。
最后还有一个问题,这些配置怎么持久化呢?参考红帽的文档Networking Guide,可以在/etc/sysconfig/network-scripts
目录下,添加rule-XXXX
和route-XXXX
文件,实现配置持久化:
[root@test]# cat route-enp24s0f1
default via 192.168.200.1 dev eth1 table 101
[root@test]# cat rule-enp24s0f1
from 192.168.200.0/24 table 101
添加了配置文件后,执行ifup enp24s0f1
就可以实现自动的配置了。
评论前必须登录!
注册