Reverse Path Filtering,Linux 内核对接收到的数据包的反向路由校验过滤,主要用于防止 IP 地址欺骗攻击。本文主要介绍该校验机制、系统配置方式以及过滤包查看方法。
反向路由校验机制
反向路由校验,即在网卡收到数据包后,校验该数据包的反向路由是否匹配,如不匹配,则丢弃该包。具体流程如下:
- 对于网卡收到的数据包,Linux 内核会检查该数据包的源 IP
- 参照当前的路由表,判断如以该数据包的源 IP 作为目的 IP,返回路径的路由选择是否与当前接收接口一致
- 如不一致,则认为该数据包可能是伪造的,丢弃该数据包
如下图,eth1 网卡开启了严格的 rp_filter 检查,此时 eth1 网卡收到源 IP 为 172.16.19.24
的包,rp_filter 检查如果以 172.16.19.24
为目的 IP,根据路由表,匹配的网卡应该为 eth0,而不是收到包的 eth1,因此判断该数据包可能伪造源 IP,丢弃该包。
Linux 内核参数
net.ipv4.conf.XXX.rp_filter
rp_filter 为 Linux 用于设置反向路由校验机制的内核参数,共有三种可配置值 0、1、2,
rp_filter = 0
:关闭反向路由校验。rp_filter = 1
:开启严格的反向路由校验。如果反向路由不是最佳路由,则丢弃该包。rp_filter = 2
:开启松散的反向路由校验。对于收到的数据包,只检查其源 IP 是否可达,即反向路由是否可通(任意网卡均可),如果反向路径不通,则丢弃该包。
rp_filter 分为三类:all
、default
、特定网卡。
default
用于生成网卡时设置默认的 rp_filter 值- 每张网卡的 rp_filter 取
conf/{all,interface}/rp_filter
中的最大值
如下面配置,eth0 的 rp_filter 为 1(取 all 和 eth0 中的最大值),eth1 的 rp_filter 为 2(取 all 和 eth1 中的最大值)
1 | net.ipv4.conf.all.rp_filter = 1 |
查看 rp_filter
1 | root@ubuntu2404:~# sysctl -a | grep rp_filter |
设置 rp_filter
临时设置(重启后失效)
1 | root@ubuntu2404:~# sysctl -w net.ipv4.conf.ens160.rp_filter=1 |
tcpdump 与 rp_filter
tcpdump 依旧可以抓到被 rp_filter 过滤掉的包。
下图的五层网络分层模型中,收包是从下到上,发包是从上到下。
tcpdump 运行在链路层的网络设备层,而 rp_filter 运行在协议栈的网络层,对于收包流程来说,tcpdump 先于 rp_filter 进行,所以即使数据包会被 rp_filter 过滤掉,依旧可以通过 tcpdump 抓到该数据包。
rp_filter 日志
默认情况下,内核并不会记录被 rp_filter 过滤掉的包,但可以通过 iptables 添加日志规则,模拟和预测哪些包会被 rp_filter 丢弃。
添加 iptables 日志规则(如需删除,则把其中的 -A
改成 -D
)
1 | iptables -t raw -A PREROUTING -m rpfilter --invert -j LOG --log-prefix "RP_FILTER_DROP: " |
查看添加的 iptables 日志规则
1 | root@ubuntu2404:~# iptables -t raw -L PREROUTING -v |
查看内核日志
1 | dmesg -T | grep "RP_FILTER_DROP" |
1 | root@ubuntu2404:~# dmesg -T | grep "RP_FILTER_DROP" | tail -20 |