ICMP

6.8k 词

關於ICMPv4, ICMPv6, ping和traceroute你所需要知道的一切

ICMPv4

ICMPv4 是 IPv4 協議簇中負責傳遞控制訊息和錯誤報告的核心機制。雖然它封裝在 IP 報文中,但它被視為 Network Layer 的一部分。

報文結構

1
2
3
4
5
6
7
8
9
 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Rest of Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data Payload |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Type (8 bits): 定義報文的大類(如錯誤報告或查詢)
  • Code (8 bits): 提供Type的具體上下文(如「目的不可達」的具體原因)
    • e.g.
      • Type 3: Destination Unreachable
      • Code 4: Fragmentation Needed and Don’t Fragment set
  • Checksum (16 bits): 使用One’s Complement算法,覆蓋整個ICMP報文(Header + Data)
  • Rest of Header (32 bits): 內容取決於Type/Code
  • Data Payload

報文分類

ICMPv4訊息可以分爲兩大類: 差錯報告查詢

  • 差錯報告 (Error Message):
    此類報文用於反饋網路層傳輸中的異常,絕對不會對「差錯報告報文」再生成差錯報告(防止廣播風暴)
    • 終點不可達 (Destination Unreachable, Type 3):
      當Router或Host無法交付數據包時發送,原因通過Code區分: 網路不可達、主機不可達、協定不可達或埠不可達
      現代防火牆經常過濾這些回顯,導致traceroute在互聯網上呈現 * * * 的狀態
      • Code 0/1 網絡/主機不可達(路由表缺失或ARP失敗)
      • Code 3 埠不可達(目標主機無進程偵聽該TCP/UDP埠)
      • Code 4 Fragmentation Needed and DF set
        這是PMTUD (Path MTU Discovery)的基礎,Router丟棄大於MTU且DF=1的包,並回傳此報文及Next-Hop MTU
    • 原點抑制 (Source Quench, Type 4):
      此報文已基本廢棄,參見RFC 6633
    • 重定向 (Redirect, Type 5):
      Router通知Host對於目標地址,有更優的next hop路徑,常見於多Gateway局域網
    • 超時 (Time Exceeded, Type 11):
      • Code 0: TTL在傳輸過程中減至0,Router丟棄數據包並通知源主機
      • Code 1: 分片重組超時
  • 查詢 (Query Message)
    • 回送請求/回答 (Echo Request/Reply, Type 8/0):
      ping工具的基礎,用於測試目標可達性及測量往返延遲 (RTT)
    • 時間戳請求/回答 (Timestamp Request/Reply, Type 13/14):
      在現代網路架構中被NTP取代
      出於安全考慮(防止指紋識別、正常運行時間推斷等),現代防火牆和操作系統默認幾乎都會Drop掉這類報文

ICMP Echo Request/Reply Type 8/0 報文結構

1
2
3
4
5
6
7
8
9
 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type (8/0) | Code (0) | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data (Optional, usually timestamp or alpha-numeric) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Identifier: 用於區分並行ping任務,常爲ping進程pid
  • Seq Num: 序列號,每傳送一個包自增1,用於檢測丟包和亂序

差錯報告報文結構

1
2
3
4
5
6
7
8
9
 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type (3) | Code (0-15) | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Rest of Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Original Packet |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Rest of Header
對於Type 3 Code 4,應包含Next-Hop MTU;
對於Type 5,應包含Gateway Address;
對於其他Type 3代碼,Rest of Header不使用且必須爲0

data payload特殊性
在RFC 792的原始定義中,Data Payload要求包含IP Header + 原始數據的前64 bits
 這是因爲數據包的前8 Bytes足以包含TCP/UDP頭的src port/dst port訊息,足以src host追溯引發問題的程式
在RFC 1812的現代實踐中,Data Payload要求儘可能包含原始數據包的內容,但是總長度不應超過576 Bytes (Minimum Reassembly Buffer Size),以避免分片,確保錯誤報告能被任意接收端處理

ICMPv6

IPv4和IPv6的ICMP雖然名字相似,但地位完全不同,ICMPv4是輔助,ICMPv6是核心架構,ICMPv6合併了IPv4的ICMP,ARP,IGMP,甚至接管了部分DHCP的功能
你最好不要將二者混爲一談

報文結構

1
2
3
4
5
6
7
8
9
 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Message Body +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

看上去和ICMPv4相同?確實,前4 Bytes的格式是相同的
但是需要注意的是,ICMPv6的checksum計算時包含IPv6 Pseudo-Header(會在下一小節中講到)

因爲在IPv6中ICMPv6 (RFC 4443) 是一個極其龐大的協定簇,合併了IPv4中的ICMPv4, ARP, IGMP的功能,故Message Body在ICMPv6中的形式會更多變
在這篇文章當中沒有辦法完整的闡述ICMPv6協定,只會例舉一些Common Packets

ICMPv6 報文校驗

與ICMPv4不同,ICMPv6的校驗和計算強制包含IPv6 Pseudo-Header,包括:

  • Source Address (128 bits)
  • Destination Address (128 bits)
  • Upper-Layer Packet Length (32 bits)
  • Zero (24 bits)
  • Next Header (8 bits, 值固定爲58)

TLV選項結構

Options字段是ICMPv6的強大之處所在
在NDP和RA中,報文會攜帶多個Option,每個字段都遵循以下原則

1
2
3
4
5
 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Op. Type | Op. Length | Op. Data (Variable) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段 長度 描述
Type 8 bits Option Type
Length 8 bits Option Length (Length value = 1, Total Option Length = 8 Bytes (Type + Length + Value + Padding))
Value Variable 實際內容

ICMPv6 Packet Too Big, Type 2 報文結構

ICMPv6 Packet Too Big是IPv6路徑MTU發現的核心
IPv6強制要求端到端分片。若路由器發現包體超過出路徑MTU,唯一的處理方式是丟棄並返回Type 2報文,src host再根據收到的Type 2報文重新分片數據包並傳送

1
2
3
4
5
6
7
8
9
 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type (2) | Code (0) | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MTU |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Invoking Packet |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • MTU (32 bits): 明確告知src host Next-Hop MTU
  • Invoking Packet: 根據RFC 4443,應盡可能多地包含原始數據包,直到ICMPv6報文本身達到IPv6的最小MTU (1280 Octets),以確保錯誤報告能被任意接收端處理

ICMPv6 Neighbor Solicitation, Type 135/136 報文結構

ICMPv6 Neighbor Solicitation的功能等同於ARP,但使用Multicast而非Broadcast,大幅減少對鏈路層無關節點的干擾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type (135) | Code (0) | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved (0) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Target Address (128 bits) +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Op. Type | Op. Length | Op. Data (Variable) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

注意:
 Reserved欄位必須發送爲0,接收方必須忽略,這是協議擴展性的預留
 NS報文中的Target addr不得爲Multicast addr
 上方報文結構主要展示的是Type 135, 對於Type 136, Reserved被替換爲Router, Solicited, Override標誌位,佔29 bits,需要通過其標誌位來更新鄰居緩存狀態

IPv4 v.s. IPv6: 爲什麼ICMPv6很重要?

爲了解決IPv4協定簇碎片化的問題,IPv6將ARP, IGMP等協定全部併入IPv6,通過Type+Code+Checksum+Options的結構,將鏈路層尋址、組播管理、自動配置全部歸入同一個協定內
e.g.:

功能 IPv4 IPv6 變化
L2地址解析 ARP IPv6 NDP, ICMPv6 Type 135/136 based 從Broadcast到Multicast,減少網路噪音
整合進L3協定便於管理
組播成員管理 IGMP IPv6 MLD, ICMPv6 Type 130-132 based 協議棧簡化,直接復用ICMPv6
路徑MTU Router分片
ICMPv4 Destination Unreachable: Fragmentation Needed and DF Set, Type 3 Code 4通告
Router禁止分片
ICMPv6 Packet Too Big, Type 2告知src host路徑MTU
src host分片
Router去除繁重的分片任務,推動End2End原則
位址自動配置 DHCP IPv6 SLAAC, ICMPv6 Type 133/134 based 實現「即插即用」,由Router直接下發前綴

在解析ICMPv6的時候,需要特別注意以下三點:

  1. 分片限制:
    ICMPv6 Error Messages報文不允許分片,若報文超過MTU(通常受限於IPv6最小MTU 1280 Bytes),路由器必須對Message Body中的原始數據包進行截斷,確保整個ICMPv6報文能放入單個IPv6幀中發送
    ICMPv6 Informational Messages報文不推薦分片,但是在Node Information Response、超大Payload的Echo Reply等特殊極端場景下允許分片
  2. SEND (SEcure Neighbor Discovery) & RA Guard:
    因爲IPv6 NDP替代了ARP協定,故對ICMPv6協定本身產生了安全性需求
    RFC 3971爲ICMPv6引入了SEND,在Options中引入了加密簽章
    在Switch層面,必須配置RA Guard (Router Advertisement Guard),防止惡意主機僞裝成Router發送RA報文,篡改網路前綴或Gateway
  3. Multicast依存:
    ICMPv6中的很多功能依賴於被請求節點多播位址 (Solicited-Node Multicast Address)
    這意味着在Switch層面,MLD Snooping的配置對於ICMPv6的正常工作至關重要,如果MLD Snooping配置錯誤可能會導致NDP解析失敗,表現爲路由表正確但是無法ping通的詭異現象

報文類型規劃

ICMPv6重新規劃了Type值的範圍,使其更具有邏輯性
Type 0-127爲差錯,Type 128-255爲訊息
部分ICMPv4中的Destination Unreachable, Type 3子類被獨立爲新的Type
 e.g.
  ICMPv4 Destination Unreachable (Fragmentation Needed and DF set), Type 3 Code 4
   ↓↓↓
  ICMPv6 Packet Too Big, Type 2