Networking

如果請求的 IP 地址與另一個(禁用)介面相關聯,Linux 不會回复 ARP 請求消息

  • February 20, 2020

我有一台 PC(核心3.2.0-23-generic),它已192.168.1.2/24配置為eth0介面,並且還使用介面192.168.1.1192.168.1.2地址tun0

root@T42:~# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
   inet6 ::1/128 scope host
      valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
   link/ether 00:16:41:54:01:93 brd ff:ff:ff:ff:ff:ff
   inet 192.168.1.2/24 scope global eth0
   inet6 fe80::216:41ff:fe54:193/64 scope link
      valid_lft forever preferred_lft forever
3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN
   link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
4: irda0: <NOARP> mtu 2048 qdisc noop state DOWN qlen 8
   link/irda 00:00:00:00 brd ff:ff:ff:ff
5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
   link/ether 00:13:ce:8b:99:3e brd ff:ff:ff:ff:ff:ff
   inet 10.30.51.53/24 brd 10.30.51.255 scope global eth1
   inet6 fe80::213:ceff:fe8b:993e/64 scope link
      valid_lft forever preferred_lft forever
6: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc pfifo_fast state DOWN qlen 100
   link/none
   inet 192.168.1.1 peer 192.168.1.2/32 scope global tun0
root@T42:~# ip route show dev eth0
192.168.1.0/24  proto kernel  scope link  src 192.168.1.2 
root@T42:~# 

如上所示,tun0在管理上被禁用(ip link set dev tun0 down)。現在,當我收到 ARP 請求時192.168.1.2,PC 不會回复這些請求:

root@T42:~# tcpdump -nei eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:30:34.875427 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:36.875268 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:39.138651 00:1a:e2:ae:cb:b7 > 00:1a:e2:ae:cb:b7, ethertype Loopback (0x9000), length 60:
^C
3 packets captured
3 packets received by filter
0 packets dropped by kernel
root@T42:~#

只有在我刪除tun0interface( ) 後,PC 才會回复on interfaceip link del dev tun0的 ARP 請求。192.168.1.2``eth0

路由表在之前和之後看起來完全一樣ip link del dev tun0

root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# ip link del dev tun0
root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# 

下面的路由條目已使用ip link set dev tun0 down命令刪除:

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.1.2     0.0.0.0         255.255.255.255 UH        0 0          0 tun0

然而,雖然路由表在命令之前和之後完全一樣ip link del dev tun0,但核心將做出的實際路由決策卻不是:

T42:~# ip route get 192.168.1.1
local 192.168.1.1 dev lo  src 192.168.1.1 
   cache <local> 
T42:~# ip link del dev tun0
T42:~# ip route get 192.168.1.1
192.168.1.1 dev eth0  src 192.168.1.2 
   cache  ipid 0x8390
T42:~# 

這是預期的行為嗎?為什麼核心忽略路由表?

確切地說,您的路由表沒有被忽略。它被更高優先級的路由表否決。

這是怎麼回事

您在鍵入時看到的路由表ip route show並不是核心使用的唯一路由表。實際上,預設情況下有三個路由表,按照命令顯示的順序進行查找ip rule

# ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

您最熟悉的表是main,但優先級最高的路由表是local。該表由核心管理以跟踪本地和廣播路由:換句話說,該local表告訴核心如何路由到它自己介面的地址。它看起來像這樣:

# ip route show table local
broadcast 127.0.0.0 dev lo  proto kernel  scope link  src 127.0.0.1
local 127.0.0.0/8 dev lo  proto kernel  scope host  src 127.0.0.1
local 127.0.0.1 dev lo  proto kernel  scope host  src 127.0.0.1
broadcast 127.255.255.255 dev lo  proto kernel  scope link  src 127.0.0.1
broadcast 192.168.1.0 dev eth0  proto kernel  scope link  src 192.168.1.2
local 192.168.1.1 dev tun0  proto kernel  scope host  src 192.168.1.1
local 192.168.1.2 dev eth0  proto kernel  scope host  src 192.168.1.2
broadcast 192.168.1.255 dev eth0  proto kernel  scope link  src 192.168.1.2

查看該行引用tun0。這就是導致您的奇怪結果的原因route get。它說 192.168.1.1 是本地地址,這意味著如果我們想向 192.168.1.1 發送 ARP 回复,這很容易;我們把它寄給我們自己。並且由於我們在local表中找到了一條路線,因此我們停止搜尋路線,並且不費心檢查mainordefault表。

為什麼要多個表?

至少,能夠打字ip route而不是看到所有那些“明顯”的路線使顯示器混亂(嘗試route print在 Windows 機器上打字)是件好事。它還可以作為一些針對錯誤配置的最小保護:即使主路由表已經混淆,核心仍然知道如何與自己對話。

(為什麼首先要保留本地路由?所以核心可以對本地地址使用與其他所有內容相同的查找程式碼。它在內部使事情變得更簡單。)

使用這種多表方案,您還可以做其他有趣的事情。特別是,您可以添加自己的表,並指定搜尋時的規則。這稱為“策略路由”,如果您曾經想根據其地址路由數據包,這就是在 Linux 中的方法。

如果您正在做特別棘手或實驗性的事情,您可以通過在命令中local指定來自己添加或刪除路由。但是,除非您知道自己在做什麼,否則您可能會混淆核心。當然,核心仍然會繼續添加和刪除它自己的路由,所以你必須注意確保你的路由不會被覆蓋。table local``ip route

最後,如果您想一次查看所有路由表:

# ip route show table all

有關更多資訊,請查看ip-rule(8)手冊頁或iproute2 文件。你也可以試試Advanced Routing and Traffic Control HOWTO,看看你能做什麼。

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