What is rp_filter, what do the values 0, 1 and 2 mean, and when does it break things?
Show the answer
Say this first
rp_filter is reverse path filtering, the anti-spoofing check from RFC 3704. For each incoming packet the
kernel looks up the route back to the source. 1 strict: the best route back must point out the same
interface the packet arrived on, otherwise drop. 2 loose: the source only needs to be reachable through
some interface. 0 off. The effective value per interface is the higher of conf.all and conf.<iface>.
Strict mode silently drops asymmetric traffic on multihomed hosts.
Go deeper
Check it
$ sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.ens224.rp_filter
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.ens224.rp_filter = 1The kernel default is 0, but distributions ship their own value (1 or 2 are both common). Check, do not assume.
conf.default only applies to interfaces created after it is set.
Seeing the drops
sysctl -w net.ipv4.conf.all.log_martians=1
dmesg | grep martian
nstat -az TcpExtIPReversePathFilter
ip route get 10.0.99.21 from 10.0.50.10 iif ens224IPv4: martian source 10.0.99.21 from 10.0.50.10, on dev ens224
RTNETLINK answers: Invalid cross-device linkIn the martian log the first address is the destination and the second the source. "Invalid cross-device
link" from ip route get is the same check failing.
Typical breakage
- A server with a management NIC: monitoring traffic arrives on the management interface, but the route back to the monitoring subnet points out the data interface.
- Two uplinks with traffic coming in on the one that is not the default.
- Routers in an ECMP or asymmetric design.
Fixes, best first
- Make the routing symmetric (policy routing by source address).
- Loose mode (2) on that interface, which still drops sources with no route at all.
- 0 only when you understand why, for example inside some overlay or VPN designs.
They will ask next
You set rp_filter to 0 on ens224 and packets are still dropped. Why?
net.ipv4.conf.all.rp_filteris still 1, and the kernel uses the maximum ofalland the interface value. To relax one interface, set it to 2 (max of 1 and 2 is 2), or loweralland set the other interfaces explicitly.Is there an rp_filter for IPv6?
Not as a sysctl. IPv6 reverse path checks are done in the firewall: the
rpfiltermatch in ip6tables (-t raw -A PREROUTING -m rpfilter --invert -j DROP) orfib saddr . iif oif missing dropin nftables. firewalld adds one by default.
Traps
- Setting the interface value to 0 while
allis 1 and believing it is off. - Disabling rp_filter everywhere instead of fixing the asymmetric routing.