任何人都能看得懂的網絡協議之 ARP

 噹噹網4.23圖書3.9折大促 

對於 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 提供的功能簡單高效,但和所有網絡協議一樣,它並不是完美的。它的不完美主要體現在它並不安全。

  1. ARP 報文沒有任何認證。攻擊者可以發送僞造的 ARP 報文(尤其是應答報文),惡意修改網關或網絡內其他主機的 ARP 表項,造成報文的轉發異常,這就是 ARP 欺騙攻擊( ARP spoofing )。

  2. ARP 報文沒有狀態。它不會去檢查自己是否發過請求包,也不知道自己是否發過請求包,也不管應答是否合理,只要收到目標 MAC 是自己的 reply 或者 request 廣播包,都會照單全收,寫進自己的 ARP 緩存,原有相同的表項就會被替換。如果攻擊者利用這一特性,發送大量僞造的 ARP 應答報文,造成主機 ARP 表項溢出,導致無法緩存正常的 ARP 表項,從而影響報文的正常轉發,這就是大名鼎鼎的拒絕服務攻擊(DDoS)或 ARP 泛洪攻擊。

這兩種攻擊都會導致:

  1. 網絡不穩定,引發用戶無法上網或者企業斷網導致重大生產事故。

  2. 非法獲取遊戲、網銀、文件服務等系統的帳號和口令,給被攻擊者造成利益上的重大損失。

解決方案

那麼遇到這些攻擊,該如何避免呢?

因爲攻擊者在暗處,我們用戶在明處,顯然無法知道攻擊者的信息,從而加以檢測。所以就只能從我們自己身上來避免了。主要要做到兩點:

  1. 保證不接收 ARP 欺騙包

  2. 保證接收到 ARP 欺騙包之後不相信,直接丟棄

那麼根據這兩點,業界也提出了一些方案,比如

動態 ARP 檢測方案(DAI)

這種方案一般是在網絡設備(比如交換機和路由器)上來做,在攻擊數據進入用戶主機之前,就將它阻隔。

簡單來說,就是交換機或者路由器維護着一個 DAI 表,表中記錄這每個接口對應的 IP 和 MAC,比如:port<->mac<->ip。如果當某個接口收到的 ARP 應答包,IP 和 MAC 對應關係和 DAI 表中記錄的不一致,那麼就可以將這個包丟棄。

一般這種技術都只用在高端的網絡設備上,基本都是企業級的產品。

對於我們普通用戶,沒必要爲了防止 ARP 攻擊而去買這種設備,那應該怎麼辦呢?

這就只能在自己的電腦端加以防護了,我們可以:

1)安裝 ARP 防火牆 ,很多安全產品都自帶這個功能,比如騰訊電腦管家,360安全衛士等,也有專業的 ARP 防火牆,比如金山貝殼,360 ARP 防火牆等。這些防火牆的技術原理,主要是根據網絡數據包的特徵,自動識別局域網存在的 ARP 掃描和欺騙行爲,並做出攻擊判斷(哪個主機做了攻擊,IP 和 MAC 是多少)。

2)自己手動綁定局域網 IP 和 MAC 的映射關係 ,這樣即便收到 ARP 欺騙包,由於靜態綁定的 ARP 項優先級高於動態學習到的,可以保證不被欺騙。這種方法的缺點也很明顯,如果局域網內的主機很多的話,工作量將會很大。

有哪些命令可以操作 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

定義了對本機 IP 的 ARP 請求時不同的應答模式,它有 8 個整數值:

  • 0:默認值,對本機某個網口的 ARP 請求,所有網口都可以進行 ARP 應答

  • 1:只應答被請求的網口

  • 2:只應答被請求的網口,且請求的 IP 必須在該網口的子網段內

  • 3:不應答該網口的 arp 請求,而只對設置的唯一和連接地址做出迴應

  • 4-7:保留未使用

  • 8:不應答所有(本地地址)的 ARP 請求

所以,解決上面的問題,只需要讓該網口的 arp_ignore=1即可。

在內核參數中,除了每個網口都有自己的 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 請求

附參數配置方法:

Linux內核各種參數的配置,包括以上幾個,也包括其他的一些參數,配置上都可以參考以下兩種方法:

1、臨時生效的配置方法

1)使用 sysctl -w 參數配置

# sysctl -w net.ipv4.conf.default.arp_ignore=1
# sysctl -w net.ipv4.conf.all.arp_ignore=1

2)修改內核參數的映射文件

# echo 1 > /proc/sys/net/ipv4/conf/default/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore

2、永久生效的配置方法

在 /etc/sysctl.conf 配置文件中加入如下的配置項:

net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.all.arp_ignore=1

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

總結

本文我們從 ARP 基本概念,到報文結構,再到安全相關的內容,最後到命令、相關內核參數配置上,可以說基本囊括了 ARP 協議的所有內容,大家還有什麼內容想交流可以留言指出。


後臺回覆“加羣”,帶你進入高手如雲交流羣

推薦閱讀:

3.9折圖書限時秒殺!噹噹網這次要被薅慘了

用好你的網絡瑞士軍刀netcat

一次Linux系統被攻擊的分析過程

Linux下刪除大量文件效率對比

130 個相見恨晚的神器網站

分享20個Linux命令小貼士與技巧

一文帶你徹底理解文件系統

5G與Wi-Fi6空口技術對

內存泄漏(增長)火焰圖

TCP-RST 攻擊與防護,看這一篇就夠了

探究!一個數據包在網絡中的心路歷程

牛逼的Linux性能剖析—perf

HTTPS 的 7 次握手以及 9 倍時延

NFV和SDN之間到底有什麼關係?

Linux 程序編譯過程的來龍去脈

一文搞定 UDP 和 TCP 高頻面試題!


喜歡,就給我一個“在看”


10T 技術資源大放送!包括但不限於:雲計算、虛擬化、微服務、大數據、網絡、Linux、Docker、Kubernetes、Python、Go、C/C++、Shell、PPT 等。在公衆號內回覆「1024」,即可免費獲取!!

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