如果請求的 IP 地址與另一個(禁用)介面相關聯,Linux 不會回复 ARP 請求消息
我有一台 PC(核心3.2.0-23-generic),它已
192.168.1.2/24
配置為eth0
介面,並且還使用介面192.168.1.1
和192.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:~#
只有在我刪除
tun0
interface( ) 後,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
表中找到了一條路線,因此我們停止搜尋路線,並且不費心檢查main
ordefault
表。為什麼要多個表?
至少,能夠打字
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,看看你能做什麼。