Linux 双网卡网络回包问题
一、背景
办公网:172.16.246.171/24
内网:192.168.0.0/16
最近我在使用 ESXI 和 vCenter 虚拟机工具,由于服务器网卡不是很多,只有4张卡,并且2个电口2个光口,由于没有使用光口交换机只有电口交换机,所以也就使用的电口网卡
由于创建虚拟机不想影响到办公网络,于是我就想创建一台虚拟机,给虚拟机使用两张虚拟网卡(端口组),这样一来区分开虚拟机外网地址(办公网)和虚拟机内网地址,这样一来后面的虚拟机想要上网的话可以,以 192.168.0.1 为网关,然后路由转发到 172.16.246.0/24 网络环境中,从而实现 nat 上网。
二、现象
当我配置好网卡之后,发现只有处于办公网络(二层)网络下才能正常 ping 通虚拟机的外网地址,但是如果经过路由器来访问虚拟机的办公地址的话是无法 ping 通的


关闭内网地址网卡恢复正常


三、初步怀疑
ping 请求包 可能从三层网络经过路由器进入,进行路由规则找到 172.16.246.0/24 网络地址池,然后经过查找 ARP 协议找到对应的 Mac 地址最后下发到虚拟机上,此时是通过 ens192 进入的入向流量。但是回包的时候,系统可能从 ens224 网卡进行的回包,但是这是一个仅主机内网的地址,他无法经过上层路由进行汇报,因为上游路由协议中没有这个内网的相关 ARP 协议以及路由条目。
1. 策略路由(PBR)
设置一个策略路由,让 172.16.246.0/24 网段的流量始终走 ens192
# 临时生效
[root@localhost ~]# ip rule add from 172.16.246.171 table 100
[root@localhost ~]# ip route add default via 172.16.246.1 dev ens192 table 100
# 永久生效
[root@localhost ~]# vim /etc/sysconfig/network-scripts/rule-ens192
ip rule add from 172.16.246.171 table 100
ip route add default via 172.16.246.1 dev ens192 table 100
[root@localhost ~]# systemctl restart network
2. 验证效果

小结论:这也就是为什么二层网络中你能 ping 通,三层网路中你无法ping 通,因为二层网络设备之间互相通信是相互寻找 Mac 地址,而不会经过路由条目。
四、配置端口映射
如果想通过外网地址登陆过着访问到内网地址的服务可以使用端口映射
1. 创建规则
[root@localhost ~]# iptables -t nat -A PREROUTING -d 172.16.246.171 -p tcp --dport 2021 -j DNAT --to-destination 11.0.1.11:22
[root@localhost ~]# iptables -t nat -A POSTROUTING -d 11.0.1.11 -p tcp --dport 22 -j MASQUERADE
[root@localhost ~]# iptables -t nat -vnL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 361 packets, 21607 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DNAT tcp -- * * 0.0.0.0/0 172.16.246.171 tcp dpt:2021 to:192.168.0.11:22
[root@localhost ~]# iptables -t nat -vnL POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 3889 209K mt_rtr_4_n_rtr all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 MASQUERADE tcp -- * * 0.0.0.0/0 192.168.0.11 tcp dpt:222. 测试
从其他的机器上登陆,本地是不可以的
[root@mirrors ~]# ssh -p 2021 172.16.246.171
The authenticity of host '[172.16.246.171]:2021 ([172.16.246.171]:2021)' can't be established.
ECDSA key fingerprint is SHA256:ceiwc3ljUuyHsVARtkszD21dlojadTVczEbGXxcPFUE.
ECDSA key fingerprint is MD5:09:1d:10:01:2b:cf:bb:4c:d8:4f:49:43:d8:37:2f:fe.
Are you sure you want to continue connecting (yes/no)? 四、为什么会这样
Linux 的 路由决策机制 是基于 最长前缀匹配(LPM)+ Metric 权重:
两张网卡都匹配 IP 包,但是
192.168.0.0/16和172.16.246.0/24都是直连网络。Metric 小的优先,ens192 的 Metric 是
100,ens224 是101,所以默认流量优先走ens192。但 返回流量(Reply Packets) 不一定会走
ens192,因为:Linux 可能根据源地址选择 ens224 进行回包,导致问题。
这个现象在 Linux 的 反向路径过滤(rp_filter)未启用 时更容易发生。
五、多种办法
1. 策略路由(PBR)
ip rule 让 172.16.246.171 只走 ens192
[root@localhost ~]# ip rule add from 172.16.246.171 table 100
[root@localhost ~]# ip route add default via 172.16.246.1 dev ens192 table 1002. arp_ignore & arp_filter 限制 ARP 响应
arp_ignore = 1让 Linux 只在绑定该 IP 的网卡上响应 ARP 请求,防止错误的网卡响应。arp_filter = 1让 Linux 根据最佳路由选择正确的接口响应 ARP,避免流量走错。
在多网卡环境(如 ens192 和 ens224)下,强烈建议开启这两个参数,可以有效避免 非对称路由和 ARP 响应异常。
# 临时生效
[root@localhost ~]# echo 1 > /proc/sys/net/ipv4/conf/ens224/arp_ignore
[root@localhost ~]# echo 1 > /proc/sys/net/ipv4/conf/ens224/arp_filter
# 永久生效
[root@localhost ~]# cat >> /etc/sysctl.conf <<EOF
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.ens192.arp_ignore = 1
net.ipv4.conf.ens224.arp_ignore = 1
EOF
[root@localhost ~]# sysctl -p3. 启用 rp_filter(反向路径过滤)
rp_filter 是 Linux 内核中的 反向路径过滤机制,用于防止 源地址欺骗(IP Spoofing) 和 非对称路由 问题。
工作原理
当 rp_filter 启用时,Linux 内核会检查 进入数据包的源 IP 地址,如果发现该 IP 不能从同一接口返回,就会直接丢弃该数据包。
# 临时生效
[root@localhost ~]# echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
[root@localhost ~]# echo 1 > /proc/sys/net/ipv4/conf/default/rp_filter
# 永久生效
[root@localhost ~]# cat >> /etc/sysctl.conf <<EOF
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
EOF
[root@localhost ~]# sysctl -p