CentOS 9 双公网网卡回程路由异常的排查与处理
服务器上有两张公网网卡:
enp10s0 45.125.47.173/24 enp115s0f4u2 150.138.72.230/24
其中:
enp10s0是主公网网卡;enp115s0f4u2是第二张公网网卡;默认路由走的是
enp10s0;需要让
150.138.72.230的流量从enp115s0f4u2正常进出。
查看当前路由:
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位网友发表了看法:
发表评论