多网卡与策略路由:请求从哪里进,响应从哪里出
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
目标:修复双网卡服务器的错误回程;能解释 ip rule、多路由表及源地址选路。先完成 路由基础,本篇仍在 Linux 隔离命名空间中执行。
1. 场景与初始证据#
下载 policy-lab.py,使用带 iproute2、Python 3、curl、tcpdump 的可丢弃 Linux VM。脚本没有公网出口,不修改主机路由。
客户端 lo=203.0.113.10/32
eth0=10.0.1.2/30 → R1:10.0.1.1 → 192.0.2.1 → 应用 eth0=192.0.2.10/24
eth1=10.0.2.2/30 → R2:10.0.2.1 → 198.51.100.1 → 应用 eth1=198.51.100.10/24
应用默认路由经 R1;HTTP 服务绑定 eth1 地址的 8080。sudo python3 policy-lab.py setup
sudo ip -n rp-app rule
sudo ip -n rp-app route get 203.0.113.10 from 198.51.100.10
sudo ip netns exec rp-client curl --noproxy '*' --fail --max-time 3 --interface 203.0.113.10 http://198.51.100.10:8080/health请求应成功,但 route get 显示响应走 eth0/R1,请求却经 eth1/R2 进入。脚本在实验命名空间内把 rp_filter 设为 0,故意允许这个错误设计显现;实际环境可能被反向路径检查或有状态防火墙丢弃。能 curl 成功不代表回程正确。
2. 用源地址选择独立路由表#
# 表 200:先确保网关直连,再添加默认路由。
sudo ip -n rp-app route add table 200 198.51.100.0/24 dev eth1 src 198.51.100.10
sudo ip -n rp-app route add table 200 default via 198.51.100.1 dev eth1
# 数字越小越先执行;不覆盖默认 priority 0 的 local 规则。
sudo ip -n rp-app rule add priority 100 from 198.51.100.10/32 lookup 200
sudo ip -n rp-app rule show
sudo ip -n rp-app route show table 200
sudo ip -n rp-app route get 203.0.113.10 from 198.51.100.10
sudo ip -n rp-app route get 203.0.113.10 from 192.0.2.10预期:源 198.51.100.10 走表 200、eth1/R2;源 192.0.2.10 仍走 main、eth0/R1。规则 priority 比较发生在查表层面;表内的最长前缀、metric 是另一层判断。ip-rule
终端 A 运行 sudo ip netns exec rp-r2 tcpdump -ni wan tcp port 8080,终端 B 重跑 curl;应在 R2 看到请求与响应。TCP(传输控制协议)响应沿已有 socket 的本地地址匹配源地址规则,不是 Linux 自动记住“入口网卡”来决定回程。
3. 四个常见误区#
| 误区 | 正确判断 |
|---|---|
| 两条 default 加不同 metric 就实现双线按源回程 | metric 通常只决定同表默认路径偏好;按源选择需规则/独立表 |
| 默认网关掉了会自动切到备用 | 远端故障不一定移除路由;metric 不是健康探测,需要路由协议或监控机制 |
| 表 200 有 default 就应该接管所有流量 | 只有匹配 ip rule 的流量才进入它;主机自己的其他源地址仍需正确规划 |
| 配了源规则,新建客户端连接一定走第二网卡 | 程序未绑定源地址时可能先按 main 选源;需明确绑定或额外策略,使用真实应用验证 |
更早的表若找到 default,就不会继续去后面的表找“更具体”的路由;表内没有匹配或命中 throw 才能继续后续规则。unreachable/blackhole 则终止并失败。fwmark 是包标记,不自动等于连接标记;生产若用标记选路,还要设计 conntrack(连接跟踪)的标记保存/恢复。
4. 验收与恢复#
删除单条规则,route get 应恢复走 R1;重新添加后回到 R2。不要执行全局 ip rule flush。
sudo ip -n rp-app rule del priority 100 from 198.51.100.10/32 lookup 200
sudo ip -n rp-app route get 203.0.113.10 from 198.51.100.10
sudo ip -n rp-app rule add priority 100 from 198.51.100.10/32 lookup 200继续 反向路径检查,或者 sudo python3 policy-lab.py cleanup 清理。本实验解决主机回程;在 AWS 多 ENI(弹性网卡)环境中,还要核对各子网路由、SG(安全组)、NACL(子网访问控制列表)及适用的源/目标检查。