為什麼這個命令會破壞網路?ip rule add from 0.0.0.0/8 unreachable
我偶然發現這
ip rule add from 0.0.0.0/8 unreachable
會破壞網路。甚至不能在同一個區域網路上 ping 通。我不明白為什麼。我記得
0.0.0.0/8
IPv4 地址塊是保留的,只能由使案例如 DHCP 的機器使用來查找其真實 IP。這不是我的情況,所有主機都是靜態配置的。我根本沒想到會看到0.0.0.0
地址。即使使用 DHCP,此類數據包也僅限於目前 LAN 而不會路由。那麼為什麼該規則會阻止正常流量呢?
當套接字連接(即:使用
connect(2)
系統呼叫)到 IPv4 目標時,它可以:
- 在連接
bind(2)
之前到特定地址- 或不綁定,這與綁定到用作佔位符的INADDR_ANY aka 0.0.0.0 相同,直到確定要使用的實際源地址。
通常,各種路由條目決定了源地址最終會變成什麼,因為它不能保持 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()
(例如,在核心中:tcp或udp 或原始案例……)來確定路由和實際源。- 然後它將使用前一個函式(tcp、udp 或 raw …)的結果更新套接字的源。
- 但是添加了偽造的路由規則後,
ip_route_connect()
最終fib_rules_lookup()
會執行一個匹配 0.0.0.0 源的不可達規則並且會connect(2)
失敗。