前阵子帮同事调一台双网卡工控机,一块网卡接办公网、一块接生产网,测跨网段吞吐时丢包丢到怀疑人生。抓包看到回包明明已经到主机了,内核就是不认,最后根源落在反向路径过滤和路由出口选择上。这类问题太典型了——多网卡环境下,系统根本不关心你“插了几块网卡”,它只关心“这个目标地址该从哪张表查到、用哪个接口出门、回包又该从哪回来”。所以我想借这个标题,把多网卡路由区分这件事从原理到实操完整梳理一遍,重点讲讲“宽松模式”测试到底松了什么、什么时候该开、什么时候开了反而害你。适合双网卡工控机、实验室测试台、多出口网关这类场景的运维和网工直接抄。
1. 多网卡的路由选择逻辑:最长匹配与默认路由为什么总打架
1.1 路由表其实是“目标网段查找表”
要弄懂多网卡怎么区分路由,先把路由表当成一张表格来看。每个有效表项基本包含四要素:目标网络、子网掩码、网关、出接口。系统收到一个IP包,拿目的IP去跟路由表逐条比对,掩码越长、匹配越精确的表项优先级越高,这叫最长前缀匹配;如果没有精确匹配,最终落到默认路由(0.0.0.0/0)上。
打个比方,这就像快递分拣中心:地址写到“北京市”也能分拣,写到“海淀区某街道某号院某栋某室”就直接给快递员,后者一定更准。路由表里同时存在192.168.2.0/24和0.0.0.0/0时,发往192.168.2.55的报文一定走24位掩码那条,而不是默认出口。这就是“多网卡区分路由”的第一条基础:不是网卡自己选了流量,是路由表替流量选了网卡。
实操里我常让人先跑一条命令,把表头看明白再动手。Windows下是route print -4,Linux下是ip route show table main。一张典型桌面机路由表大概长这样:
| 目标网络 | 掩码 | 网关 | 接口 |
|---|---|---|---|
| 0.0.0.0 | 0.0.0.0 | 192.168.1.1 | 192.168.1.10 |
| 192.168.2.0 | 255.255.255.0 | 192.168.2.1 | 192.168.2.10 |
| 192.168.1.0 | 255.255.255.0 | on-link | 192.168.1.10 |
这种表是最理想的状态:192.168.2.x精确走内网卡,其余流量默认走办公网。多数项目出问题,恰恰是第二张表里的默认路由多写了一条,或者两条默认路由的度量值没拉开。
1.2 两块网卡、两条默认路由,流量到底走谁
多网卡环境最常见的就是两块网卡都从DHCP拿到了网关,于是路由表里同时躺两条0.0.0.0/0。Windows的处理方式是保留接口Metric更小那条,大的那条直接标为不活跃;Linux则更“激进”,多条默认路由可以同时存在并轮询使用,这就会出现一个很邪门的现象:访问外网时同一个TCP连接的前几个包从eth0出去,后几个包从eth1出去,对端看到源地址跳来跳去,直接给你RST。
很多人把这种现象叫“多网卡负载均衡”,说句实话这是误解。系统层面的多条默认路由只是“轮询选路”,不是什么高级负载均衡,它既不看连接状态也不看链路占用,把视频会议、长连接、跨网段测速这类流量放上去,基本必炸。真正想做网卡负载均衡,标准做法是NIC Teaming配合交换机LACP,或者在上层业务里做多连接分发,而不是靠路由表里躺两条default。
这里还想强调一个很多人忽略的“回程路由”。一个数据包能从A网卡出去,不等于对方的回包能同样回到A网卡。对端服务器要根据它自己的路由表决定回包走哪个接口、源IP是谁,如果两端都有双网卡,很容易出现“去程走eth0,回程走eth1”的非对称路径。单网卡时代没人关心这事,多网卡一介入,非对称路由就成了丢包重灾区,后面讲宽松模式时主要就是跟它较劲。
1.3 什么时候必须上策略路由
如果两个网段完全独立、没有交集,比如办公网192.168.1.0/24和生产网10.20.30.0/24,静态路由加两条就够用了。但现实中有三类场景,普通静态路由根本搞不定:
- 要求特定源IP段固定从特定出口走,比如研发网段强制走专线、其他网段走宽带;
- 两个出口要访问同一个目标网段,必须把流量按来源或按端口分流;
- 服务器有多块网卡,希望“谁进的门谁送回”,即从网卡A进的请求,回包也走网卡A。
这些场景需要的就是策略路由(PBR),核心是让系统不只看“目的IP”,还能看“源地址、协议、端口、报文标记”等条件来选路由表。Windows这边没有原生完善的策略路由界面,更多靠静态路由和接口Metric配合;Linux用ip rule加自定义路由表,非常灵活。第2部分我会把两边都能落地的配置一步步写出来。
2. 实操:Windows和Linux下把路由权重握在自己手里
2.1 Windows:静态路由加接口跃点数双管齐下
Windows下多网卡分流的第一板斧是加静态路由。假设内网网段是192.168.2.0/24,内网网关是192.168.2.1,内网网卡IP是192.168.2.10,这时用管理员权限执行:
route add 192.168.2.0 mask 255.255.255.0 192.168.2.1 metric 5-p参数顺手带上,否则重启机器后这条路由就没了:
route add -p 192.168.2.0 mask 255.255.255.0 192.168.2.1 metric 5路由Metric越小优先级越高,给它5就是为了让它明显压过默认路由。删错路由用route delete 192.168.2.0 mask 255.255.255.0 192.168.2.1。
第二板斧是调整网卡接口跃点数。光加路由还不够,很多人碰到的问题是两个网卡都有网关,默认路由互相抢。最省心的处理是:把内网网卡的“默认网关”从TCP/IP设置里直接清掉,让内网网卡只负责静态路由覆盖的网段,外网网卡独占默认路由。清不掉网关的情况下,就手动控制两条默认路由的Metric。在网卡的“高级TCP/IP设置”里取消“自动跃点数”,把内网网卡填成10、外网网卡填成20,Windows自然偏向Metric更小的外网卡。
PowerShell下操作更直观,先看当前接口索引和Metric:
Get-NetIPInterface -AddressFamily IPv4 | Sort-Object InterfaceMetric然后单独设置:
Set-NetIPInterface -InterfaceAlias "以太网 2" -InterfaceMetric 10这条命令比图形界面右键点半天高效太多,批量配多台测试机尤其好用。实测下来,只要两条默认路由的Metric拉开差距,再把精准网段用静态路由锁死,Windows侧的多网卡路由混乱基本能压下去。
2.2 Linux:多路由表实现按源地址分流
Linux下的思路换成“多路由表加策略规则”。先把直连路由和默认路由按出口网卡拆成两张独立表,比如table 100代表办公网eth0,table 200代表生产网eth1:
ip route add 192.168.1.0/24 dev eth0 src 192.168.1.10 table 100 ip route add default via 192.168.1.1 dev eth0 table 100 ip route add 192.168.2.0/24 dev eth1 src 192.168.2.10 table 200 ip route add default via 192.168.2.1 dev eth1 table 200然后写ip rule规则,按源地址选路由表:
ip rule add from 192.168.1.0/24 lookup 100 ip rule add from 192.168.2.0/24 lookup 200ip rule的优先级从0开始,数字越小的规则越先命中,可以用pref显式指定顺序,比如ip rule add pref 100 from 192.168.1.0/24 lookup 100。这样从192.168.1网卡进来的业务,查表时只看得见办公网出口;从192.168.2网卡进来的,只会走生产网出口。表里没有其他干扰项,回包路径天然对称。
如果要对特定端口做策略路由,可以给报文打标记再选表,比如让访问22端口的流量固定走生产网:
iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 1 ip rule add fwmark 1 lookup 200持久化时,Debian/Ubuntu把表名写进/etc/iproute2/rt_tables,把ip rule和ip route写进/etc/network/interfaces的pre-up脚本里;CentOS/RHEL则用/etc/sysconfig/network-scripts/route-ethX加rule-ethX。不熟的话建议先用一个临时脚本把命令跑通,再固化,避免开机网络起不来。
3. “宽松模式”到底松了什么:rp_filter与弱主机模型
3.1 严格模式、宽松模式、关闭模式三档对比
多网卡场景里,Linux默认的反向路径过滤(rp_filter)是很多人丢包的真正元凶。它有三种模式:
| 模式 | 值 | 行为 | 适用场景 |
|---|---|---|---|
| 关闭 | 0 | 不做反向路径校验,任意接口收到的包都接受 | 明确信任内网,网络路径天然不对称 |
| 严格 | 1 | 收到源地址为S的包时,系统认为到达S应走的接口必须等于收包接口,否则丢弃 | 单出口、防IP伪造,Linux多数发行版默认值 |
| 宽松 | 2 | 只要源地址S在系统任意路由表中可达,就接收,不强求接口一致 | 双网卡、多出口、合法非对称路由的场景 |
严格模式的设计初衷是防IP源地址伪造。一个包从eth0进来,但按路由表计算,发回源地址的最佳路径明明应该从eth1出,这一看就有问题,严格模式下直接丢。问题在于,双网卡环境里“合法”的非对称路径很常见:你的服务器从两个运营商接入,外部访问可能从电信口进来,回程却从联通口走,这种架构在严格模式下就会莫名丢包。
3.2 双网卡跨网段测试打不通,把rp_filter临时调到2
说个我调试时的真实场景。主机A有eth0(192.168.1.10)和eth1(192.168.2.10),主机B同样有双网卡192.168.1.20和192.168.2.20。我从A的eth0去ping B的eth1地址192.168.2.20,报文到达B的eth1后,B查反向路径发现源地址192.168.1.10应该从eth0返回,现在却从eth1进来,严格模式下直接丢弃,于是表现为“同一个局域网,跨网段ping不通,单网卡ping都正常”。
这种场景临时调整一下就好:
sysctl -w net.ipv4.conf.all.rp_filter=2 sysctl -w net.ipv4.conf.eth0.rp_filter=2 sysctl -w net.ipv4.conf.eth1.rp_filter=2注意all和具体网卡两个值都要写,很多发行版不会自动把all的配置下发到每个接口。改完立即生效,再执行ping -I eth0 192.168.2.20,能通则进一步证明丢包就是反向路径过滤导致的。
永久生效写入/etc/sysctl.d/99-rp-filter.conf:
net.ipv4.conf.all.rp_filter = 2 net.ipv4.conf.default.rp_filter = 2 net.ipv4.conf.eth0.rp_filter = 2 net.ipv4.conf.eth1.rp_filter = 2然后sysctl --system加载。这里必须提醒一句:宽松模式只适合你明确知道网络存在合法非对称路径的情况。如果是为了让伪造源地址的包混进来,那这个口子开得就非常危险。生产环境开启前先确认所有网络设备都在你的管控边界内。
3.3 Windows弱主机模型对应问题与调整
Windows网络栈默认走“弱主机模型”:收到目的IP不是本网卡IP、但属于本机其他网卡IP的包,系统照样接收;发送报文时也不强制从最匹配路由的网卡发出。所以在Windows里做双网卡跨网段测试,通常不会像Linux严格模式那样直接丢包,回包会被“宽大处理”,这就是Windows版的天然宽松模式。
如果希望模拟Linux严格模式,可以用netsh关掉单块网卡的弱主机接收和发送:
netsh interface ipv4 set interface "以太网 2" weakhostreceive=disabled weakhostsend=disabled恢复用enabled。但我在实际项目里不推荐普通测试机去关它,Windows走弱主机模型至少保证业务不中断,真正要解决路由对称问题,重点还是看静态路由和Metric配置。
3.4 测试工具里的“宽松模式”和路由优化谁先谁后
很多打流测试工具和网络仪表里也有“宽松模式”的选项,字面意思是放宽对报文源地址、目的地址、端口号的匹配校验。初看很方便,双网卡环境下勾上它,很多“丢包”现象立刻消失。但这里有个大坑:工具宽松模式只能让打流软件“看得过去”,底层内核和交换机该丢还是会丢。它掩盖的是路由不对称、反向路径过滤、防火墙状态连接不匹配这些真实问题,不是把问题解决了。
我自己的优先级是这样的:先用宽松模式做快速定位,确认丢包和路由有关;然后把路由、接口Metric、策略路由调整到位;最后关掉宽松模式用严格模式重测,拿到的数据才是真实可用的带宽和时延。工具里留宽松模式做日常摸底没问题,但验收测试、高负载测试一定要用严格模式。
4. 多网卡测试网络的常见坑与排查顺序
4.1 四个高频故障场景及修复
| 症状 | 可能原因 | 快速定位 | 解决办法 |
|---|---|---|---|
| 双网卡接上后外网时通时断 | 两条默认路由抢出口 | Windows跑route print -4,Linux跑ip route show default | 只保留一条默认路由,另一网卡删网关或调大Metric |
| 同网段两块网卡设了不同IP,ping时通时不通 | ARP表在两个网卡间抖动 | arp -a看到同一IP对应两个MAC,或目标设备MAC在漂移 | 尽量避免同网段多网卡,必要时禁掉其中一块网卡 |
| Linux下跨网段ping单通,回包到不了应用 | rp_filter严格模式丢弃非对称回包 | tcpdump -i eth1 host 对端IP,能看到回包被内核丢掉 | 临时sysctl -w net.ipv4.conf.all.rp_filter=2,再改策略路由 |
| 关掉工具的宽松模式测试立刻掉速 | 去程与回程路径不对称,底层丢包 | 两侧同时抓包,对比同一连接的进出接口 | 绑定源IP打流,或配置ip rule按源网段选表 |
同网段多网卡的问题我再多说一句:只要两块网卡IP属于同一网段,目标设备发ARP请求时,两块网卡都可能应答,目标设备的ARP表就在两个MAC之间反复横跳,丢包就成了必然。这不属于路由配置问题,是组网设计问题,无解时只能禁用其中一块网卡。
4.2 双网卡连接测试失败的标准排查顺序
遇到双网卡连不通,我建议按下面顺序走,不要一上来就改路由表。跳步很容易改乱。
- 确认物理层:
ipconfig /all或ip addr看网卡是否UP,有无IP、网关; - 验证直连:同一网段内互ping,排除网线、交换机、防火墙问题;
- 检查路由表:找多余默认路由、错误网关、接口Metric乱序;
- 跨网段试探:
tracert/traceroute看报文走到哪一跳消失; - 抓包定位丢包位置:在目标主机跑
tcpdump -i any host 来源IP,分辨“包没到”和“包到了回不去”; - 查看反向路径相关项:Linux检查
sysctl net.ipv4.conf.all.rp_filter,Windows检查网卡弱主机设置和防火墙; - 最后再看设备双工、速率协商、网卡驱动版本这些“低级但致命”的细节。
这套顺序至少帮我省下半天无效加班。很多双网卡问题的真相都是第5步之后才浮出来的:包早就到了,只是内核看了一眼网卡不对,直接丢了。
5. 一点个人体会
多网卡环境里,路由表决定“出口”,反向路径过滤决定“入口”,两者缺一不可。我遇到过太多工程师盯着一堆网线、驱动、交换机折腾半天,结果一句rp_filter就解决了。宽松模式是个好用的诊断工具,但它只能告诉你“反向路径是不是有问题”,不能替代真正的策略配置。现在我处理这类问题的固定套路是:先固定Metric、删掉冲突的默认路由、把精准网段用静态路由锁死;Linux再按需上ip rule策略路由;全部弄完才开打流工具做严测。这套组合拳在工控机、测试台、实验室组网里反复验证过,直接复制用就行。