網絡協議 5 - ICMP 與 ping

    日常開發中,我們經常會碰到查詢網絡是否暢通以及域名對應 IP 地址等小需求,這時候用的最多的應該就是 ping 命令了。 那你知道 ping 命令是怎麼工作的嗎?今天,我們就來一起認識下 ping 命令及其對應的 ICMP 協議。

ICMP 協議

    ICMP 全稱 Internet Control Message Protocol,指互聯網控制報文協議

    網絡本身是不可靠的,數據包在傳輸過程中,可能會發生很多突發事件並導致數據傳輸失敗。而網絡層的 IP 協議是一個無連接的協議,它不會處理網絡層的故障,因此,我們需要其它的協議,在數據包傳輸出現故障時,能將故障信息傳回來,這樣才能對應處理相關問題。

    就像在電視劇裏看到的古代戰爭一樣,打仗的時候需要通過斥候來傳遞戰局情況,進而更好的控制戰局。而 ICMP 報文在網絡世界中就充當“斥候”這樣的角色。

    ICMP 報文是封裝在 IP 包裏面的。因爲傳輸指令的時候,肯定需要源地址和目標地址。它本身格式非常簡單,如下圖:

    ICMP 報文有很多的類型,不同的類型有不同的代碼,最常用的類型是主動請求,代碼爲 8,主動請求的應答,代碼爲 0。從大的方面看可以分爲 查詢報文類型差錯報文類型

查詢報文類型

    我們經常在電視劇裏聽到這樣的話:來人,前方戰事如何?斥候回來沒?一有情況,立刻通報。

    類似這種主帥發起,主動查看敵情的情況,就對應着 ICMP的查詢報文類型。例如,常見的 ping 命令就是查詢報文,是一種主動請求,並且獲得主動應答的 ICMP 協議。因此,ping 命令發出的包也是符合 ICMP 協議格式的,只不過它在後面增加了自己的格式。

    對 ping 的主動請求,進行網絡抓包,稱爲 ICMP ECHO REQUEST。同理,主動請求的回覆,稱爲ICMP ECHO REPLY。比起原生的 ICMP,這裏面多了兩個字段,一個是標識符,另一個是序號。這不難理解,大帥派出去兩隊斥候,一隊是找誰要的,一隊是偵查戰況的,要有個標識才能區分。

    另一方面,派出去的斥候,都要編個號。如果派出去 10 個,回來 10 個,就說明前方戰況不錯。如果派出去 10 個,回來 2 個,就說明情況可能不妙。

    在選項數據中,ping 還會存放發送請求的時間值,來計算往返時間,說明路程的長短。

差錯報文類型

    差錯報文主要是用來將發送的出錯報文相關信息返回到源設備,以供源設備確定如果更好的重發失敗的數據包

    還是拿我們的“大帥”舉例。

    當主帥正在大帳中看地圖,思考戰事時,外面的小兵突然喊到:大帥,不好啦,張將軍遭遇埋伏,全軍覆沒了。

    這種是異常情況發起的,來報告發生了不好的事情,對應 ICMP 的差錯報文。

    差錯報文有以下常用的類型:

  • 3:終點不可達
  • 4:源抑制
  • 5:重定向
  • 11:超時

    第一種情況終點不可達。小兵報告,大帥,送給張將軍的糧草沒有送到。

    那大帥肯定會問,爲啥沒有送到?這就對應 ICMP 中的以下代碼了。

  • 網絡不可達代碼:0
  • 主機不可達代碼:1
  • 協議不可達:2
  • 端口不可達:3
  • 需要進行分片但設置了不分片:4

    具體的場景就像這樣:

  • 網絡不可達:大帥,找不到地方
  • 主機不可達:大帥,找到地方,沒找到張將軍
  • 協議不可達:大帥,找到地方,也找到人了,但是口令沒對上。
  • 端口不可達:大帥,找到地方,找到了人,也對上了口令,但事情沒對上。我去送糧草,人家說在等救兵。
  • 需要進行分片但設置不分片:大帥,走到一半,山路狹窄,想換瞎扯,但是出發前你下令嚴禁換小車,就沒辦法送到了。

    第二種是源站抑制。也就是讓源站放慢發送速度(小兵:大帥,糧草送的太多了吃不完,你可以慢點送)。

    第三種是時間超時。也就是超過網絡包的生存時間還是沒到目的地(大帥,送糧草的人都把糧食吃完了,還沒到地方,已經餓死了)。

    第四種是路由重定向。也就是下次發給另一個路由器(大帥,上次送糧草的人本來只要走大王村,一公里就到了,結果非要繞道張家界,多了五公里,下次記得走大王村)。

    差錯報文的結構相對複雜一些。除了前面還是 IP,ICMP 的前 8 個字節不變,後面則跟上出錯的那個 IP 包的 IP 頭和 IP 正文的前 8 個字節。

    而且這類斥候特別盡責,不但字節返回來報信,還把一部分遺物帶回來。

  • 斥候:大帥,張將軍已經戰死沙場,這是他的印信和佩劍。
  • 大帥:張將軍是怎麼死的(可以查看 ICMP 的前 8 字節)?沒錯,這是張將軍的劍(IP 數據包的頭及正文前 8 字節)。

ping:查詢報文類型的使用

    接下來,我們重點來看 ping 命令的發送和接收過程。

    假定主機 A 的 IP 地址是 192.168.1.1,主機 B 的 IP 地址是 192.168.1.2,它們都在同一個子網。那麼,當在主機 A 上運行“ping 192.168.1.2” 後,會發生什麼呢?

  1. 源主機構建 ICMP 請求數據包。這個數據包內包含多個字段。最重要的有兩個,一個是類型字段,對應請求數據包而言,該字段爲 8。另一個是順序號,主要用於區分連續 ping 的時候發出的多個數據包。每發出一個請求數據包,順序號會自動加 1.爲了能夠計算往返時間 RTT,它會在報文的數據部分插入發送時間。
  2. IP 層構建 IP 數據包。ICMP 協議將數據包連同目標 IP 一起交給 IP 層,IP 層將以 192.168.1.2 作爲目的地址,本機 IP 地址作爲源地址,加上其他控制信息,構建一個 IP 數據包。
  3. 加入 MAC 頭。找到 192.168.1.2 對應的 MAC 地址,附加上一些控制信息,依據以太網的介質訪問規則,將它們傳送出去。

    主機 B 收到數據幀後,會進行如下步驟:

  1. 檢查 MAC 地址,丟棄或接收數據幀,提取 IP 數據包。檢查數據包目的 MAC 地址,並與本機 MAC 地址對比。如符合,就接收數據幀,否則就丟棄。接收後檢查數據幀,將 IP 數據包從幀中提取處理,交給本機的 IP 層。
  2. IP 層檢查IP。檢查完成後,提取有用的信息交給 ICMP 協議。
  3. 構建 ICMP 應答包。應答數據包的類型字段爲 0,順序號爲接收到的請求數據包中的順序號。
  4. 將應答數據包發給主機 A。

    在規定的時間內,源主機如果沒有接到 ICMP 的應答包,則說明目標主機不可達。

    如果接收到了應打包,則說明目標主機可達。此時,源主機會檢測時間延遲。就是用當前時刻減該數據包從源主機發出去的時刻。

    當然,這只是最簡單的,同個局域網的情況。如果跨網段的話,還會涉及網關的轉發、路由器的轉發等。

    可以看出,ping 命令是使用了 ICMP 裏面的 ECHO REQUEST 和 ECHO REPLY 類型。

    那其它類型呢?是不是隻有真正遇到錯誤的時候,才能收到?答案是否定的。有一個 Traceroute 命令,它會使用 ICMP 的規則,故意製造一些能夠產生錯誤的場景。

Traceroute:差錯報文類型的使用

    Traceroute 命令有兩個比較常用的功能。

    第一個功能:

    通過設置特殊的 TTL,追蹤去往目的地時經過的路由器

    Traceroute 的參數執行某個目的 IP 地址,會發送一個 UDP 的數據包。

    將 TTL 設置成 1 時,表示這個數據包的 MP 爲 1,碰到第一個“攔路虎”(通常是路由器或一個其它類型的關卡)就會陣亡了,然後就會返回一個 ICMP 包,這個包就是 網絡差錯包,類型是時間超時

    通過差錯包,我們就能得到數據包到第一個關卡時花費的時間及其每個關卡的 IP 地址(有的主機不會響應 ICMP,所以會出現請求時全是 * 的情況)。

    那怎麼知道 UDP 有沒有到達目的主機呢?Traceroute 程序會發送一份 UDP 數據包給目的主機,但它會選擇一個不可能的值作爲 UDP 端口號(大於30000)。當該數據報到達目的主機時,由於找不到對應端口號,所以會返回一個“端口不可達”的錯誤報文。這樣,我們就知道 UDP 是否到達主機了。

    第二個功能:

    設置數據包不分片,確定路徑的 MTU

    發送分組,並設置“不分片”標誌。發送的第一個分組的長度正好與出口的 MTU 相等。如果中間遇到窄的關卡就會被卡主,返回 ICMP 網絡差錯包,類型是“需要進行分片但設置了不分片”。就這樣,每次收到ICMP“不能分片”差錯時就減小分組的長度,從而確定整個路徑中的 MTU。

總結

  • ICMP 相當於網絡世界的偵察兵。常用的有兩種類型,主動探查的查詢報文和異常報告的差錯報文。
  • ping 命令使用查詢報文,Traceroute 命令使用差錯報文。

參考:

  1. 劉超-趣談網絡協議系列課;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章