ICMP 協議
定義
網際控制訊息協定,全稱 Internet Control Message Protocol。主要功能是用來 偵測網路當前的狀況
,因為透過 IP 在網路傳遞資料不怎麼可靠,傳遞過程必須經過 多個路由器
轉發才能夠送達目的地,那麼為了確保轉發前能夠安全送達,所以就有了 ICMP 協議。
在網路上,每一個 Node
或是 路由器
都會支援 ICMP 協議,在 彼此的傳遞過程
就可以來互相交換目前網路的狀況資訊,一旦在傳遞的過程中發生錯誤 (例如:主機不可達、路由不可達、網路中斷等),ICMP 協議就會將這些 錯誤資訊的封包傳回主機
進行 錯誤處理
。
其中,ICMP 所產生的報文有兩種,分別是 障礙通知
和 狀況查詢
:
障礙通知
:當主機封包傳送至一半發生問題而無法繼續傳遞,ICMP 就會將原因回傳原主機
。
狀況查詢
:透過發送 ICMP 來查詢目前網路狀況
。
圖片中的不論是
路由器 (1、2)
還是Host B (3)
,都有可能
回傳 ICMP,畢竟我們不知道經過的這些路徑中,是否每個能夠正常運作。
ICMP 格式
ICMP 的報文則是 被嵌入在 IP 報文
內,但是 ICMP 的長度不是固定的,會根據 訊息的類型
而異。
內部 ICMP 格式:
- Message Type:表示
ICMP 的訊息類型
,總共有13 種
的類型,請參考下表。 - Code:
編碼
,對各種訊息類型進一步說明
工作內容,通常都會是0
,類似於HTTP Status Code
。 - Checksum:
錯誤檢查
,用於封包進行錯誤檢查,該校驗和是從ICMP Header 和 Data
替換為 0 的數據計算得出的,Checksum 的演算法則是明確被定義於 RFC 1071 。 - Message Description:
訊息說明
。 - Message Data:
訊息資料
。
Message Type | ICMP 訊息功能 |
---|---|
0 | Echo Reply(回應答覆) |
3 | Destination Unreachable(目的地無法到達) |
4 | Source Quench(來源抑制) |
5 | Redirect(改變傳輸路徑) |
8 | Echo Request(回應要求) |
9 | Router Advertisement(路由器宣傳) |
10 | Router Solicitation(路由器懇請) |
11 | Time Exceeded for a Datagram(溢時傳輸) |
12 | Parameter Problem on a Datagram(參數問題) |
13 | Timestamp Request(時間標籤要求) |
14 | Timestamp Reply(時間標籤回覆) |
15 | Information Request(資訊要求)(停用) |
16 | Information Reply(資訊回覆)(停用) |
17 | Address Mask Request(位址遮罩要求) |
18 | Address Mask Reply(位址遮罩回覆) |
Ping
Ping 是一個簡單的網路工具,用於測試與驗證 目標的 IP Address 是否可用
,或是評估彼此之間的往返的時間 (RTT,Round Trip Time)
,而 Ping 就是使用 ICMP 協議的 Echo Request
向需要評估的網路介面傳遞封包並等待 Echo Reply
。
使用範例
1 | # 設定 ping 的間隔秒數 |
Traceroute
在 IP Header
中的 Options
欄位佔用了 0-40 bytes
(Padding 則是為了讓 IP Header 能夠 以 32位元為倍數
,補足 Options
的長度),其中這個位置就是 ping 用來 存放經過的路由 IP
。
不過在 Options 內又會有 3 bytes
用來儲存欄位資訊,所以最後只會剩下 37 bytes
能夠儲存 IP Address,以 IPv4 的格式計算的話,每個 IP Address 佔用 4 bytes
,最多只能存放 9 個路由
的 IP 位址。
由於這樣的限制,而 traceroute 有了迫切的需求,traceroute 的運作原理則是透過 UDP
協議和 TTL (Time to Live)
去作為 每個路由器的計數器
,每次到達一個路由時,就會讓其 TTL 減 1
,若是 TTL 歸 0
則就會用 ICMP 的超時報文 (Time to live exceed in-transit)
返回原本的主機。
然後再次使用 UDP 協議,但 TTL 會隨著每次經過的路由器而疊加,直到抵達目的 IP Address 後返回 ICMP 端口不可達報文 (Port unreachable)
。
透過每次 TTL 的疊加計算,就可以突破 IP Header 中的 9 個 IP 位址的上限。
每個 TTL 都會
發送 3 個封包
,並且會計算來回的時間
。若是5 秒內
沒有收到任一份回應,就會打印星號 (*)
。
使用場景
通常 Ping 是用來去判斷 兩者之間的網路運作是否正常
和 整體的回應時間
,而使用 traceroute 則是針對了解 所經過路由器的延遲時間
進而分析更細部的問題。
使用範例
1 | $ traceroute google.com |
ICMP 排查
本篇文章將會使用本機的環境 (Macbook) 向 8.8.8.8
Google 的 DNS Server 使用 ping
與 traceroute
工具發送請求,並且透過 Wireshark 對其封包進行解析。
Ping
- 開啟 Wireshark,並在篩選輸入
ip.addr == 8.8.8.8
來查找與該位址一樣的封包,選擇WiFi en0 的網路介面
(網路介面依電腦環境而異,如果是使用乙太網路,可以選擇乙太網路
的選項),並且網路介面上的 filter 輸入host 8.8.8.8
。
- 開啟 command line,輸入 ping 指令,執行 4 次,並可以從 Wireshark 看到封包的動向。
1 | $ ping -c 4 8.8.8.8 |
- ICMP Echo Request 排查。
- Type:
8 (Echo request)
- Code:0
- Checksum:0x97d6
- Identifier:(0xbcf1)(0xf1bc)
- Sequence number:(0x0000)(0x0000)
- ICMP Echo Reply 排查。
- Type:
0 (Echo reply)
- Code:0
- Checksum:0x9fd6
Traceroute
- 操作如 Ping 的
步驟一
。 - 使用 command line,執行 traceroute。
1 | $ traceroute 8.8.8.8 |
可以觀察到,從我的 Macbook 到 8.8.8.8,會經過 9 個 hops (包含 8.8.8.8)
,總共有 30 個封包
,對應每筆請求都會 傳遞 3 個封包的規則
,最後目的位址則是返回 Destintantion unreachable (Port unreachable)
的 ICMP 報文收尾。
如果從 第 3、6 筆
封包也確實有根據 TTL 經過的 路由器數量
來遞增。
這邊其實使用
host 8.8.8.8
將 IP 地址進行過濾,所以可能有人會發現沒有Time to live exceed in-transit
報文,只要不過濾 8.8.8.8 就可以看到相對應資訊,如下圖所示。
參考資料
- https://www.tsnien.idv.tw/Manager_WebBook/chap4/4-5 ICMP 協定與分析.html
- https://sdn.feisky.xyz/wang-luo-ji-chu/index/icmp
- https://www.scaler.com/topics/difference-between-ping-and-traceroute/
- https://youtu.be/yihwHXom_ek