How Linux Kernel rp_filter Works

实验环境:

  • RaspberryPi (ArchLinux)
    • eth0: MiWiFi (优先路由)
    • wlan0: OpenWrt
  • MiWiFi: 二级路由
  • OpenWrt: 一级路由 (静态路由: 192.168.31/24 -> 192.168.1.254)

实验步骤:

  • 在OpenWrt上ping树莓派eth0地址
  • 通过启用/停用树莓派eth0的rp_filter参数
  • 观察ping及tcpdump的结果

/etc/systemd/network/eth0.network

[Match]
Name=eth0

[Network]
DHCP=yes

[DHCP]
RouteMetric=512  

/etc/systemd/network/wlan0.network

[Match]
Name=wlan0

[Network]
DHCP=yes

[DHCP]
RouteMetric=1024  

Routing Table

$ ip route show
default via 192.168.31.1 dev eth0  proto dhcp  src 192.168.31.231  metric 512  
default via 192.168.1.1 dev wlan0  proto dhcp  src 192.168.1.111  metric 1024  
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.111  
192.168.1.1 dev wlan0  proto dhcp  scope link  src 192.168.1.111  metric 1024  
192.168.31.0/24 dev eth0  proto kernel  scope link  src 192.168.31.231  
192.168.31.1 dev eth0  proto dhcp  scope link  src 192.168.31.231  metric 512

$ ip route get 192.168.1.1
192.168.1.1 dev wlan0  src 192.168.1.111  
    cache

$ ip route get 192.168.31.1
192.168.31.1 dev eth0  src 192.168.31.231  
    cache

Reverse Path Filtering: ON

# on 192.168.31.231
$ sysctl -w net.ipv4.conf.eth0.rp_filter=1
$ tcpdump -ni eth0 icmp # good
$ tcpdump -ni wlan0 icmp # bad

# on 192.168.1.1
$ ping 192.168.31.231 # bad

Reverse Path Filtering: OFF

# on 192.168.31.231
$ sysctl -w net.ipv4.conf.eth0.rp_filter=0
$ tcpdump -ni eth0 icmp # good
$ tcpdump -ni wlan0 icmp # good

# on 192.168.1.1
$ ping 192.168.31.231 # good