Routing

為什麼這個命令會破壞網路?ip rule add from 0.0.0.0/8 unreachable

  • November 12, 2020

我偶然發現這ip rule add from 0.0.0.0/8 unreachable會破壞網路。甚至不能在同一個區域網路上 ping 通。我不明白為什麼。

我記得0.0.0.0/8IPv4 地址塊是保留的,只能由使案例如 DHCP 的機器使用來查找其真實 IP。這不是我的情況,所有主機都是靜態配置的。我根本沒想到會看到0.0.0.0地址。即使使用 DHCP,此類數據包也僅限於目前 LAN 而不會路由。

那麼為什麼該規則會阻止正常流量呢?

當套接字連接(即:使用connect(2)系統呼叫)到 IPv4 目標時,它可以:

通常,各種路由條目決定了源地址最終會變成什麼,因為它不能保持 0.0.0.0:要麼是路由條目中暗示的src參數,要麼是為該路由選擇的介面上的主地址。

但是由於附加的路由規則(可能只是from 0.0.0.0/32 unreachable為了相同的結果),表main中的初始路由查找永遠不會發生:

$ ip rule
0:  from all lookup local
32765:  from 0.0.0.0/8 unreachable
32766:  from all lookup main
32767:  from all lookup default

路由規則遍歷將在條目優先級 32765 處停止,並且永遠不會到達查找路由表的下一個條目。僅綁定套接字,包括在添加此路由規則之前未綁定套接字的已建立連接,因為源地址隨後更新為實際地址,並且它們正在進行的流量仍然可以正常工作。


例如,假設系統在介面eth0上的地址為 192.0.2.2/24 ,然後嘗試在偵聽 5555/tcp 的服務上連接到 192.0.2.1:

socat tcp4:192.0.2.1:5555 -

將失敗,因為此路由查找現在失敗:

$ ip route get to 192.0.2.1
RTNETLINK answers: Network is unreachable

(與 相同ip route get from 0.0.0.0 to 192.0.2.1

儘管有虛假的路由規則,但首先顯式綁定到 192.0.2.2 會成功:

socat tcp4:192.0.2.1:5555,bind=192.0.2.2 -

出於同樣的原因,此路由查找仍然成功:

$ ip route get from 192.0.2.2 to 192.0.2.1
192.0.2.1 from 192.0.2.2 dev eth0 uid 1000 
   cache 

from源與附加路由規則不匹配。

如果最初不存在虛假路由規則,那麼第一個範例將成功,並且如果稍後添加,則連接的套接字將不再受到虛假路由規則的影響:0.0.0.0 地址將不再出現在任何查找中這種聯繫。


核心原始碼中存在一些明確的答案,但這有點超出了我徹底遵循​​的能力。這是我可以告訴connect(2)沒有的bind(2)

  • connect(2)最後將使用0.0.0.0 作為萬用字元源地址ip_route_connect()(例如,在核心中:tcpudp 或原始案例……)來確定路由和實際源。
  • 然後它將使用前一個函式(tcpudp 或 raw …)的結果更新套接字的源。
  • 但是添加了偽造的路由規則後,ip_route_connect()最終fib_rules_lookup()會執行一個匹配 0.0.0.0 源的不可達規則並且會connect(2)失敗。

引用自:https://unix.stackexchange.com/questions/619119