為什麼說 ICMP 協議是網路最強輔助

風的姿態 發表於 2023-03-27

大家好,我是風箏

輕解網路系列又來了。已有高畫質 PDF 版本可以離線閱讀了,全冊 65 頁,如果有需要離線版的高畫質 PDF 可以直接下載

今天我們們說說 ICMP 協議。ICMP 可謂是網路世界中的最強輔助了,IP資料包如果在途中遭遇不測的話,全靠 ICMP 來通知,要不然丟掉的IP資料包就有如石沉大海,從此杳無音信,傳送方也不知道這個包有沒有傳輸成功,倘若沒有成功,那失敗原因是什麼?這些,全靠 ICMP 協議來通知。

ICMP 全稱網際網路控制報文協議(Internet Cntrol Message Protocol),是網路層的重要協議。

為什麼說 ICMP 協議是網路最強輔助

ICMP 是幹啥用的

它到底是用來幹啥的呢?為啥叫控制報文協議,控制的是什麼?

ICMP 分為查詢報文和差錯報文兩大類。查詢報文是我們主動發起的,比如ping命令;而差錯報文是在發生差錯之後要發給源端的,這都是網際網路協議模型約定好的。

ICMP的差錯報文反饋發生在通訊環境中的遇到的各種問題。透過這些資訊,使管理者可以對所發生的問題作出診斷,然後採取適當的措施解決。

ICMP的差錯報文是整個資料傳輸鏈路中非常重要的一個環節。打個比喻,差錯報文就是一個只報告壞訊息的信使,當資料包在網路中一路暢通的時候,ICMP 差錯報文就像隱身了一樣,你根本不會知道它的存在,一旦資料包在網路中碰到了各種各樣的障礙,這個信使就出來活動了,它的目的只有一個,就是把這個資料包遭遇的不測通知給傳送端,但是話術就那麼20多種(對應差錯程式碼)。

比如下面兩個場景,想必你也有點熟悉吧。

  • 當路由器收到一份IP資料包但又不能轉發時,就要傳送一份 ICMP「主機不可達」差錯報文。

  • 當IP資料包應該被髮送到另一個路由器時,收到資料包的路由器就要傳送 ICMP「重定向」差錯報文給IP資料包的傳送端。

ICMP 協議說明

雖然工作在網路層,看上去和 IP 協議是並列的,但是 ICMP 報文要附加 IP 頭,一般被 IP 層或者更高層的協議(例如TCP或UDP)使用。很少有應用程式直接使用 ICMP 協議,除了 pingtraceroute

為什麼說 ICMP 協議是網路最強輔助

ICMP 協議格式

ICMP 協議格式和 IP 協議、TCP 協議這些比起來,那還是非常簡單的。

為什麼說 ICMP 協議是網路最強輔助

型別

型別欄位佔用 8 位,主要定義報文的大類,比如型別為 3 統一表示的是不可達,而具體原因是什麼則要由程式碼欄位決定。

程式碼

程式碼欄位同樣佔用 8 位,程式碼欄位其實就是型別下的子型別,比如上面說了型別為 3 是不可達,程式碼為 0 表示網路不可達,程式碼為 1 表示主機不可達。

檢驗和

用於錯誤檢查,和 IP 協議的檢驗和的作用一致。

內容

因為型別和程式碼不同,表示產生差錯的原因不同,不同的原因都要有對應的描述,內容這部分就是用來描述產生差錯的原因的。

接下來會舉幾個例子說明。

下面這張圖是 ICMP 的分類,包括查詢報文和差錯報文,需要原始 Excel 的同學可以回覆 ICMP獲取原始檔。

為什麼說 ICMP 協議是網路最強輔助

目的不可達差錯報文

目的不可達是網路傳輸中經常遇到的問題,各位在開發的過程中可能也碰到過,尤其是做網路程式設計的時候,經常會碰到,比如連錯IP了,比如埠設定錯了。

透過上表可知,當型別為 3 的時候,都是不可達的錯誤,而程式碼可以從 0 -15,也就是說有16種不可達的具體原因。這種情況下的協議格式是下面這樣的。

為什麼說 ICMP 協議是網路最強輔助

型別為 3 ,程式碼 0 - 15。檢驗和後面有 4 個位元組的空間是不使用的,但是必須為0 ,沒理由,就這樣。

前面說到了內容部分是根據型別和程式碼不同而不同的。如果是目的不可達,也就是型別是 3 的情況下,內容分為兩部分,IP首部和原始IP資料包中資料部分的前 8 個位元組。

原始IP資料包中資料部分指的就是TCP或者UDP這些網路層之上的協議,拿 TCP 來說,TCP 是傳輸層的,當 TCP 資料包到達網路層,會加上 IP 首部,變成一個 IP 資料包。所以這裡說的資料部分就是 TCP 資料包,但是這個資料包可能很大,所以只用前 8 個位元組就夠了,因為前8個位元組包含的資訊已經足夠用了。

回想一下 TCP 協議的格式,前 8 個位元組就是下圖紅框部分,包含源埠和目的埠以及序號。

為什麼說 ICMP 協議是網路最強輔助

例如程式碼為 3 的時候,差錯資訊是埠不可達,那有了 TCP 協議的前8個位元組就能知道導致這個錯誤的原始資料包文中的目的埠是多少,不可達的埠也就是這個埠。也可以知道原始報文的源埠是多少,有了源埠號就知道這個資料包是哪個使用者程式發出來的,就可以交給這個程式對這個差錯及時進行處理了。

源埠號是關聯使用者程式的重要標示,比如我們開發了一個應用,這個應用佔用了 8888和8898兩個埠,如果安裝了這個應用的機器收到了一個差錯報文,而差錯報文中的內容部分的原始資料包前8個位元組拆解後,發現源埠是8898,那就知道這個要交給我們開發的這個應用去處理了。

下面是一個埠不可達的差錯報文,用 WireSharek 監測到的格式。

telnet 一個沒有開放的埠即可獲得 ICMP 埠不可達的差錯報文。

為什麼說 ICMP 協議是網路最強輔助

查詢報文

將 ICMP 用作查詢報文的場景比較少,用作查詢報文的意思就像是使用 ARP 協議或者 TCP 協議這種,是我們主動發起的,只不過選了 ICMP 協議。

比如 pingtraceroute這兩個,之後我們再講,這兩個比較有意思,對 ICMP 應用很巧妙。

另外,可以用作無盤系統啟動過程中來獲取自身的子網掩碼。還可以用作向第三方系統查詢當前的時間戳。

瞭解一下就可以了。

有一些場景不傳送差錯報文

有些場景下是不傳送差錯報文的,這樣做的目的是為了防止ICMP差錯報文帶來廣播風暴。

  1. ICMP差錯報文字身發生差錯,是不會對差錯報文再傳送差錯報文的。是不是讀起來有點繞,TCP 、UDP 出錯會傳送差錯報文,但是 ICMP差錯報文在通知源端的過程出錯了,那就不管了,要不然可能就沒玩沒了的發了,比如源端的網線斷了。但是, ICMP查詢報文可能會產生ICMP差錯報文,比如ping命令在傳輸過程中出錯了,源端會收到差錯報文。

  2. 目的地址是廣播地址或多播地址(D類地址)的IP資料包,不傳送差錯報文。

  3. 作為鏈路層廣播的資料包,不傳送差錯報文,ARP 就是典型的鏈路層廣播資料包。

  4. 不是IP分片的第一片,不傳送差錯報文。資料如果過長,網路層是會進行分片的,這些分片實際上還是同一個資料包的,這種情況下只對第一片傳送差錯報文,其他分片不管。

  5. 源地址不是單個主機的資料包,不傳送差錯報文。 源地址不能為零地址、環回地址、廣播地址或多播地址。

總結

1、 ICMP 在網路層,但要加上 IP 首部;

2、ICMP 分為查詢報文和差錯報文,主要用到的還是差錯報文;

3、ICMP 的差錯報文就好像一個只通知壞訊息的資訊,當資料包在網路中出現問題的時候,及時告知源端,告知的內容包括原因以及產生錯誤的原始資料包的必要部分;

4、有一些情況是不會傳送 ICMP 差錯報文的,這樣做是為了防止網路風暴;


如果覺得還不錯的話,給個推薦吧!

公眾號「古時的風箏」,Java 開發者,專注 Java 及周邊生態。堅持原創乾貨輸出,你可選擇現在就關注我,或者看看歷史文章再關注也不遲。長按二維碼關注,跟我一起變優秀!

為什麼說 ICMP 協議是網路最強輔助