问题描述
如网络拓扑图所示。在私有云环境下,创建了两台虚机分别时test-dual-vpc与test-single-lan2。
test-dual-vpc绑定了两块网卡:
eth0 192.168.40.22 与 lan4网络 192.168.40.0/24直连
eth1 192.168.30.22 与 lan3网络 192.168.30.0/24直连
test-single-lan2绑定了一块网卡:
eth0 192.168.20.22 与 lan2网络 192.168.20.0/24直连
lan2、lan3、lan4都与路由器vpc-router-01相连,且vpc-router-01是三个网络的网关,网关地址如下:
lan2 192.168.20.254
lan3 192.168.30.254
lan4 192.168.40.254
从上面的配置直观来看,test-single-lan2这台虚机无论与test-dual-vpc的任意一块网卡交互,应该都是联通的。
无论是ping 192.168.40.22还是ping 192.168.30.22都应该经过vpc-router-01转发至相应的网段内。
但是事实上,test-single-lan2 ping 192.168.40.22是通的,ping 192.168.30.22并不通。
问题分析
上面描述的现象,总结一下就是:
- 虚机绑定了两块网卡,第一块网卡也就是默认网卡跨网段访问是能正常访问的,而第二块网卡跨网段访问不通。
当test-single-lan2 ping 192.168.30.22时,tcpdump icmp包看了一下,发现只有请求的包,test-dual-vpc没有给响应。请教了私有云厂商的人,给的答复是**“linux机制 双网卡下 默认单路由”**,貌似linux就是这么设计的。在网上看到了华为云的一篇文章:
https://support.huaweicloud.com/vpc_faq/vpc_faq_0079.html
文中背景知识的内容摘抄如下:
当云服务器拥有多张网卡时,主网卡默认可以和外部正常通信,扩展网卡无法和外部正常通信,此时需要在云服务器内部为这些网卡配置策略路由,才可以确保多张网卡均可以和外部正常通信。
根据上文的解释,第二张网卡不能与外网通信是合理的,需要另外配置策略路由。根据文中的方法,在test-dual-vpc上进行了策略路由的配置,第二块网卡的确能正常工作了。
继续分析
但是为什么不配置策略路由的时候,只有默认网卡能工作,而第二块网卡无法正常跨网段访问?文中却没有解释。和组里同事讨论了这个问题,最终在网上发现了关于rp_filter的介绍
https://www.cnblogs.com/lipengxiang2009/p/7446388.html
rp_filter是为了防止ddos攻击而设计的。当rp_filter置为1时,将严格检查接受报文的网卡,和响应报文的源IP的网卡是否是同一个网卡,如果不是,就丢弃
有了这个背景知识,我们再分析一下遇到的问题,去test-dual-vpc虚机上查看路由信息
default via 192.168.40.254 dev eth0
192.168.30.0/24 dev eth1 proto kernel scope link src 192.168.30.22
192.168.40.0/24 dev eth0 proto kernel scope link src 192.168.40.22
问题差不多明了了,当test-single-lan2 ping 192.168.30.22时,接收请求的网卡是eth1,而根据默认路由需要经过eth0发响应报文。eth0和eth1不是同一块网卡,rp_filter规则生效将包丢掉。
前文讲到的配置策略路由,实际上就是根据源ip的不同选择特定的路由表,这样就可以设置多个默认路由。
[root@192-168-40-22 ~]# ip rule
0: from all lookup local
32764: from 192.168.30.22 lookup 20
32765: from 192.168.40.22 lookup 10
32766: from all lookup main
32767: from all lookup default
[root@192-168-40-22 ~]# ip route show table 20
default via 192.168.30.254 dev eth1
192.168.30.0/24 dev eth1 scope link
策略路由如上所示,当源ip来自192.168.30.22时,就会去查找路由表20,路由表20指明了默认路由走eth1。这样就不会出现接收请求是eth1,而响应请求是eth0的情况,能够通过rp_filter的检查。
思考
关于问题的描述,我一直强调是跨网段的访问。因为同在192.168.30.0网段的机器访问192.168.30.22是正常的,这又是为什么呢?分析一下也很简单,因为linux了配置了直连路由:
192.168.30.0/24 dev eth1 proto kernel scope link src 192.168.30.22
同在30网段的机器,就是通过eth1发出去的。那这样也符合接收与发送是同一块网卡的检查。