理解 net.ipv4.conf.all.rp_filter

理解 net.ipv4.conf.all.rp_filter

Comzyh:一些坑了我的 Linux 内核网络参数zhuanlan.zhihu.com图标

前面文章提到了,rp_filter 本身会过滤反向路由不通的数据包。用通俗的话解释一下,就是NIC1 有 incoming 数据包,Reverse Path Filtering 模块会将数据包的源地址和目的地址(srcIP->dstIP)调转过来成为(dstIP->srcIP),然后在路由表中查找这个(dstIP->srcIP) 的路由,如果出口恰好是 NIC1 那么 rp_filter 测试通过,否则不通过/丢弃。


有的时候我们使用一些策略路由可能会让rpfilter表现出我们不希望的结果。例如:打上 fwmark 的数据包通过 NIC2 出去,但是 NIC2 回来的数据包肯定是没有 fwmark 的,rp filter 就会反向路由查找失败,导致包被丢弃。

如何避免这种问题呢,StackOverflow 给出了一种用 conntrack 记录出包,然后在包回来的时候恢复 fwmark 的方法,原理上可行,不过我没有测试。

Linux policy routing - packets not coming backserverfault.com图标


看了 StackOverflow 上的回答,大部分都不推荐直接关闭 rp_filter。不过我的情况,关闭特定端口的 rp_filter 没什么问题。

我尝试sysctl net.ipv4.conf.nic2.rp_filter=0 来关闭 NIC2 的 rp filter,发现没有效果。调整 net.ipv4.conf.all.rp_filter=0也不行。只有二者都调整为0才可以。但是我又担心all.rp_filter=0会关闭所有NIC的rp filter,一直没有这样运行。

读内核文档才知道:只要 net.ipv4.conf.nic2.rp_filter 和 net.ipv4.conf.all.rp_filter 有一个是1,那么 NIC2 的 rp filter 就会被启用。原文摘录如下:

kernel.org/doc/Document

rp_filter - INTEGER
0 - No source validation.
1 - Strict mode as defined in RFC3704 Strict Reverse Path
Each incoming packet is tested against the FIB and if the interface
is not the best reverse path the packet check will fail.
By default failed packets are discarded.
2 - Loose mode as defined in RFC3704 Loose Reverse Path
Each incoming packet's source address is also tested against the FIB
and if the source address is not reachable via any interface
the packet check will fail.

Current recommended practice in RFC3704 is to enable strict mode
to prevent IP spoofing from DDos attacks. If using asymmetric routing
or other complicated routing, then loose mode is recommended.

The max value from conf/{all,interface}/rp_filter is used
when doing source validation on the {interface}.


Default value is 0. Note that some distributions enable it
in startup scripts.

所以如果只想关闭一个接口的 rp filter,应该把 net.ipv4.conf.all.rp_filter 调整为0,并开启其他接口的 rp filter,再调整目标接口的 rp filter 为0.

发布于 04-13