CentOS 9 双公网网卡回程路由异常的排查与处理

服务器上有两张公网网卡:

enp10s0        45.125.47.173/24
enp115s0f4u2   150.138.72.230/24

其中:

查看当前路由:

ip route

输出如下:

default via 45.125.47.1 dev enp10s0 proto static metric 50 
45.125.47.0/24 dev enp10s0 proto kernel scope link src 45.125.47.173 metric 50 
45.125.47.0/24 dev enp10s0 proto kernel scope link src 45.125.47.187 metric 50 
150.138.72.0/24 dev enp115s0f4u2 proto kernel scope link src 150.138.72.230 metric 104

可以看到,系统默认出口是:

default via 45.125.47.1 dev enp10s0

也就是说,如果没有额外配置,所有默认出站流量都会从 enp10s0 出去。

二、问题现象

第二张公网网卡 enp115s0f4u2 能抓到外部流量,说明网卡本身是有流量进来的。

例如执行:

tcpdump -i enp115s0f4u2

可以看到类似流量:

IP 163.177.221.181 > zz1: ICMP echo request
ARP, Request who-has 150.138.78.1 tell 150.138.78.101

这说明外部请求已经到达了这张网卡。

但问题在于:请求从 enp115s0f4u2 进来后,服务器的回包可能会根据默认路由从 enp10s0 出去。

这就会造成一个典型的问题:

外部访问 150.138.72.230
请求从 enp115s0f4u2 进来
回包却从 enp10s0 出去
对端收到的源地址或路径不符合预期
连接异常

这就是双公网网卡环境中常见的“回程路由不一致”问题。

三、查看策略路由规则

继续查看当前策略路由:

ip rule

输出如下:

0:      from all lookup local
32765:  from 150.138.72.230 lookup 100
32766:  from all lookup main
32767:  from all lookup default

这里其实已经有一条规则:

from 150.138.72.230 lookup 100

意思是:

只要源地址是 150.138.72.230,就查询路由表 100

这条规则本身是正确的。

但是继续查看 100 号路由表:

ip route show table 100

结果为空。

也就是说,虽然系统已经告诉内核:

源地址为 150.138.72.230 的包要查 table 100

table 100 里面没有任何路由。

所以问题就出在这里:策略规则存在,但对应路由表是空的。

四、临时修复方法

table 100 添加对应的网段路由和默认路由。

执行:

ip route replace 150.138.72.0/24 dev enp115s0f4u2 src 150.138.72.230 table 100

这条命令的意思是:

在 table 100 中添加 150.138.72.0/24 网段路由,
这个网段走 enp115s0f4u2,
源地址使用 150.138.72.230。

然后继续添加默认路由:

ip route replace default via 150.138.72.1 dev enp115s0f4u2 src 150.138.72.230 table 100

这条命令的意思是:

在 table 100 中添加默认路由,
默认网关是 150.138.72.1,
出口网卡是 enp115s0f4u2,
源地址使用 150.138.72.230。

完整命令如下:

ip route replace 150.138.72.0/24 dev enp115s0f4u2 src 150.138.72.230 table 100
ip route replace default via 150.138.72.1 dev enp115s0f4u2 src 150.138.72.230 table 100

五、验证路由是否正确

添加完成后,使用下面命令验证:

ip route get 8.8.8.8 from 150.138.72.230

输出结果如下:

8.8.8.8 from 150.138.72.230 via 150.138.72.1 dev enp115s0f4u2 table 100 uid 0 
    cache

这就说明现在路由已经正确了。

重点看这一段:

via 150.138.72.1 dev enp115s0f4u2 table 100

含义是:

当源地址是 150.138.72.230 时,
访问外部地址会走 table 100,
并通过 enp115s0f4u2 网卡,
从 150.138.72.1 网关出去。

这正是我们需要的效果。


本次问题的核心原因是:

双公网网卡环境下,第二张公网网卡只有直连网段路由,没有对应的回程默认路由。

当前系统主默认路由是:

default via 45.125.47.1 dev enp10s0

所以如果不做策略路由,服务器很可能出现:

150.138.72.230 收到请求
但回包从 45.125.47.173 / 45.125.47.187 所在网卡出去

最终导致连接失败或者访问异常。

解决思路就是:

根据源 IP 分流。

也就是:

源地址是 150.138.72.230 的流量,必须从 enp115s0f4u2 出去。

对应命令是:

ip route replace 150.138.72.0/24 dev enp115s0f4u2 src 150.138.72.230 table 100
ip route replace default via 150.138.72.1 dev enp115s0f4u2 src 150.138.72.230 table 100

验证命令是:

ip route get 8.8.8.8 from 150.138.72.230

只要结果中出现:

via 150.138.72.1 dev enp115s0f4u2 table 100

就说明回程路由已经正常。


上面的命令属于临时生效,系统重启后可能会丢失。


对,这里需要补充清楚。

100 号路由表不是系统默认“显示出来”的普通路由表,它属于 Linux 策略路由里的一个自定义路由表编号。

严格来说:

table 100

这个表可以直接使用,不一定需要提前创建。Linux 允许直接通过编号使用路由表,比如:

ip route add default via 150.138.72.1 dev enp115s0f4u2 table 100

即使 /etc/iproute2/rt_tables 里没有写 100 xxx,也可以生效。

但是为了方便以后查看和维护,建议在博客里加上这一段。


补充:100 号路由表是什么?

在 Linux 中,默认情况下常见的路由表有:

local
main
default

平时执行:

ip route

看到的其实主要是 main 路由表的内容。

而策略路由可以让系统根据不同条件查询不同的路由表,例如根据源 IP、目标 IP、网卡等条件分流。

在本次环境中,系统里存在这样一条规则:

32765:  from 150.138.72.230 lookup 100

这条规则的意思是:

如果数据包的源地址是 150.138.72.230,就去查询 100 号路由表。

这里的 100 就是一个自定义路由表编号。

需要注意的是,100 号路由表不一定会提前出现在配置文件里。Linux 允许直接使用数字编号作为路由表,例如:

ip route replace default via 150.138.72.1 dev enp115s0f4u2 table 100

这条命令执行后,table 100 就会有对应的路由内容。

如果想让这个路由表更容易识别,也可以给它起一个名字。编辑:

vim /etc/iproute2/rt_tables

在文件末尾添加:

100 net150

之后就可以用名字查看或操作这个路由表:

ip route show table net150

等价于:

ip route show table 100

也可以这样添加路由:

ip route replace 150.138.72.0/24 dev enp115s0f4u2 src 150.138.72.230 table net150
ip route replace default via 150.138.72.1 dev enp115s0f4u2 src 150.138.72.230 table net150

不过需要明确一点:

/etc/iproute2/rt_tables 只是给路由表编号起名字,方便阅读和管理。
真正决定路由是否生效的,是 ip rule 和对应 table 里的路由内容。

也就是说,下面这条规则:

from 150.138.72.230 lookup 100

负责告诉系统“源 IP 是 150.138.72.230 的流量去查 100 表”。

而下面这两条路由:

ip route replace 150.138.72.0/24 dev enp115s0f4u2 src 150.138.72.230 table 100
ip route replace default via 150.138.72.1 dev enp115s0f4u2 src 150.138.72.230 table 100

负责告诉系统“查 100 表时,应该从 enp115s0f4u2 这张网卡出去”。


前面已经看到系统里存在策略规则:

from 150.138.72.230 lookup 100

但是查看 100 号路由表时:

ip route show table 100

没有任何输出,说明 table 100 是空的。

这就会导致一个问题:系统已经知道源地址为 150.138.72.230 的流量应该去查 table 100,但这个表里没有默认路由,所以无法正确回包。

因此需要手动补全 100 号路由表:

ip route replace 150.138.72.0/24 dev enp115s0f4u2 src 150.138.72.230 table 100
ip route replace default via 150.138.72.1 dev enp115s0f4u2 src 150.138.72.230 table 100

第一条命令添加本地网段路由:

150.138.72.0/24 dev enp115s0f4u2 src 150.138.72.230

第二条命令添加默认出口:

default via 150.138.72.1 dev enp115s0f4u2 src 150.138.72.230

补全后,再次验证:

ip route get 8.8.8.8 from 150.138.72.230

如果输出类似:

8.8.8.8 from 150.138.72.230 via 150.138.72.1 dev enp115s0f4u2 table 100 uid 0
    cache

就说明 150.138.72.230 的回程路由已经正确走 enp115s0f4u2


已有10位网友发表了看法:

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。