ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

多网卡路由不对称?rp_filter宽松模式与策略路由排查指南

2026/9/29 15:56:27 拓冰建站 浏览量
多网卡路由不对称?rp_filter宽松模式与策略路由排查指南 之前帮客户排查过一台双网卡服务器的故障现象很典型机器上同时配了两块网卡一块走办公网一块走业务网业务网那边的主机 ping 服务器能通但访问 TCP 服务就是卡死tcpdump 抓包又能看到请求进来了可应用层毫无反应。折腾了很久最后所有线索都指向了内核里的rp_filter参数。把它的值从严格模式切成宽松模式服务瞬间恢复。这篇文章不绕弯子直接聊透多网卡环境下的路由区分逻辑、rp_filter的三种工作模式以及如何用宽松模式快速定位这类网络问题。内容适合刚接触多网卡配置的运维新手也适合那些被网卡通了却不通折磨过的老手。1. 多网卡分不清路由的真相Linux选路根本不看网卡1.1 弱主机模型IP是机器共有的不是网卡私有的很多刚接触 Linux 多网卡配置的人都会有一个下意识的想法eth0 上配了 192.168.1.10eth1 上配了 192.168.2.10那么发给 192.168.1.10 的流量应该从 eth0 进来再从 eth0 回去发给 192.168.2.10 的流量走 eth1各管各的互不干扰。这个直觉在 Windows 里部分成立但在 Linux 上完全是另一套逻辑。Linux 网络栈是一个典型的弱主机模型IP 地址属于整个系统不属于某一块物理网卡。内核在收到一个数据包时不会先问这个包是从哪块网卡进来的而是先看这个包的目标 IP 是不是本机的。只要目标 IP 是本机任意一块网卡上的地址内核就认为这个包是给自己的然后交给上层协议栈处理。也就是说从 eth0 进来的包目标 IP 是 eth1 的地址Linux 内核照样收。这个机制本身不是 bug它是 TCP/IP 协议栈能灵活工作的基础。但问题恰恰出在灵活上——既然 IP 不绑定网卡那内核如何决定一个包应该从哪块网卡发出去答案是内核根本不看网卡它只查路由表。1.2 最长前缀匹配与回程路由决定通信成败的往往不是去程Linux 路由查找遵循最长前缀匹配规则。简单理解路由表里的每一条路由都带一个网段和掩码内核收到一个目标 IP 后在路由表里找出能覆盖这个 IP 的所有路由然后挑掩码最长也就是最精确的那条来用。比如路由表里有这两条192.168.1.0/24 走 eth00.0.0.0/0默认路由走 eth1现在要给 192.168.1.5 发包内核一比对192.168.1.0/24 这条掩码是 24 位比默认路由的 0 位更精确所以走 eth0。要发给一个外网 IP比如 223.5.5.5没有更精确的匹配就走默认路由 eth1。这里有个关键点必须理解发出去一个包容易但能不能收到回包取决于对端的路由怎么走。对端同样要查自己的路由表来决定回包发给谁。如果对端的回程路由和你的出口路径不一致就会出现包发出去了回包却丢了的诡异现象。我见过很多新人排查多网卡问题第一反应是看出口路由、ping 外网通不通这是没错的。但多网卡环境里真正卡住你的往往不是出口路由而是回程路由。假设你从业务网卡 eth1 接到一个请求源 IP 是 172.16.0.2但你机器上的默认路由只有 eth0 一条那么内核在回复这个包时查路由表发现 172.16.0.2 没有更精确的匹配就会顺着默认路由丢给 eth0。这个回包从 eth0 出去了对端看到来源网卡和请求时发往的网卡不是同一个于是一脸懵我明明发到 eth1 的怎么回包从 eth0 来了这时候如果没有额外机制兜底对端要么直接丢弃要么陷入无限重传。而你自己在服务器上 tcpdump又能看到回包确实发出去了于是陷入我明明在回包啊的困惑。1.3 多网卡环境的两种典型非对称场景实际运维中多网卡导致路由非对称的场景就两种最常见场景一默认路由只有一个出口机器有两块网卡eth0 配了外网 IP 和默认网关eth1 配了内网 IP 但没有配网关。内网主机往 eth1 发送请求时服务器收到的包没问题但回复时查路由表发现目标 IP内网主机不属于任何内网直连网段也没有针对内网网段的明细路由最终走了默认路由 eth0 出外网。这就是典型的进得来、出不去该走的出口。场景二多个网卡在同一网段或路由表里有等价路径这种更隐蔽。机器上有 eth0 和 eth1两个网卡都配了同一网段的 IP比如都是 192.168.10.x内核路由表里就有两条等价直连路由。包从 eth0 进来回复时内核做哈希或轮询选择一条出接口可能正好选了 eth1。对端的交换机如果没有开启对称路由检测通常问题不大但如果对端主机也开了反向路径校验就会把这个回包当成伪造源地址丢弃。这两种场景的共同特点是去程路径和回程路径不一致也就是非对称路由。在非对称路由环境下如果内核或者对端设备启用了严格的反向路径过滤通信就会失败。这时候rp_filter就要登场了。2. rp_filter 三种模式严格、宽松、关闭各拦什么2.1 严格模式rp_filter1回程出接口必须与入接口一致rp_filter的全称是 Reverse Path Filtering中文常翻译为反向路径过滤。它的作用是防止 IP 欺骗一个数据包从某块网卡进来内核会以这个包的源 IP 为目标 IP反向查一次路由表看看如果我要给这个源 IP 发包是不是应该从当前这块网卡出去。如果设置为严格模式值等于 1要求就非常苛刻反向查询得到的最佳路由出接口必须和这个包进来的网卡完全一致否则直接丢包。回到前面那个例子eth1 收到一个源 IP 为 172.16.0.2 的包内核以 172.16.0.2 为目标反向查路由表发现只有默认路由出接口是 eth0与当前入接口 eth1 不一致。严格模式下这个包在内核协议栈的 IP 接收阶段就直接被丢弃了根本不会向上递交给 TCP/UDP 层。所以你会看到什么现象tcpdump 抓包能看到客户端发的包确实到达了网卡但应用层没有任何响应因为内核压根没把包交上去。客户端那边自然是超时重试最终连接失败。严格模式是很多服务器发行版的默认行为所以默认情况下上面说的非对称路由场景就会导致网络不通。这也是为什么很多人加了一块网卡之后莫名其妙发现新网卡 Ping 不通但网卡物理链路明明是通的。2.2 宽松模式rp_filter2只校验源IP可达性宽松模式值等于 2就好说话得多。它同样以数据包的源 IP 反向查路由表但不要求出接口与入接口一致只要求只要路由表里有任何一条路由能到达这个源 IP就认为这个包是合法的放行。还是那个例子eth1 收到源 IP 172.16.0.2 的包反向查路由表即使最优路由是走 eth0 的默认路由但至少存在一条路径能到 172.16.0.2宽松模式判断通过包被交给上层协议栈处理。这就是标题里宽松模式的核心价值所在它允许非对称路由存在同时仍然能拦截那些源 IP 完全不可达的伪造包。对比一下模式检查逻辑对非对称路由的态度安全性严格1回程最佳路由的出接口必须等于入接口直接丢弃最高宽松2源 IP 在路由表里可达即可放行中等关闭0不做任何反向路径检查放行最低宽松模式不是不设防它还是会挡掉一部分明显非法的包。比如一个源 IP 是 203.0.113.5 的包从内网网卡进来但你的路由表里根本没有到 203.0.113.5 的路由不管走哪个接口宽松模式下照样丢弃。只有那些源 IP 合法但回程路径不对称的包宽松模式才会放行。2.3 关闭模式rp_filter0与配置生效规则all 和接口参数取最严格值还有一种配置是 0也就是完全关闭反向路径过滤。这个模式下内核不关心包是从哪来的只要目标地址是自己的就照单全收。关闭模式能解决所有因非对称路由引起的丢包问题但代价是服务器更容易被伪造源 IP 的流量攻击比如放大型的反射攻击。实际操作里踩坑最多的不是选哪个模式而是不知道rp_filter内核参数的聚合生效规则。Linux 的rp_filter参数有三种配置前缀net.ipv4.conf.all.rp_filternet.ipv4.conf.default.rp_filternet.ipv4.conf.具体网卡名.rp_filter内核实际取的是all和具体网卡两者之间的最大值也就是更严格的那个值生效。举个例子你把 all 设成了 1严格把 eth1 设成了 2宽松你以为 eth1 上是宽松模式实际上 eth1 仍然按严格模式运行因为max(1, 2)是 2等等——这里我要纠正一下网上很多说法不严谨。内核代码里的逻辑是在计算某个接口的有效rp_filter值时取conf-all.rp_filter和conf-ethX.rp_filter的最大值。如果 all1、eth12最大值是 2eth1 实际按宽松模式运行这是对的。但你如果想着把 all 保持默认 0只把 eth1 设成 1那 eth1 的有效值也是 1没问题。最怕的情况是all 已经是 1很多发行版默认如此你把 eth1 改成 2 想开宽松结果 eth1 上依然按严格模式运行因为max(1, 2)2——这里我又绕回来了算了直接说结论吧正确做法是要开宽松就把all也设成 2或者设成 0。只改单个网卡往往不生效因为发行版默认的all.rp_filter已经是 1。排查时一定要把all和每个网卡的参数都看一遍。这个坑我至少见过三次有人改完net.ipv4.conf.eth1.rp_filter2sysctl -p也执行了但问题依旧折腾半天才发现all.rp_filter1把 eth1 的设置给顶掉了。3. 宽松模式实测一次多网卡故障的完整排查链路3.1 故障现场eth0 通外网eth1 接内网内网却连不上直接还原一次真实排障过程你就能理解宽松模式到底是怎么测试网络的。客户服务器是双网卡eth0公网 IP网关指向公网出口外网访问正常eth1内网 IP 192.168.50.10/24网关为空内网不设网关内网有一台办公主机 192.168.50.20需要访问服务器上的一个应用端口。问题很简单办公主机 Ping 192.168.50.10 能通但 TCP 连接永远卡在 TCP 握手应用完全连不上。先说明 Ping 能通这一点特别误导人。ICMP 是内核协议栈直接处理的如果入包被rp_filter丢弃那 Ping 应该也不通。但实际中可能出现 Ping 却通的情况因为某些系统配置里 ICMP 走的是另一套处理路径或者办公主机 Ping 用的是网卡直连地址恰好触发了对称路由。不管怎样Ping 通不代表 TCP 就通这个案例里 Ping 能通反而让排查绕了远路。3.2 排查步骤从 ping/tcpdump 到抓出 rp_filter我给的排查路径是这样的第一步确认回程路由。在服务器上执行ip route get 192.168.50.20这条命令非常关键它直接告诉你如果我要给 192.168.50.20 发包内核会选择哪个出接口。结果出来是192.168.50.20 dev eth0 ...也就是说服务器回复给 192.168.50.20 的包居然要绕道 eth0 出去而不是从 eth1 直连出去。这就确认了非对称路由存在。原因是服务器上可能有一条覆盖 192.168.50.0/24 的静态路由指向了 eth0或者 eth1 上没起来直连路由。第二步验证入包是否被丢。在服务器上抓 eth1 的包tcpdump -i eth1 host 192.168.50.20可以看到办公主机的 SYN 包确实到达了网卡。但此时再看服务器上的 TCP 连接状态没有任何 192.168.50.20 的半连接记录。说明包在协议栈就被丢掉了根本没到 TCP 层。第三步查 rp_filter 的值。sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.default.rp_filter net.ipv4.conf.eth0.rp_filter net.ipv4.conf.eth1.rp_filter输出大概是这样net.ipv4.conf.all.rp_filter 1 net.ipv4.conf.default.rp_filter 1 net.ipv4.conf.eth0.rp_filter 0 net.ipv4.conf.eth1.rp_filter 0注意关键卡点出现了eth0 和 eth1 都明确写成 0关闭但 all 的值是 1按照内核的聚合规则所有网卡的有效rp_filter值都是max(1, 0)1也就是严格模式。这就是包被丢弃的根本原因。3.3 切到宽松模式验证为什么网络立刻通了把 all 改成 2临时验证sysctl -w net.ipv4.conf.all.rp_filter2改完这一条办公主机再连服务瞬间通了。这个瞬间本身就是有力的诊断证据物理链路没问题路由表没问题防火墙规则也没问题唯一的变量就是反向路径过滤策略。为什么切到宽松模式就通了因为宽松模式不要求回程出接口与入接口一致。办公主机 192.168.50.20 的源 IP 在路由表里合法可达虽然要走 eth0 绕行内核判定这个包不是伪造的放行交给上层。TCP 握手完成回包依然走ip route get查出来的 eth0 出口办公主机上如果没有反向路径过滤自然能正常收到。这里也可以反向推断一次如果改成宽松模式后问题依旧那说明丢包原因不在rp_filter而是防火墙、应用监听地址、或者对端的反向路径校验就需要往别的方向排查。整个排查链路里宽松模式充当的角色不是一个治本方案而是一个隔离变量用的探针它把反向路径过滤从嫌疑名单里摘出去让你能确认问题根因。这也是使用宽松模式测试网络这句话的真正含义。4. 多网卡路由区分的根治方案策略路由与多路由表4.1 为什么宽松模式只是测试手段宽松模式能解决问题但代价是放行了一些本可以被严格模式拦截的包。对一台公网服务来说长期开着宽松模式等于降低了对伪造源 IP 攻击的防御能力。所以在生产环境里宽松模式只适合作为临时验证手段验证完根因之后应该考虑更体面的治本方案。治本的方向只有一条让回程路由变得对称。换句话说从 eth1 进来的流量回复时也必须从 eth1 出去。这就要用到策略路由。默认的 Linux 路由机制是目的地路由只看目标 IP不看来源。多网卡区分路由的痛点恰恰在于来源——我希望根据来源网卡或者来源 IP 决定走哪条路。这就是策略路由做的事。策略路由的核心组件是两个ip rule和自定义路由表。4.2 ip rule 多路由表让回程按来源走指定出口先看两个概念路由表Linux 本身支持多张路由表常见的有main、default和local。你可以创建自己的表比如给 eth1 单独建一张表里面写凡是来源是内网网段默认网关走 eth1。策略规则ip rule决定哪些包查哪张路由表。每条规则可以匹配来源地址、入接口、fmark 等条件并指定跳转到某张路由表里查找。整体流程是这样的数据包到来 → 内核按优先级逐条匹配ip rule→ 命中某条规则后去对应的路由表里做最长前缀匹配 → 找到出接口。实际操作以之前的场景为例给 eth1 建独立的回程路由表先给新表起个名字。编辑/etc/iproute2/rt_tables加一行100 eth1_table然后添加策略规则和路由# 来源为 192.168.50.0/24 的包跳到 eth1_table 查路由 ip rule add from 192.168.50.0/24 lookup eth1_table pref 100 # 在 eth1_table 里写入直连路由和默认路由 ip route add 192.168.50.0/24 dev eth1 src 192.168.50.10 table eth1_table ip route add default via 192.168.50.1 dev eth1 table eth1_table这里的核心逻辑是凡是从 192.168.50.0/24 网段来的包内核在回复时只查 eth1_table不再去看 main 表。eth1_table 里明确写了这个网段直连 dev eth1所以回包就会从 eth1 出去路由对称了。验证一下ip route get 192.168.50.20 from 192.168.50.10 iif eth1这个命令模拟一个来自 192.168.50.10、到达本机的包回程应该如何走。预期结果是出接口为 eth1与入接口一致。这样即使rp_filter保持严格模式也不会丢包了。4.3 策略路由配置示例与持久化策略路由的持久化有两种做法写脚本开机自启或者在/etc/iproute2/rt_tables配合 NetworkManager 或 systemd-networkd 的 routing rule 配置来实现。不同发行版差异很大我习惯用一个独立脚本简单可控#!/bin/bash # /etc/network/if-up.d/eth1_policy_routing # 或者 systemd service 方式 ip rule add from 192.168.50.0/24 lookup eth1_table pref 100 ip route add 192.168.50.0/24 dev eth1 src 192.168.50.10 table eth1_table 2/dev/null ip route add default via 192.168.50.1 dev eth1 table eth1_table 2/dev/null需要注意策略路由的ip rule规则是幂等的重复添加会报错所以脚本里最好先判断规则是否存在或者用ip rule del from 192.168.50.0/24 lookup eth1_table 2/dev/null先删除再加。实际生产环境里网卡重启、NetworkManager 重载时可能会清掉自定义路由表和规则最好用系统的 network dispatcher 钩子来保证鲁棒性。5. 多网卡网络测试的经验补充与避坑清单5.1 我常用的网络测试工具组合多网卡问题排查里最怕的就是凭感觉改配置。我自己的习惯是固定一套工具组合按顺序跑ip route get—— 第一利器快速判断去程和回程的出口比人脑想路由表靠谱得多。ip rule show—— 看有没有策略路由在生效尤其是那些计划外的规则经常是它们抢了默认路由。tcpdump 特定端口/ICMP—— 判断包是否到达网卡。注意 tcpdump 看到包不代表内核接受了包要看上层协议栈的行为。sysctl 查看 rp_filter 全家桶—— 一定要把all和所有网卡的值都列出来再计算聚合结果。nc 或 curl 做真实连接测试—— 拿端到端的连接结果说话比 Ping 可靠得多。我见过有人在多网卡机器上 ping 了一大通都通就下了网络没问题的结论结果实际上业务端口全是卡的。建议测试时始终用真实业务流量验证ICMP 只作为链路是否 up 的参考。5.2 宽松模式的安全边界能开多久、哪些场景别开需要明确一点宽松模式不是长期配置选项而是临时诊断选项。除了安全性的考虑宽松模式开着还会掩盖很多网络问题。比如你新接了一条专线或者换了交换机本应该出现非对称路由告警但宽松模式下包照样通问题就被淹没了。有几个场景特别不建议开宽松模式直接暴露在公网的 Web/数据库服务器。严格模式能挡住一部分源 IP 伪造的扫描和反射放大攻击把它关了等于削弱一层防护。有等保或安全合规要求的业务环境。很多安全基线检查会强查rp_filter的值不符直接扣分。对端也启用了严格反向路径校验的网络。这种情况光在自己这边开宽松没用回包到对端还是会被丢必须靠策略路由根治。5.3 多网卡环境踩坑汇总清单最后把多网卡路由相关的坑集中总结一下都是我实际踩过或者帮别人擦过屁股的坑现象解法只改具体网卡 rp_filter不改 all明明配了宽松模式实际仍是严格两个都要改确认聚合值多个网卡同网段等价路由导致回程随机选接口用 ip rule 按入接口绑路由表默认路由唯一内网业务网卡收到的包回程走外网给业务网卡建独立路由表网卡重启后自定义路由丢失策略路由临时生效重启消失写持久化脚本挂到 network 钩子防火墙规则掩盖真实问题改完 rp_filter 还是不通先查 iptables/nftables 日志确认是否被独立规则拦截还有一个容易被忽略的点云主机和虚拟化平台的多网卡行为。大部分云平台虚拟网卡的接收队列行为、底层交换机的对称路由策略与物理机差异不小。你在物理机上改rp_filter能生效在云主机上可能因为虚拟化层的 VPC 网关策略而失效。遇到云上的多网卡非对称路由问题建议先看云平台文档有没有启用多网卡对称路由的开关再谈内核参数。多网卡路由问题看着玄乎本质就是去程和回程路径不一致 反向路径过滤策略过严的组合。理解了这条底层逻辑再看到网卡通了却连不上的故障你至少不会再盲猜了。先用ip route get看路径再用宽松模式验证rp_filter最后用策略路由治本——这套组合拳打下来基本能解决九成以上的多网卡疑难杂症。