跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

Linux 内核参数 rp_filter 完全解析

一、什么是 rp_filter?

rp_filter 是 Linux 内核中用于反向路径过滤(Reverse Path Filtering) 的安全机制,核心功能是防止 IP 地址欺骗(IP Spoofing)攻击。

其工作原理如下:

当系统收到一个 IP 数据包时,内核会提取数据包的源 IP 地址,然后拿这个源 IP 地址去查询路由表(FIB,Forwarding Information Base),看系统如果要发送数据包到这个源 IP,应该从哪个本地网卡出去。接着,内核将路由表返回的“出口网卡”与“实际接收该数据包的网卡”进行比对:

  • 如果两者一致:校验通过,数据包正常进入协议栈处理。
  • 如果两者不一致:校验失败,数据包被直接丢弃。

核心逻辑可以概括为:系统回复这个数据包时准备走的路,必须和这个数据包进来的路是同一条。如果路径不一致,内核就认为源 IP 可能是伪造的。

二、三种工作模式

rp_filter 提供三个可选值:

值模式名称行为描述
0关闭验证不进行任何反向路径检查,所有数据包照单全收
1严格模式要求路由表查询到的出口网卡与接收网卡完全一致。这是大多数 Linux 发行版的默认值
2宽松模式只检查源 IP 是否“可达”(即路由表中存在通往该 IP 的路由),不要求进出同一网卡

宽松模式(=2)不要求进出同口,因此能兼容非对称路由环境,同时保留了对完全不可达的伪造源 IP 的基本防御能力。

三、用三个具体例子说明 rp_filter 的判断逻辑

为了说清楚 rp_filter 到底在检查什么,我们用一台双网卡服务器来演示。假设服务器配置如下:

  • eth0:IP 地址 192.168.1.10/24
  • eth1:IP 地址 10.0.0.10/24
  • 路由表:
  192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10
  10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.10
  default via 10.0.0.1 dev eth1

关键理解:rp_filter 查询路由表时用的是数据包的源 IP 地址,跟发送方有几块网卡、MAC 地址是什么完全没有关系。它只问一个问题——“如果我要回复这个源 IP,应该走哪个本地网卡?”

例一:同网段放行

数据包从 eth0 进来,源 IP 是 192.168.1.100。

检查步骤结果
接收网卡eth0
用源 IP 192.168.1.100 查路由表匹配 192.168.1.0/24 dev eth0
路由表返回出口网卡eth0
比对:接收网卡 vs 出口网卡eth0 == eth0,放行

这个例子里,发送方的 IP(192.168.1.100)恰好落在 eth0 的直连网段内,所以路由表告诉内核“去这个 IP 走 eth0”,而数据包也确实是从 eth0 进来的,路径对称,校验通过。

例二:不同网段丢弃

数据包从 eth0 进来,源 IP 是 10.0.0.100。

检查步骤结果
接收网卡eth0
用源 IP 10.0.0.100 查路由表匹配 10.0.0.0/24 dev eth1
路由表返回出口网卡eth1
比对:接收网卡 vs 出口网卡eth0 ≠ eth1,丢弃

这里源 IP 10.0.0.100 落在 eth1 的直连网段内,路由表告诉内核“去这个 IP 走 eth1”,但数据包却是从 eth0 进来的。内核认为路径不一致,包可能是伪造的,直接丢弃。

例三:陌生网段走默认路由丢弃

数据包从 eth0 进来,源 IP 是 8.8.8.8。

检查步骤结果
接收网卡eth0
用源 IP 8.8.8.8 查路由表不匹配任何直连网段,匹配默认路由 default via 10.0.0.1 dev eth1
路由表返回出口网卡eth1
比对:接收网卡 vs 出口网卡eth0 ≠ eth1,丢弃

源 IP 8.8.8.8 是一个公网地址,服务器没有任何网卡属于这个网段,路由表通过默认路由将去往 8.8.8.8 的流量指向 eth1。由于接收网卡是 eth0,路径不一致,校验失败丢弃。如果默认路由指向的是 eth0,则 eth0 == eth0,校验通过,放行。

四、一张表总结所有情况

接收网卡数据包源 IP路由表匹配结果出口网卡rp_filter=1 裁决
eth0192.168.1.100匹配 192.168.1.0/24eth0✅ 放行
eth010.0.0.100匹配 10.0.0.0/24eth1❌ 丢弃
eth08.8.8.8匹配默认路由(dev eth1)eth1❌ 丢弃
eth0172.16.0.100无默认路由,查不到无❌ 丢弃(查无结果即失败)
eth110.0.0.100匹配 10.0.0.0/24eth1✅ 放行
eth1192.168.1.100匹配 192.168.1.0/24eth0❌ 丢弃

从表中可以清晰看到:放行的唯一条件是路由表查到的出口网卡 == 实际接收网卡。其他所有情况——查到不同网卡、查不到路由、只能匹配默认路由——都会导致数据包被丢弃。

五、什么情况下需要修改 rp_filter?

1. 非对称路由(最常见)

当数据包的往返路径不一致时,严格模式必然丢包。典型场景包括:

  • 多网卡服务器:请求从 eth0 进入,但默认网关在 eth1 上,响应包从 eth1 发出。
  • LVS-DR 负载均衡模式:请求经过 LVS 到达后端服务器,响应绕过 LVS 直接返回客户端,对后端服务器来说就是非对称路由。
  • BGP 多线机房:不同运营商的流量从不同网卡进出,路径天然不对称。

上述场景下,如果用 tcpdump 能在网卡上抓到请求包,但应用程序完全收不到,很可能是 rp_filter 在静默丢包。

2. 策略路由(Policy Routing)冲突

当系统根据 fwmark、源 IP 等条件选择不同路由表时,rp_filter 的严格模式容易产生冲突。因为反向路径验证时,策略路由所需的匹配条件(如 iif、mark)通常无法满足,导致校验失败。

3. VPN 和隧道技术(IPsec、GRE)

隧道流量的封装和解封装会改变数据包的路径特征,反向路径过滤可能将正常隧道流量误判为欺骗包。由于 IPsec 等协议自身已经提供了更强的反欺骗能力,这种情况下关闭 rp_filter 是合理选择。

4. 多播数据包接收

通过 AF_PACKET 或 UDP 多播接收数据时,多播包的源 IP 可能是任意地址。如果该源 IP 不在接收网卡的直连网段内,或只能匹配默认路由,严格模式就会丢弃数据包。实践中大量案例表明,多播接收不通时,将 rp_filter 设为 0 或 2 是最常见且有效的解决方案。

5. 容器和网络命名空间环境

Docker、Kubernetes 等容器环境中,网络插件(如 Calico、Flannel)的流量往往跨越多个网络命名空间,网络路径复杂。很多容器网络解决方案在初始化时会主动关闭 rp_filter,以确保流量不被误拦截。

六、如何查看和修改 rp_filter

查看当前配置

# 查看所有接口的 rp_filter 配置
sysctl -a | grep rp_filter

# 查看全局配置
sysctl net.ipv4.conf.all.rp_filter

# 查看特定网卡的配置
sysctl net.ipv4.conf.eth0.rp_filter

临时修改(立即生效,重启失效)

# 设置为宽松模式
sysctl -w net.ipv4.conf.eth0.rp_filter=2

# 完全关闭
sysctl -w net.ipv4.conf.eth0.rp_filter=0

永久修改

编辑 /etc/sysctl.conf 文件:

# 只修改特定网卡(推荐)
net.ipv4.conf.eth0.rp_filter = 2

# 或全局修改(影响所有网卡,不推荐)
net.ipv4.conf.all.rp_filter = 2

执行 sysctl -p 使配置生效。

关于 all、default 与具体接口的关系

  • conf/all/rp_filter:全局开关,影响所有已存在的网卡。
  • conf/default/rp_filter:新创建网卡的默认值,不影响已有网卡。
  • conf/eth0/rp_filter:仅影响 eth0 这一块网卡。

从 Linux 2.6.31 内核开始,实际生效值是 all 和具体接口配置的 最大值(max)。也就是说,如果 net.ipv4.conf.all.rp_filter=1,即使某个接口设为 0,该接口依然会执行严格校验。

因此,要关闭或放宽某个特定网卡的 rp_filter,必须同时确保 all.rp_filter 不为严格模式(设为 0 或 2)。

七、不同场景的推荐配置

场景推荐配置说明
普通单网卡服务器rp_filter = 1保持默认,安全性最高
双网卡/多网卡服务器rp_filter = 2宽松模式,兼容非对称路由
接收多播数据rp_filter = 0 或 2避免源 IP 不在直连网段时被丢弃
LVS-DR 后端服务器rp_filter = 0响应直通客户端,必须关闭
VPN/隧道网关rp_filter = 0隧道协议自身保证安全
容器/Pod 网络保持网络插件默认值插件通常会按需配置

八、修改 rp_filter 的安全考量

关闭 rp_filter 或使用宽松模式会降低系统对 IP 欺骗攻击的防御能力。RFC 3704 标准推荐在网络边缘(如边界路由器)启用严格模式的 uRPF,以防范 DDoS 和 IP Spoofing。

在实际操作中,应遵循以下原则:

  1. 优先使用宽松模式(=2)而非完全关闭(=0):宽松模式仍然会检查源 IP 是否可达,只是不苛求进出同口,能在安全性和兼容性之间取得平衡。
  2. 精准修改而非全局关闭:如果只有 eth0 存在问题,只修改 conf/eth0/rp_filter,不要轻易修改 conf/all/rp_filter。
  3. 注意 all 和具体接口的叠加关系:关闭某个具体接口时,务必确认 all.rp_filter 不会覆盖掉这个设置。
  4. 修改后必须验证:用 tcpdump 确认数据包能到达网卡,用应用程序确认能正常接收,必要时用 dropwatch 等工具确认丢包是否消失。

九、历史演进

rp_filter 在内核中经历了数次重要变化:

  • 2.6 早期内核:all 与具体接口采用 AND 逻辑,必须两者都开启才生效。
  • 2.6.31 版本:改为 max() 取最大值,all 和具体接口中取较大值作为实际生效值。这一逻辑沿用至今。
  • 3.3 版本:rp_filter 实现从协议栈迁移到 Netfilter 框架的 PREROUTING 钩子点,使得严格模式和宽松模式都能在框架内实现。

了解这些变化有助于理解为什么 all 和具体接口的配置关系如此特殊。

十、总结

rp_filter 是 Linux 网络栈中一项“守卫森严”的安全机制,它的设计初衷是防止 IP 地址欺骗,在单网卡、对称路由的环境中工作良好。但在多网卡、负载均衡、多播接收、容器网络等复杂场景下,它会因为“路径不一致”而丢弃大量本应正常处理的数据包。

理解 rp_filter 的核心在于记住一件事:它检查的不是多播组地址,不是发送方的 MAC 地址,而是数据包的源 IP 地址。 它拿着这个源 IP 去查路由表,看系统回复时走哪个网卡,再和接收网卡做比对。只有两者一致才放行,其他所有情况——查到不同网卡、查不到路由、匹配默认路由——都会导致数据包被丢弃。

排查网络不通问题时,如果 tcpdump 能在网卡上抓到包但应用程序收不到,rp_filter 是应该首先排查的嫌疑对象之一。

作者

老丹

关注我
其他文章
上一个

一招搞定:如何将 Git 项目同时推送到多个远程仓库

下一个

多播数据包:tcpdump 能抓到,应用程序收不到 —— 完整排查指南

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • Ubuntu 防火墙迁移指南:从 UFW 到 firewalld 的完整实践 2026年9月12日
  • Nano 编辑器完全操作指南:从入门到熟练 2026年9月12日
  • SSCG:让自签名证书不再“危险”的生成工具 2026年9月12日
  • Ubuntu Samba 服务安装与配置完全指南 2026年9月12日
  • 从零开始:用 Docker 部署 Jellyfin 并启用英特尔核显硬件加速 2026年9月11日

文章分类

  • C/C++开发 (22)
  • Docker容器 (5)
  • Linux工具包 (17)
  • Linux服务配置 (50)
  • Linux系统 (16)
  • OpenWrt路由 (3)
  • Shell脚本 (3)
  • 代码管理 (1)
  • 安防技术 (4)
  • 数据安全 (36)
  • 未分类 (1)
  • 网络协议 (25)
  • 计算机理论 (23)
  • 音视频技术 (5)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号