pretty code

2019年11月29日 星期五

一個 ARP 廣播封包的故事

ARP 協定是在乙太區域網路中常用到的一個協定,當我們有資料要傳給區域網路上的某台裝置時,由於上層僅知道 IP 資訊,故需要使用 ARP 協定來得知該裝置的 MAC。

一般來說,系統都會有內建的 ARP table,以 Windows 來說,可以使用 "arp -a" 來觀看,如果在 table 中找不到對應的 IP,就會發出 ARP 廣播封包來得到該台裝置的 MAC,而這個封包的目的 MAC 便會是 "FF:FF:FF:FF:FF:FF",表示要傳給區域網路中的所有節點。


我們有個專案會使用 UEFI Shell 開機且定時的使用 HTTP Web API 跟 Server 溝通,以得知接下來要做的測試並回報測試結果。

某天我們拿到了新的板子,恰巧的是網路卡晶片也改了,這時原本正常的測試都無法順利進行,不是 DHCP 取不到 IP 就是 HTTP Web API 無法正常工作。當然,一開始會直覺是因為新板子的緣故。

由於此板已經在私人的網路環境測試過,DHCP 看起來都正常工作,只好詢問公司 IT 是否有更改公司區域網路設定,不料 IT 並沒有修改設定,這段期間也有將自己電腦接到該板子所使用的 port 測試,看起來網路也都正常,偏偏兩者合起就來就是無法正常工作,這中間還做了很多實驗,但都無助於問題解決。

沒辦法只好動用 Wireshark 和 mirror port switch 了,首先可以確認的是某些時候不論是 DHCP 的回應封包或是測試 Server 的 SYN-ACK 封包,都有正常送回板子端,但不知道什麼緣故,板子會認為沒有收到封包,結果便是 DHCP 取不到 IP 以及 HTTP Web API 失效。

雖然從封包可以證明問題似乎是出自板子端,但對解決問題還是沒有幫助,畢竟在我們自己的私人網路環境都是正常的。幸好在截取封包的過程中,發現有一個設備不斷的在發出 ARP 廣播封包且每次要詢問的 IP 都不一樣,從比例來看,至少佔了封包數的 40 % 以上( 因為是 mirror 故這個數字可能 double 了 ),這是個不正常的現象,一般來說,大部份都會是 IPV4 封包佔的比例會是最高,ARP 應該是 10% 以下較為合理。


將此情況回報給 IT 後,據 IT 的說法是該台設備的使用者誤將 DHCP 設定設成固定 IP,導致該設備不斷的發出 ARP 廣播封包。說也奇怪,在 ARP 廣播封包消失後,我們的板子就恢復正常了,個人猜測是因為 UEFI Network Stack 的 implement 無法處理此類情況,畢竟 UEFI 只是個單執行緒的精簡 OS?

雖然後續測試看起來都正常了,但到底是不是因為 ARP 廣播封包所引起?這個問題一直在我心頭縈迴不去,看來證明它的方式便是想辦法創造出一樣的環境。

Google 了一下,想要發出 ARP 封包看起來在 Windows 下不可行,幸好這個世界上還有萬能 OS - Linux 存在,只要使用 RAW Socket 便可以順利的發出 ARP 廣播封包。

萬事具備,只欠東風,使用 Switch 架設了一個私人網路環境,並配合測試 Server 配置,設定了相關裝置的固定 IP,原本只是簡單寫個 for loop scrip 10000 + C code 發送 ARP 廣播封包,但板子看起來卻是一切正常?靈機一動之下,判斷是壓力不夠,在開啟另外一個終端機並執行相同的 script 後,我們的板子終於宣告不治,一直要等到 ARP 廣播封包結束後才能恢復正常。


能夠確認自己的判斷並重現問題,我想這才是 RD 的本事所在,真不枉費我寫了 14 年的 Code。

2021/12/24 更新

原來是我誤會 Windows 了,Windows 有提供一個 SendARP 的 Win32 API,故我們在 Windows 下也可以發送 ARP 封包,重點是可以用 Go!另外,我也找到一個 Go package 可以在 Linux 下發送 ARP 封包,這樣就更容易做測試了。

沒有留言: