繼續來做(da)推(guang)介(gao)我自己的!由於這兩年接觸到了比較多的這方面的知識,不想忘了,我決定把他們記錄下來,所以決定在GitBook用半年時間上面寫下來,這是目前寫的一節,目前已完成了九篇啦。后面會在gitbook上不斷更新,歡迎大家star,主要是在寫完之前歡迎各位給出指正的意見。最最重要的,地址在這里:https://rogerzhu.gitbooks.io/-tcp-udp-ip/content/,或者在gitbook上搜索“三十天學不會TCP,UDP/IP編程”。
我覺得我要以一個真實的故事來開始這一部分。在我上大二的時候,突然從某一天開始,我們那層連着的6個寢室全都不能上網了,但是有時候又能短暫的上一會兒網,沒有規律。不過有一個同學例外,雖然他也處在這6個寢室之中,但無論何時他都能上網。我們很苦悶,於是他那段時間挨個寢室炫耀自己可以上網。就這樣過了大約一個星期,后來他們寢室另外三個人突然發現一個規律,只要這個同學沒有插網線我們就能上網,只要他一插網線我們就全完了。在用他的電腦做了幾次開關機時間之后,我們確認了這個事實。這是個不得了的發現吶,考慮到之前他太高調了,我們6個寢室的人勒令他不允許開電腦,哈哈。但是我們還是有良心的,開始在網上搜索資料,后來架不住人(mei)多(wang)力(shang)量(bu)大(xing),我們在茫茫互聯網資料中,搜索到了兩個詞“arp欺騙”和“arp病毒”。特別是想到那位同學前幾天炫耀的表情,在興(fen)趣(nu)的指引下,我們認真學習了其原理,確認了確實是那位同學的鍋。然后下載了個殺毒軟件,給那位同學的電腦徹底的殺毒,從此上面的現象再也沒有出現過了。而且在后面長達一周的時間內,我們每天必做的一件事就是去問候一下那位同學,哈哈。
ARP是什么?
ARP學名Address Resolution Protocol,從英文上看意思已經躍然紙上了。地址解析協議,解析啥呢,解析IP地址到MAC地址。為什么要這么做呢,因為兩個計算機通信本質上是通過MAC地址來識別對方的。我覺得在避免陷入一個協議復雜的細節之前,可以先從一個宏觀上面弄明白協議的整個流程是什么樣的,是時候再一次獻上我的手繪版了。

ARP協議主要在兩個場景下有所使用,第一個猶如圖中繪制的,某一段想向另一端發送數據包之前,需要通過ARP協議來知曉對方的的地址,具體用文字描述就是如下:
首先,發送端會發出一個ARP請求以太網報文,由於現在發送端還不知道對端的MAC地址,所以ARP的請求報文利用了鏈路層廣播,使得局域網內所有的主機都能接受到這個信息,這就像我們小時候站在別的班教室門口找人一樣,大喊,誰誰誰,有人找你,所有人都能聽到,但是只有正確的誰誰誰才會發出響應。
按照這個邏輯,回憶一下,其實就是點擊一下“MAC地址與數據鏈路層”里介紹的數據鏈路層以太網幀格式,其中以太網頭部填上目標鏈路層廣播MAC地址,也就是在前一節里已經介紹過的全FF,接下來的填入自己的MAC地址,剩下的幀類型是0x0806,標識ARP協議。
接下來就是數據部分了,在ARP協議的數據部分, 要填入的數據類型的很多, 我想以一個表格的形式來表示會比較清晰(表中黑體部分標識以太網幀頭部分,普通字體表示數據部分):
長度 | 數據類型 |
48 | 目標以太網地址(FF:FF:FF:FF:FF:FF) |
48 | 發送端以太網地址 |
16 | 幀類型(0x0806) |
16 | 硬件類型(0x0001表示以太網) |
16 | 協議類型(0x8000表示IPv4,0x86DD標識IPv6) |
8 | 硬件地址長度(6) |
8 | 協議地址長度(4對應IPv4,6對應IPv6) |
16 | 操作碼(1) |
48 | 發送端MAC地址 |
32 | 發送端IP地址 |
48 | 目標MAC地址(全0標識空) |
32 | 目標IP地址 |
當這個請求數據幀構造后之后,發送端將其發送給整個網絡,接下來的局域網中所有接口卡都會讀入這個幀,但是在驅動程序讀到數據部分的目標IP地址之后發現與自己的IP地址並不匹配,所以就什么也不做,簡單的丟棄這個幀就好。直到正確的對端出現,他發現這個幀里面的IP地址就是自己,於是下面他就需要構造一個ARP應答幀。
這個應答幀的組成絕大部分和上表列出的一樣,不同的只有這幾點:
-
目標以太網地址不再是全FF的廣播地址,而是剛才發送端A的MAC地址,因為該應答端B已經從A的ARP請求幀的數據部分可以知道A的MAC地址,沒必要再廣播了。
-
操作碼改為2,2表示ARP應答。
-
其余將所有"發送端”相關的都填自己(B)的信息,目標端都填要回復的那一端的信息(A),這一點是顯而易見的。
當應答幀構造完畢發送出去以后,A的網卡驅動程序就能篩選出發給自己應答幀,里面含有他需要的對端的B的MAC地址信息。這時候以備以后使用,A會把這個信息寫入自己的一個cache里面存起來,這個緩存會有個老化機制,會定期淘汰很久沒用的,這樣可以保持這個表不至於太龐大,加快查詢速度。這樣下次再想和B通信的時候就不用再一次的廣播消息重走長征路了,占用帶寬而且也沒有必要。而這個緩存信息,在每個機器上都能看到,在windows上用arp -a命令,在linux上使用arp命令就可以看到。

這里有個有趣的現象,我的局域網的廣播地址對應的物理地址是全ff,這一點我在上一節也說過了,鏈路層廣播地址和IP層次的廣播地址沒有完全直接的關系,可能好幾類的IP層次的廣播地址映射的都是全ff的鏈路層廣播地址。
按照慣例,我會截圖截個wireshark的數據包來看一下實際中的包表示標准沒有欺騙我們,那么當然這一次也不例外:

看看wireshark這個相當用戶友好化的界面說明,我的電腦要找到局域網的路由器的地址,先霸氣的在網絡里大叫,“誰TM的擁有192.168.8.1,告訴我192.168.8.124”,而且注意第一個消息的地址是Broadcast,是一個廣播消息,接下來,路由器做出了應答,“我是192.168.8.1,我的MAC地址是。。。”,這里的發送地址已經准確的是我的電腦了。
為了更一步的看看包里面到底有啥,就選取ARP請求包展開看一下其中內容,對比一下前面表中的內容,又一次發現,標准說明沒有騙我們:

免費ARP和免費一點也沒有關系
前面我說了,ARP協議主要用在兩個場景,在上一節中已經介紹了第一個,第二個就是這個翻譯的令人感到很困惑的免費ARP了。免費ARP,其實學名是gratuitous ARP, gratuitous這個詞主要有三個意思,無端的,沒有理由的和免費的。我覺得翻譯成另外兩個都比免費的這個翻譯好。
廢話不多說了,那么這個gratuitous ARP到底是干啥的呢?不知道大家有沒有遇到過這樣一個現象,在公司里用電腦用的好好的,突然會右下角會出現一個氣泡提示,說你的IP地址沖突了。這個提示就來源於gratuitous ARP,每個機器在DHCP(后面會詳細介紹這個重要協議的)拿到這個IP之后,會向局域網中廣播一個ARP請求,但是這個請求中的目標IP地址是自己已經分配了的IP地址,按照前面的邏輯,如果局域網上還有一個主機具有同樣的IP地址的主機,那么他就會發送一個回復,而這個回復中會包含自己MAC地址。發送端如果接收到這么一個回復,那么意味着在網絡中有一個和自己一模一樣的IP地址的主機,他自己就知道自己的IP地址重復了,於是就會給出這個么一個提示給用戶。
ARP欺騙
有了前面這個免費ARP的例子,那么ARP欺騙就很好理解了。只要做一個如下的想象:
如果有一個程序,他可以篡改ARP應答包里的MAC地址,也就是把MAC地址改成自己規定好的主機,那么按照我們上面說的,,發送包在收到這個ARP應答后會把cache起來以防下次再做不必要的努力。那么你以后本來想發送到B的包就會被發到一個指定的主機上,因為數據層的MAC地址已經被邪惡的入侵者所改掉,不會填入B的MAC地址。
這也就是為什么最開始的故事中我們都上不了網,唯獨我那一個同學能上網的原因,因為他機器上的ARP病毒將所有包的地址都改為他自己的主機,我們其余的電腦都根本無法完成通信,或者也可能是說根本收不到消息。