You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Linux下强制本地目标数据包走外部以太网接口及解决ICMP Ping回复问题

Linux下强制本地目标数据包走外部以太网接口及解决ICMP Ping回复问题

首先得搞清楚你遇到的核心问题:Linux内核默认会把所有配置在本机的IP地址归为本地路由(local table),所以当你从本机一个IP发往另一个本机IP时,内核会直接走lo接口转发,完全忽略你配置的普通路由表条目——这就是为什么你抓包看不到流量经过交换机的原因。

下面分两步解决你的问题:

一、强制跨接口流量走外部交换机

要绕开内核的本地路由逻辑,我们需要结合策略路由和内核参数调整:

1. 开启允许本地地址路由到外部接口

首先修改内核参数,让内核允许发往本机IP的数据包通过外部网卡转发,而不是仅限lo

# 临时生效
sysctl -w net.ipv4.conf.all.route_localnet=1
sysctl -w net.ipv4.conf.enp1s0f0.route_localnet=1
sysctl -w net.ipv4.conf.enp1s0f1.route_localnet=1

2. 配置策略路由规则

我们需要给每个网卡的源IP指定专属的路由表,强制对应流量从指定网卡出站:

  • 首先在路由表配置文件里添加自定义表(方便识别):
    echo "100     enp1s0f0-table" >> /etc/iproute2/rt_tables
    echo "101     enp1s0f1-table" >> /etc/iproute2/rt_tables
    
  • 添加策略路由规则和路由条目:
    # 让从enp1s0f0的IP发出的流量使用自定义表100
    ip rule add from 172.16.0.100 table enp1s0f0-table
    # 给表100添加子网路由,指定从enp1s0f0出站
    ip route add 172.16.0.0/16 dev enp1s0f0 src 172.16.0.100 table enp1s0f0-table
    
    # 同理配置enp1s0f1
    ip rule add from 172.16.1.100 table enp1s0f1-table
    ip route add 172.16.0.0/16 dev enp1s0f1 src 172.16.1.100 table enp1s0f1-table
    

3. 验证配置

现在执行以下命令,应该能看到流量不再走lo了:

ip route get from 172.16.0.100 to 172.16.1.100

正常输出应该显示dev enp1s0f0而非dev lo

二、解决ICMP Ping无回复的问题

你提到ping能发送包但收不到回复,这和内核的反向路径过滤(rp_filter)、ARP行为配置有关,按以下步骤调整:

1. 关闭反向路径过滤

反向路径过滤会检查数据包的源IP是否符合入站网卡的路由,这里我们需要关闭严格检查:

# 临时生效
sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.enp1s0f0.rp_filter=0
sysctl -w net.ipv4.conf.enp1s0f1.rp_filter=0

2. 调整ARP行为避免地址混淆

因为两个网卡在同一子网,内核可能会混淆ARP请求/响应的绑定,需要调整参数让每个网卡只处理自己的IP:

# 临时生效
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
sysctl -w net.ipv4.conf.enp1s0f0.arp_ignore=1
sysctl -w net.ipv4.conf.enp1s0f0.arp_announce=2
sysctl -w net.ipv4.conf.enp1s0f1.arp_ignore=1
sysctl -w net.ipv4.conf.enp1s0f1.arp_announce=2
  • arp_ignore=1:只响应目标IP是当前网卡配置IP的ARP请求
  • arp_announce=2:发送ARP请求时,仅使用当前网卡的IP作为源IP

3. 允许外部接口接收本机IP的数据包

确保内核允许从外部网卡接收发往本机IP的数据包:

# 临时生效
sysctl -w net.ipv4.conf.all.accept_local=1
sysctl -w net.ipv4.conf.enp1s0f0.accept_local=1
sysctl -w net.ipv4.conf.enp1s0f1.accept_local=1

三、配置持久化(重启后生效)

上面的配置都是临时的,要让重启后依然生效:

1. 保存sysctl参数

创建/etc/sysctl.d/99-custom-routing.conf文件,写入以下内容:

net.ipv4.conf.all.route_localnet=1
net.ipv4.conf.enp1s0f0.route_localnet=1
net.ipv4.conf.enp1s0f1.route_localnet=1

net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.enp1s0f0.rp_filter=0
net.ipv4.conf.enp1s0f1.rp_filter=0

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.enp1s0f0.arp_ignore=1
net.ipv4.conf.enp1s0f0.arp_announce=2
net.ipv4.conf.enp1s0f1.arp_ignore=1
net.ipv4.conf.enp1s0f1.arp_announce=2

net.ipv4.conf.all.accept_local=1
net.ipv4.conf.enp1s0f0.accept_local=1
net.ipv4.conf.enp1s0f1.accept_local=1

执行以下命令加载配置:

sysctl --system

2. 持久化策略路由

创建systemd服务来开机自动配置策略路由:

  • 创建/etc/systemd/system/policy-routing.service文件:
    [Unit]
    Description=Custom Policy Routing Setup
    After=network.target
    
    [Service]
    Type=oneshot
    ExecStart=/bin/bash -c "ip rule add from 172.16.0.100 table enp1s0f0-table; ip rule add from 172.16.1.100 table enp1s0f1-table; ip route add 172.16.0.0/16 dev enp1s0f0 src 172.16.0.100 table enp1s0f0-table; ip route add 172.16.0.0/16 dev enp1s0f1 src 172.16.1.100 table enp1s0f1-table"
    ExecStop=/bin/bash -c "ip rule del from 172.16.0.100 table enp1s0f0-table; ip rule del from 172.16.1.100 table enp1s0f1-table"
    RemainAfterExit=yes
    
    [Install]
    WantedBy=multi-user.target
    
  • 启用并启动服务:
    systemctl daemon-reload
    systemctl enable --now policy-routing.service
    

现在你再测试telnet -b 172.16.0.100 172.16.1.100 22或者ping -I enp1s0f0 172.16.1.100,应该能看到流量经过交换机,并且ping能收到回复了。

备注:内容来源于stack exchange,提问作者Donlon

火山引擎 最新活动