詳細的網絡協議之ARP請求

對於 ARP 協議,你想知道的,可能包括以下幾點:

  • ARP 是啥

  • 爲啥需要 ARP

  • ARP 是怎麼工作的

  • ARP 報文格式長啥樣

  • ARP 安全嗎

  • 有哪些命令可以操作 ARP

  • ARP 有哪些內核配置參數

帶着這些問題,下面我們就來一一解答。

 

ARP 是啥


ARP 全稱爲 Address Resolution Protocol ,即地址解析協議,主要用於根據 IP 地址求出主機所對應的物理地址(或者叫 MAC 地址)。

它還有個孿生兄弟叫 RARP(Reverse ARP),即反向地址解析協議,也就是根據主機 MAC 地址求出對應的 IP 地址,但是這個協議不常用,通常只用在無盤系統中。

ARP 只用於 IPv4,IPv6 使用鄰居發現協議( Neighbor Discovery Protocol, NDP) 來代替 ARP 的功能。

 

爲啥需要 ARP


在網絡通信中,主機和主機之間的通信需要根據 OSI 模型進行數據包的封裝和解封裝,這裏面不僅需要封裝源目的 IP 地址,也需要源目的 MAC 地址,那麼 MAC 地址從哪裏來呢,一般情況下,上層應用只知道 IP 地址,而並不關心 MAC 地址,所以就需要通過一個協議來獲知目的 MAC 地址,完成數據的封裝,這個協議就是 ARP 協議該乾的活。

 

ARP 是怎麼工作的


在介紹 ARP 如何工作之前,需要知道一個概念 ARP 緩存表 。在每臺安裝有 TCP/IP 協議的電腦或網絡設備裏都有一個 ARP 緩存表,表中記錄的是 IP 地址和 MAC 地址的映射關係,比如:

以上表中的主機 A 向主機 B 發送數據爲例,說一下 ARP 的工作流程:

  1. 當發送數據時,主機 A 會在自己的 ARP 緩存表中尋找是否有目標 IP 地址,如果找到,就把對應的目標 MAC 地址封裝進幀裏進行發送。

  2. 如果沒有找到,主機 A 就會向網絡中發送一個廣播(ARP request),和主機 A 同網段內的所有主機都會收到這個請求,該請求的目標 MAC 地址是"FF.FF.FF.FF.FF.FF",目標 IP 是主機 B 的 IP。

  3. 只有主機 B 會接收這個請求,並且向主機 A 做出迴應(ARP response),而其他主機接收到請求之後發現目標 IP 不是自己,就會選擇丟棄。主機 B 從請求中獲得主機 A 的 MAC 地址和 IP 地址,所以會以單播的方式進行迴應,同時更新自己的 ARP 緩存表。

  4. 主機 A 接收到主機 B 的響應之後,也會更新自己的 ARP 緩存,下次再訪問主機 B 時,就直接從 ARP 緩存裏查找即可。

ARP緩存超時: 既然是緩存表,意味着有時效性。ARP 緩存表採用老化機制,在一段時間內如果表中的某一條目沒有使用,就會被刪除,這樣可以減少緩存表的長度,加快查詢速度。

緩存時間,一般是 20 分鐘 ,但 RFC 也有規定一些不完整條目是 3 分鐘,什麼是不完整條目,比如下面這條,對一個不存在的主機執行了一次 ARP 請求,就是一條不完整的條目:

# arp -a
?(10.0.0.99) at <incomplete> on eth0

 

ARP 報文格式長啥樣


首先看一個以太網幀中,ARP 報文處在一個什麼位置。

以下是一個以太網幀的簡化圖,這裏只是爲了說明 ARP 報文在整個以太網幀中所處的位置,所以這個以太網幀並不是完整的。

我們看到,以太網幀通過一個 2 字節的幀類型來表示它後面的數據負載(payload)部分具體是什麼類型的數據,如果幀類型是 16進制的 0x0800,則表示 payload 是 IP 報文,如果是 0x0806,就表示 ARP 報文,包括 ARP 請求報文和應答報文。當然,這裏還有其他類型的數據,比如 ARAP,我們就不一一列出了。

下面,繼續走進 ARP 報文內部,看看它包含哪些字段:

 

  • 硬件類型:指出硬件地址類型,對於以太網,該值是 1

  • 協議類型:指出網絡層協議類型,對於 IPv4,該值是 0x0800

  • 硬件大小和協議大小:分別指出後面的硬件地址和協議地址的大小,對於使用 IPv4 的 ARP 報文,該值分別是 6 和 4

  • Op:指出該報文是 ARP 請求(值爲 1)、ARP 應答(2)、RARP 請求(3) 或 RARP 應答(4)

  • 後面的 4 個字段和前面 4 個字段對應,分別表示源目的 MAC 和源目的 IP 地址

我們通過 Wireshark 抓包看看。

ARP 請求報文:

ARP 應答報文:

可以看到 Op 字段,對於 ARP 請求和應答報文分別爲 1 和 2,其他字段大家也可以看看,比較直觀。

 

有哪些命令可以操作 ARP


① arp

用法:

# arp (選項)(參數)

-a <主機IP>:顯示 arp 緩衝區中的所有條目
-e:以 Linux 的顯示風格顯示 arp 緩衝區中的條目
-v:顯示詳細的 arp 緩衝區條目,包括緩衝區條目的統計信息
-i <接口>:顯示指定接口的 arp 緩存條目
-s <主機IP><MAC>:配置主機的 IP 地址與 MAC 地址的靜態映射
-d <主機>:刪除 arp 條目
-f <文件>:從文件 /etc/ethers(默認)或者指定文件中記錄的 arp 條目配置靜態映射

② ip neigh

ip neigh 是和 arp 相同功能但不同用法的另一套命令,全稱爲 ip neighbour

用法:

# ip neigh help
ip neigh { add | del | change | replace }
         { ADDR [ lladdr LLADDR ] [ nud STATE ] | proxy ADDR } [ dev DEV ]
ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ][ vrf NAME ]

# 其中幾個選項的意思解釋
- to ADDR: 協議地址,指定主機的 IP 地址
- dev DEV: 指定網口
- lladdr LLADDR: 指定 MAC 地址
- nud STATE: 狀態值,有以下幾個值:
    - permanent:永久有效
    - noarp:有效,不會驗證此條目,但可以在其生命週期到期時將其刪除
    - reachable:有效,直到可達性超時到期
    - stale:有效但可疑
    - all:列出所有狀態

# 常用操作

1. 列出所有 arp 條目
# ip neigh show

2. 添加 arp 靜態條目
# ip neigh add 192.168.10.11 lladdr 00:01:02:03:04:05 dev eth0

3. 刪除指定 IP 或者網口的 arp 條目
# ip neigh del 192.168.10.11 dev eth0

4. 刷新 arp 表
# ip neigh flush 192.168.10.11

# 此外還有兩個命令,可以更改 arp 條目
# ip neighbour change - 更改
# ip neighbour replace - 添加新的或更改

③ arping

arping 和 ping 相似,主要是通過發送 ARP 請求查看 IP 和 MAC 的映射關係,以及探測 IP 的衝突問題。更多的用法可以參見這篇文章 xxx

④ arpwatch

arpwatch 主要用於監聽網絡中的 ARP 數據的變化關係並記錄,可以將監聽到的變化通過 E-mail 發送。

用法:

# arpwatch [-d][-f <記錄文件>][-i <接口>][-r <記錄文件>]

監聽 eth0 的 ARP 信息
# arpwatch -i eth0

將監聽到的 ARP 記錄存儲到文件
# arpwatch -i eth0 -f /var/arpwatch/arp.dat

從指定文件中讀取 ARP 記錄,而不是從網絡中監聽
# arpwatch -r /var/arpwatch/arp.dat

 

ARP 有哪些內核配置參數


從上文我們知道,ARP 是一個無狀態協議,就是說它不管自己是否發過請求,也不管應答是否合理,再加上廣播的特性,有時候通信上會出現一些匪夷所思的問題,系統會通過以下幾個配置參數來規避這些問題。

要說清楚這些參數,我們先上個圖:

在這樣一個局域網的圖示中,B 向 A 的 eth0 接口發送 ARP 請求,由於是廣播,並且 IP 地址針對的是整個主機,而不是特定的某個接口,所以,A 的兩個口 eth0 和 eth1 都會接收請求併發出應答,而 B 則以最後應答的 MAC 地址爲準。

這就會帶來第一個問題,如果 B 本來想獲取 eth0 的 MAC 地址,但卻得到 eth1 的,這就會導致後續發送數據的不準確。

解決這個問題可以用兩個內核參數,這兩個參數都是在 ARP 應答上做文章,讓它能夠正確應答。

① arp_ignore

  • 0 - (默認值): 迴應任何網絡接口(網卡)上對任何本機IP地址的arp查詢請求。比如eth0=192.168.0.1/24,eth1=10.1.1.1/24,那麼即使eth0收到來自10.1.1.2這樣地址發起的對10.1.1.1 的arp查詢也會給出正確的迴應;而原本這個請求該是出現在eth1上,也該有eth1迴應的。
  • 1 - 只回答目標IP地址是本機上來訪網絡接口(網卡)IP地址的ARP查詢請求 。比如eth0=192.168.0.1/24,eth1=10.1.1.1/24,那麼即使eth0收到來自10.1.1.2這樣地址發起的對192.168.0.1的查詢會迴應,而對10.1.1.1 的arp查詢不會迴應。
  • 2 -只回答目標IP地址是本機上來訪網絡接口(網卡)IP地址的ARP查詢請求,且來訪IP(源IP)必須與該網絡接口(網卡)上的IP(目標IP)在同一子網段內 。比如eth0=192.168.0.1/24,eth1=10.1.1.1/24,eth1收到來自10.1.1.2這樣地址發起的對192.168.0.1的查詢不會迴應,而對192.168.0.2發起的對192.168.0.1的arp查詢會迴應。
  • 3 - do not reply for local addresses configured with scope host,only resolutions for global and link addresses are replied。(不知道怎麼翻譯合適,網上有一個參考但我認爲無法理解它的含義:不迴應該網絡界接口的arp請求,而只對設置的唯一和連接地址做出迴應)
  • 4-7 - 保留未使用
  • 8 -不迴應所有(本機地址)的arp查詢

在設置參數的時候將arp_ignore 設置爲1,意味着當別人的arp請求過來的時候,如果接收的網絡接口卡上面沒有這個ip,就不做出響應。默認是0,只要這臺機器上面任何一個設備上面有這個ip,就響應arp請求,併發送mac地址。

 

在內核參數中,除了每個網口都有自己的 arp_ignore 配置外,還有兩個(一個是默認 default,一個是全局 all),如下。一般,如果網口自身的 arp_ignore 不配置的情況下,使用 default 的配置,如果 all 和網口自身都配置的情況下,使用兩者中較大的那一個。

# sysctl -a | grep arp_ignore
net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth1.arp_ignore=1

關於配置這塊,有臨時生效和永久生效的配置方式,文末有進一步說明。

② arp_filter

這個參數和 arp_ignore能夠達到相同的目的,但 arp_filter會更嚴格一些,它在選網口應答的時候會按照路由來選。它是一個 bool 值,具體爲:

  • 0:默認值,所有網口都可以響應 ARP 請求

  • 1:會根據本機路由表來驗證哪個網口應該進行應答,優先選擇在路由表前面的網口,也就是會有一個反向路由驗證的過程。

同樣,他也有以下的參數:

$ sysctl -a | grep arp_filter
net.ipv4.conf.all.arp_filter = 0
net.ipv4.conf.default.arp_filter = 0
net.ipv4.conf.eth0.arp_filter = 0
net.ipv4.conf.eth1.arp_filter = 0
net.ipv4.conf.lo.arp_filter = 0

上面兩個參數解決的是 ARP 應答方向上的問題,而下面的 arp_announce 是解決 ARP 請求方向上的問題。它可以控制本機發出的 ARP 請求中的源 IP 地址使用哪個網口的地址。

③ arp_announce

它有以下 3 個整數值:

  • 0:默認值,可以在任意網口上發送 ARP 請求,但是請求的源 IP 地址與當前發送的網口沒有關係。也就是說如果源 IP 地址與當前發送網口的地址不同(使用其他網口作爲源 IP 地址),使用原本的源 IP 地址。

  • 1:要求儘量避免使用不在當前發送網口子網段內的 IP 地址作爲 ARP 請求的源 IP 地址,也就是說系統會遍歷所有網口的 IP,然後看哪個網口的 IP 和 ARP 請求包中的源 IP 在同一個網段內,優先選擇哪個進行發送,如果都不在,就採用下面級別 2 的方式來選擇。

  • 2:1 是看源 IP 地址,這種方式是看目標 IP 地址,選擇與目標 IP 地址在同一個網段內的網口 IP 作爲 ARP 請求的源 IP 地址,如果還是沒找到,則直接選擇當前網口的 IP 或者能夠接受到 ARP 迴應的網口 IP 來發送 ARP 請求,並設源 IP 爲發送網口的 IP。

此外,還有兩個參數:

④ arp_accept

默認對不在 ARP 表中的 IP 地址發出的 APR 包的處理方式

  • 0:不在 ARP 表中創建對應 IP 地址的表項

  • 1:在 ARP 表中創建對應 IP 地址的表項

⑤ arp_notify

ARP 通知鏈操作

  • 0:不做任何操作

  • 1:當設備或硬件地址改變時自動產生一個 ARP 請求

 

修改方法


臨時修改方法:

 1. 修改/proc文件系統:

echo "1">/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1">/proc/sys/net/ipv4/conf/eth0/arp_ignore
echo "2">/proc/sys/net/ipv4/conf/all/arp_announce
echo "2">/proc/sys/net/ipv4/conf/eth0/arp_announce

 2. 使用sysctl -w直接寫入內存:

sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.eth0.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
sysctl -w net.ipv4.conf.eth0.arp_announce=2

永久修改需要寫入配置文件:

修改/etc/sysctl.conf文件,然後sysctl -p刷新到內存

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.eth0.arp_announce=2

備註:arp_ignore和arp_announce參數分別有all,default,lo,eth0等對應不同網卡。當all和具體網卡的參數值不一致時,配置爲較大值的生效。一般只需修改all和某個具體網卡的參數即可。

然後一定記得執行 sysctl -p 使之生效。

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