问题记录

如题,在实验环境中的一台服务器上使用了两块网卡(一块儿千兆,一块儿万兆),并给其分别分配了两个网段的地址:千兆-10.10.2.21 万兆-10.10.3.21,两个网卡分别上联千兆交换机和万兆交换机。经测试,千兆和万兆环境各自都可以正常访问。但是奇怪的现象出现了,当我在办公环境想要远程访问这两个地址的时候,只有10.10.2.21这个地址是可以访问的,刚开始认为是万兆交换机的配置出了问题,一通分析后发现并没有什么明显的错误,同时发现只要把千兆网卡DOWN掉或者网线拔掉,10.10.3.21这个地址就可以正常访问了,反之亦然,但只要两个网卡都UP,就只能访问其中一个地址。简单总结问题如下:

  • 网卡em1: 10.10.2.21
  • 网卡em2: 10.10.3.21
  • 办公环境地址:172.16.11.213, 只能同时访问2.21和3.21其中的一个。

通过命令:route -n 或者ip route list查询服务器上的路由表如下:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.2.1       0.0.0.0         UG    0      0        0 em1
0.0.0.0         10.10.3.1       0.0.0.0         UG    0      100      0 em2
10.10.2.0      0.0.0.0         255.255.255.0   U     0      0        0 em1
10.10.3.0      0.0.0.0         255.255.255.0   U     0      100     0 em2

原因排查

通过ifconfig命令查看em2网卡的收包情况,发现有大量的drop报文,比例很高。为什么会出现这种情况呢?肯定是有知识盲点,那就上网查阅资料吧,果然有人遇到了同样的问题,简言之就是CentOS7 默认开启了反向路由检查功能,开启该功能后系统内核会检查发送报文的路径和接收报文的路径是否一致,如果不一致,则会将该报文丢弃。对应到我们的例子就是,当我们访问10.10.3.21的地址的时候,是从网卡em2进去的,但是根据路由,返回的报文却是从em1出去的(走的上面第一条默认路由),两者不一致,从而响应报文被丢弃,我的远程访问自然也失败了。

解决办法

关闭反向路由检查功能,如下:

echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/em1/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/em2/rp_filter

为了避免重启后配置失效,可以将上述语句写入到/etc/rc.local中。 按照上述办法执行后,终于,可以同时访问10.10.2.21和10.10.3.21这两个地址啦~~

知识点

1. 反向路由检查

反向路由检查的原理在上文中已经介绍了,即检查进来和出去的路径是否一致,不一致则丢弃报文。那么为什么还要开启这个功能呢?主要是为了避免如下两种情况:

  • 减少D:校验数据包的反向路径,如果反向路径不合适,则直接丢弃数据包,避免过多的无效连接消耗系统资源。
  • 防止IP Spoofing(IP欺骗):校验数据包的反向路径,如果客户端伪造的源IP地址对应的反向路径不在路由表中,或者反向路径不是最佳路径,则直接丢弃数据包,不会向伪造IP的客户端回复响应。

2. 内核参数rp_filter

根据linux内核官方文档的介绍,rp_filter参数有三个值:0、1、2,具体含义:

  • 0:不开启源地址校验。
  • 1:开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径。如果反向路径不是最佳路径,则直接丢弃该数据包。
  • 2:开启宽松的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意网口),如果反向路径不同,则直接丢弃该数据包。