ARP是如何工作的

ARP是如何工作的

原文:https://www.slashroot.in/how-does-arp-address-resolution-protocol-work

作者:Sarath Pillai

原文發表日期:2016年10月10日

翻譯:tommwq

譯文:http://tommwq.tech/blog/?p=358

網絡中的兩臺機器可以相互通信,如果它們知道對方的物理地址。雖然計算機程序使用IP地址來發送和接收消息,但實際的底層通信總是通過物理地址進行的。

我們先來了解一下通信如何通過電線進行。我們嘗試ping一臺google的公共DNS服務器並捕獲網絡數據包,看看源地址和目標地址是什麼。

tcpdump是一個用於捕獲網絡數據包並顯示其內容的工具。如果你不熟悉tcpdump,我建議你閱讀下面的文章,瞭解tcpdump的基礎知識。

閱讀:Linux中的tcpdump命令示例

root@ip-10-12-2-73:~# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=39 time=9.16 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=39 time=9.28 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=39 time=9.31 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=39 time=9.32 ms

在ping的同時,我們使用另一個shell會話在同一服務器上捕獲網絡數據包,使用的命令是 tcpdump -n host 8.8.8.8 。 使用參數-host 8.8.8.8只會捕獲源或目標爲8.8.8.8的數據包(同時因爲-n參數,tcpdump輸出中顯示IP地址,而不是DNS名字)。

root@ip-10-12-2-73:~# tcpdump -n host 8.8.8.8
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:39:41.531390 IP 10.12.2.73 > 8.8.8.8: ICMP echo request, id 16331, seq 1, length 64
21:39:41.540342 IP 8.8.8.8 > 10.12.2.73: ICMP echo reply, id 16331, seq 1, length 64
21:39:42.531815 IP 10.12.2.73 > 8.8.8.8: ICMP echo request, id 16331, seq 2, length 64
21:39:42.540840 IP 8.8.8.8 > 10.12.2.73: ICMP echo reply, id 16331, seq 2, length 64

tcpdump命令的輸出非常明顯。它顯示了從我們的服務器(10.12.2.73)發出的一系列ICMP echo請求,以及隨後從google(8.8.8.8)返回的響應。

由於8.8.8.8不在同一個網絡中,如果沒有網關,我的服務器無法直接訪問到。因此ping 8.8.8.8的請求會經過我的網關。網關的地址可以用命令 route -n 得到。

root@ip-10-12-2-73:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.12.2.1       0.0.0.0         UG    0      0        0 eth0
10.12.2.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0

我們的網關是10.12.2.1。在輸出的第一行就清楚地看到。爲了訪問任意IP地址(用0.0.0.0表示),數據包會通過10.12.2.1的網關。

因此,雖然我們需要訪問的是8.8.8.8,我們需要經過10.12.2.1(因爲它是網關)。但是爲什麼tcpdump輸出沒有顯示10.12.2.1(網關)的任何跟蹤?

tcpdump顯示源地址是10.12.2.73,目標地址爲8.8.8.8。由於8.8.8.8不是本地網絡的一部分,我們必須通過10.12.2.1的網關訪問它。所以這裏顯示的目標地地址應該是10.12.2.1,對不對?否則我們的數據包如何到達網關?

ping命令可以正常工作。因此它肯定通過網關來訪問8.8.8.8(因爲沒有其他出口)。但數據包中的網關地址到底在哪裏呢。數據包顯示目標地址是8.8.8.8,但是它是如何到達網關的呢?

這正是物理地址(MAC地址)使用的地方。

隨着ping 8.8.8.8繼續執行,讓我們在另一個會話上再次執行tcpdump(這次使用了附加選項-e)。

root@ip-10-12-2-73:~# tcpdump -e -n host 8.8.8.8
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:47:56.820194 12:6e:eb:de:b3:ed > 12:6f:56:c0:c4:c1, ethertype IPv4 (0x0800), length 98: 10.12.2.73 > 8.8.8.8: ICMP echo request, id 16347, seq 1, length 64
21:47:56.829102 12:6f:56:c0:c4:c1 > 12:6e:eb:de:b3:ed, ethertype IPv4 (0x0800), length 98: 8.8.8.8 > 10.12.2.73: ICMP echo reply, id 16347, seq 1, length 64
21:47:57.821516 12:6e:eb:de:b3:ed > 12:6f:56:c0:c4:c1, ethertype IPv4 (0x0800), length 98: 10.12.2.73 > 8.8.8.8: ICMP echo request, id 16347, seq 2, length 64
21:47:57.830386 12:6f:56:c0:c4:c1 > 12:6e:eb:de:b3:ed, ethertype IPv4 (0x0800), length 98: 8.8.8.8 > 10.12.2.73: ICMP echo reply, id 16347, seq 2, length 64

這一次,除了ip地址,我們還可以在輸出中看到 12:6e:eb:de:b3:ed > 12:6f:56:c0:c4:c1 和 ~12:6f:56:c0:c4:c1 > 12:6e:eb:de:b3:ed ~ 表示的物理地址(MAC地址)。

root@ip-10-12-2-73:~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 12:6e:eb:de:b3:ed  
          inet addr:10.12.2.73  Bcast:10.12.2.255  Mask:255.255.255.0
          inet6 addr: fe80::106e:ebff:fede:b3ed/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:1200693 errors:0 dropped:0 overruns:0 frame:0
          TX packets:945763 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2452613050 (2.4 GB)  TX bytes:447161879 (447.1 MB)

從上面看ifconfig命令輸出中,我們可以確認 12:6e:eb:de:b3:ed 是我們服務器的MAC地址(ifconfig輸出的 HWaddr 12:6e:eb:de:b3:ed 部分)。

而什麼又是 12:6e:eb:de:b3:ed 呢?我們可以使用命令 arp -n -a 找出它表示什麼。ARP代表地址解析協議。它負責將IP地址轉換爲MAC地址。 arp -n -a 會顯示當前機器已知的MAC地址和他們對應的IP地址。我們稍後會仔細研究ARP的工作原理。

root@ip-10-12-2-73:~# arp -n -a
? (10.12.2.40) at 12:f7:fd:48:aa:79 [ether] on eth0
? (172.17.0.2) at 02:42:ac:11:00:02 [ether] on docker0
? (10.12.2.43) at 12:48:08:aa:a5:bb [ether] on eth0
? (10.12.2.8) at 12:ab:ed:67:34:79 [ether] on eth0
? (10.12.2.94) at 12:47:87:c2:60:8d [ether] on eth0
? (10.12.2.1) at 12:6f:56:c0:c4:c1 [ether] on eth0

哈哈! 12:6e:eb:de:b3:ed 是網關的MAC地址(10.12.2.1)。即使目標IP地址是8.8.8.8,目標mac地址始終是網關服務器。

MAC地址(物理地址)是OSI第二層的部分。IP地址是第三層的部分。第三層的內容封裝在第二層中。第二層擁有我們服務器MAC地址和網關的MAC地址。這就是數據包到達網關的方式。網關會覆寫第二層(物理層)地址,當它發現目標地是8.8.8.8,它將數據包再次轉發到其網關(網關根據路由把數據包轉發到下一個網關)。

這就是數據包如何傳輸併到達其最終目標8.8.8.8的。在到達8.8.8.8的路徑中,倒數第二個網絡設備將使用ARP協議查詢8.8.8.8的MAC地址。,

最終,如果你想到達一個特定的目標IP地址,系統會把這個IP地址轉換成等效的MAC地址。因爲真正的通訊是用物理地址進行的。ARP(地址解析協議)用於查找與IP地址對應的物理地址。

上圖說明了計算機如何使用ARP協議找出與IP對應的MAC地址。圖中第一個請求“來自10.12.2.73的ARP請求”目的是尋找10.12.2.1的MAC地址。

這個ARP請求是一個廣播請求。這就是請求中的目標MAC地址設置爲00:00:00:00:00(廣播MAC地址)的原因。當本地網絡中連接所有機器的網絡設備收到目標地址00:00:00:00:00的請求時,它把請求轉發到每一臺機器(這就是廣播的意思:發送給每臺機器)。

雖然網絡中的每臺機器都會收到請求,只有IP地址是10.12.2.1的機器纔會響應。驗證目標IP地址後,其他所有機器將丟棄該請求。只有IP地址匹配的機器纔會做出響應。

在回覆時,目標服務器發送自己的MAC地址。這樣10.12.2.73會找到與10.12.2.1對應的MAC地址。以下關於ARP的屬於值得注意:

  1. ARP緩存:在找到IP對應的MAC地址後,計算機將其存儲在表中以待將來使用。後續所有到這個IP地址的通信都可以使用中的MAC地址。這個表叫做ARP緩存。
  2. ARP緩存超時:添加到ARP緩存中的條目,只在指定的時間內有效。這一術語表明了這個時間段。
  3. ARP請求:我們已經在前面看到了。ARP請求是由計算機發出的廣播請求,以找出IP地址對應的MAC地址。
  4. ARP應答:如上圖所示,ARP應答這是來自目標主機的響應,包含IP和MAC地址。

1 如何在Linux下查看ARP緩存表?

幾乎所有的linux發行版都帶有一個名爲arp的命令行實用程序。你可以使用它來查看arp表條目(如下所示)。

root@ip-10-12-2-73:~# arp -n -a
? (10.12.2.40) at 12:f7:fd:48:aa:79 [ether] on eth0
? (10.12.2.43) at 12:48:08:aa:a5:bb [ether] on eth0
? (10.12.2.8) at 12:ab:ed:67:34:79 [ether] on eth0
? (10.12.2.94) at 12:47:87:c2:60:8d [ether] on eth0
? (10.12.2.1) at 12:6f:56:c0:c4:c1 [ether] on eth0

你也可以使用下面的命令來查看arp表。

root@ip-10-12-2-73:~# arp -n -e
Address                  HWtype  HWaddress           Flags Mask            Iface
10.12.2.40               ether   12:f7:fd:48:aa:79   C                     eth0
10.12.2.43               ether   12:48:08:aa:a5:bb   C                     eth0
10.12.2.8                ether   12:ab:ed:67:34:79   C                     eth0
10.12.2.94               ether   12:47:87:c2:60:8d   C                     eth0
10.12.2.1                ether   12:6f:56:c0:c4:c1   C                     eth0

2 如何在Linux下手動添加ARP緩存表項?

Linux下的arp命令有一個選項可以執行這個操作。如:

root@ip-10-12-2-73:~# arp  -s  10.12.67.43  12:48:08:bb:a5:bb

請確保命令中的IP地址是有效的。

3 如何在Linux下手動刪除ARP緩存表中的條目?

在Linux中,可以使用ARP命令的-d選項可以從ARP緩存表中刪除一個條目。如:

root@ip-10-12-2-73:~# arp  -d  10.12.67.43

4 如何在Linux下刪除ARP緩存表中的所有條目?

ip命令可用於此操作。

root@ip-10-12-2-73:~# ip neigh flush all

5 ARP條目存儲在系統中的什麼地方?

在內存中。你可以通過/proc文件系統訪問它。

root@ip-10-12-2-73:~# cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
10.12.2.40       0x1         0x2         12:f7:fd:48:aa:79     *        eth0
10.12.2.43       0x1         0x2         12:48:08:aa:a5:bb     *        eth0
10.12.2.8        0x1         0x2         12:ab:ed:67:34:79     *        eth0
10.12.2.94       0x1         0x2         12:47:87:c2:60:8d     *        eth0
10.12.2.1        0x1         0x2         12:6f:56:c0:c4:c1     *        eth0

6 如何一次向arp緩存表添加多個條目?

arp命令支持從文件中加載條目。你可以將文件路徑作爲參數傳遞給arp命令。默認使用/etc/ether文件。文件內容如下所示:

12:f7:fd:48:aa:79 10.12.2.40
12:48:08:aa:a5:bb 10.12.2.43

現在可以將文件的路徑作爲參數。

root@ip-10-12-2-73:~# arp -f /etc/ethers

Linux內核的ARP模塊支持許多調優選項。其中大部分可以通過/proc中的文件修改。你可以在/proc/sys/net/ipv4/neigh/default中找到與ARP相關的內核文件。

root@ip-10-12-2-73:/proc/sys/net/ipv4/neigh/default# ls
anycast_delay           gc_interval    locktime       retrans_time_ms
app_solicit             gc_stale_time  mcast_solicit  ucast_solicit
base_reachable_time     gc_thresh1     proxy_delay    unres_qlen
base_reachable_time_ms  gc_thresh2     proxy_qlen     unres_qlen_bytes
delay_first_probe_time  gc_thresh3     retrans_time

你可以從這裏獲取這些文件及其內容的解釋:ARP內核模塊選項

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章