互聯網控制消息協議

G2=IT
互聯網控制消息協議（Internet Control Message Protocol，縮寫：ICMP）是互聯網協議族的核心協議之一。它用於網際協議（IP）中發送控制消息，提供可能發生在通信環境中的各種問題反饋。通過這些信息，使管理者可以對所發生的問題作出診斷，然後採取適當的措施解決。
ICMP 依靠IP來完成它的任務，它是IP的主要部分。它與傳輸協議（如TCP和UDP）顯著不同：它一般不用於在兩點間傳輸數據。它通常不由網絡程序直接使用，除了 ping 和 traceroute 這兩個特別的例子。
IPv4中的ICMP被稱作ICMPv4，IPv6中的ICMP則被稱作ICMPv6。

**技術細節**
ICMP是在 RFC 792 中定義的互聯網協議族之一。通常用於返回的錯誤信息或是分析路由。ICMP錯誤消息總是包括了源數據並返回給發送者。
ICMP錯誤消息的例子之一是TTL值過期。每個路由器在轉發數據報的時候都會把IP包頭中的TTL值減1。如果TTL值為0，“TTL在傳輸中過期”的消息將會回報給源地址。
每個ICMP消息都是直接封裝在一個IP數據包中的，因此，和UDP一樣，ICMP是不可靠的。
雖然ICMP是包含在IP數據包中的，但是對ICMP消息通常會特殊處理，會和一般IP數據包的處理不同，而不是作為IP的一個子協議來處理。在很多時候，需要去查看ICMP消息的內容，然後發送適當的錯誤消息到那個原來產生IP數據包的程序，即那個導致ICMP訊息被傳送的IP數據包。
很多常用的工具是基於ICMP消息的。traceroute 是通過發送包含有特殊的TTL的包，然後接收ICMP超時消息和目標不可達消息來實現的。 ping 則是用ICMP的"Echo request"（類別代碼：8）和"Echo reply"（類別代碼：0）消息來實現的。

**ICMP報文結構**

**報頭**
ICMP報頭從IP報頭的第160位開始（IP首部20字節）（除非使用了IP報頭的可選部分）。- Type - ICMP的類型,標識生成的錯誤報文；- Code - 進一步劃分ICMP的類型,該字段用來查找產生錯誤的原因.；例如，ICMP的目標不可達類型可以把這個位設為1至15等來表示不同的意思。- Checksum - Internet校驗和（RFC 1071），用於進行錯誤檢查，該校驗和是從ICMP頭和以該字段替換為0的數據計算得出的。- Rest of Header - 報頭的其餘部分，四字節字段，內容根據ICMP類型和代碼而有所不同。

**填充數據**
填充的數據緊接在ICMP報頭的後面（以8位為一組）：- Linux的"ping"工具填充的ICMP除了8個8位元組的報頭以外，默認情況下還另外填充數據使得總大小為64字節。- Windows的"ping.exe"填充的ICMP除了8個8位元組的報頭以外，默認情況下還另外填充數據使得總大小為40字節。

**報文類型**

**源站抑制**
源站抑制報文旨在請求發送方降低發往路由器或主機的報文發送速率。在接收的過程中，當接收方沒有足夠的接收緩衝區來處理接收到的報文，或者接收這個報文會導致臨近其本身的緩衝區限制時，就會觸發源站抑制報文。
數據被從一個或一群主機高速地發往網絡上的一個路由器，雖然路由器有緩衝機制，但是路由器的緩衝區大小通常（由於物理內存有限的原因）被限制。因此，如果路由器的通信量過大，路由器最終會（由於內存耗盡，導致必須丟棄掉接收到的數據報）無法繼續處理超過輸入緩衝區限制的部分數據，直到路由器緩衝隊列有空餘空間可以存放新的數據報。但是由於網絡層（Network Layer）缺乏確認訊息（ACK）機制，因此客戶端無法獲知數據是否成功抵達接收方。所以研究者提出了源站抑制這一補救措施來解決這一問題：當路由器發現流入數據速率遠遠高於流出數據速率時，會發送ICMP源站抑制報文給源站，通知源站應該降低其數據傳輸速度或等待一定時間後再嘗試發送更多數據。當源站接收到ICMP源站抑制報文時會減慢數據發送的速度，或者在再次嘗試發送數據前等待一定的時間，使得路由器能夠（在處理完當前接收到的數據之後）清空輸入緩衝隊列。
但是因為有研究表明“源站抑制是一種無效的（不公平的）補救措施“，所以路由的源站抑制報文已在1995年被 RFC 1812 date=20210502114855 棄用。此外，（路由）轉發和回應任何形式的源站抑制報文已在2012年被 RFC 6633 date=20200306033916 棄用
其中:
類型（Type） 必須設置為4
代碼（Code） 必須設置為0
IP數據報頭部 和其附加的數據用於發送端根據回應報文匹配對應的請求報文

**重定向**
關於ICMPv4 重定向報文如何工作的示例圖
重定向 報文是網關發出的，用於要求主機或路由器改變數據報的傳輸路徑的ICMP報文。ICMP 重定向是路由器將路由信息傳達給主機的機制。這種類型的報文通知主機更新它的路由信息（請求主機改變其路由）。如果一個主機在通信時將數據報發送給了路由器R1，而R1將這個數據報轉發給了另一個路由器R2，且主機到路由器R2之間有一條直連的路徑（也就是說，此主機和路由器R2處於同一以太網段上），那麼路由器R1會發送一條重定向報文給主機，來通知它到路由器R2可用路徑裡有一條更短、更優化的路徑。這個主機在接收到這個重定向報文之後應該改變其路由至這個優化版本的路由信息，來將抵達這個目的地的數據報直接發送到路由器R2，並且路由器仍將原始數據報發送到預期目的地。但是，如果一個數據報攜帶有路由信息，那麼即使有更加優化的路徑，路由器也不會發送重定向報文。並且，RFC 1122 指出，重定向報文應該只由網關發送，而不應該由互聯網主機發送。
其中:
類型（Type） 必須設置為 5.
代碼（Code） 指定重定向的原因，見下表
路由器的IP 地址（IP address） 是一個32位的網關IP地址，該地址指明瞭該數據報應該被重定向到的路由器地址。
激發重定向報文的數據報IP首部及其數據的前8字節（IP header） 用於收到重定向報文的主機根據回應報文匹配對應的請求報文，來確定該數據報的目的站地址。

**超時**
超時 報文是網關產生併發送給源站的ICMP報文，用於通知源站有數據報因為存活時間遞減至0而被此網關丟棄。當主機等待數據報分片的過程中超時而無法重新組裝數據報分片時也會產生該報文。
超時報文也用於traceroute工具來識別兩個主機之間的路徑上的網關。
其中:
類型（Type） 必須設置為 11
代碼（Code） 指定重超時的原因，見下表
激發超時報文的數據報IP首部及其數據的前8字節 這些信息用於源站根據收到的超時報文來確定具體哪個數據報已被丟棄。對於高層協議，比如用戶數據報協議 和 傳輸控制協議而言，額外的8字節數據指明瞭已被丟棄的數據報中的源端口與目的端口。

**時間戳請求**
時間戳請求 報文主要用於互聯網機器（包括路由器和主機）之間同步時鐘。起始時間戳是發送端最後一次改動該數據報的時間戳(為世界標準時午夜開始計算的毫秒數)。在該類型的報文中，接收時間戳和傳輸時間戳未被使用。
其中:
類型（Type） 必須設置為 13
代碼（Code） 必須設置為 0
標識符（Identifier） and 序號（Sequence） 用於在時間戳請求報文和時間戳回答報文之間建立關聯
起始時間戳（Originate timestamp） 為世界標準時午夜開始計算的毫秒數。 如果沒有可用的世界標準時參考，則可以將最高有效位設置為1以指示這是一個非標準時間值。

**時間戳回答**
時間戳回答 報文是對時間戳請求報文的回答報文。 時間戳回答報文由接收到的時間戳請求報文其中的起始時間戳和接收時間戳（回應端主機接收到請求報文並創建時間戳回應報文的時間，單位為毫秒）、傳輸時間戳（時間戳回答報文被髮送出去的時間，單位為毫秒）組成。
其中:
類型（Type） 必須設置為 14
代碼（Code） 必須設置為 0
標識符（Identifier） 和 序號（Sequence number） 用於在時間戳請求報文和時間戳回答報文之間建立關聯。
起始時間戳（Originate timestamp） 是發送端最後一次改動該數據報的時間戳。
接收時間戳（Receive timestamp） 是回應端主機接收到請求報文並創建時間戳回應報文的時間，單位為毫秒。
傳輸時間戳（Transmit timestamp） 是最後一次修改回應報文並將其發送出去的時間，單位為毫秒。
所有的時間戳都是世界標準時午夜起始的毫秒數。如果這個時間不能表示為毫秒或者沒有可用的世界標準時參考值，則可以使用任何格式的時間值並將最高有效位設置為1以指示這是一個非標準時間值。

**地址掩碼請求**
地址掩碼請求 報文是主機為了得到一個合適的子網掩碼而發送到路由器的ICMP請求報文。
接收到此請求報文的機器應當發送一個地址掩碼回答報文給源站。
其中:
類型（Type） 必須設置為 17
代碼（Code） 必須設置為 0
地址掩碼（Address mask） 可以為0
由於ICMP 地址掩碼請求可能會被用於嗅探攻擊來收集特定網絡的信息，因此該報文默認情況下被Cisco IOS禁用。

**地址掩碼回答**
地址掩碼回答 報文攜帶有地址掩碼信息，用於回答地址掩碼請求報文。
其中:
類型（Type） 必須設置為 18
代碼（Code） 必須設置為 0
地址掩碼（Address mask） 為待回答的地址掩碼

**源站不可達**
源站不可達 報文是由主機或入站網關用於通知客戶端出於目的站無法連接的報文。這些原因可能包括：物理連接失效（也即網絡距離無限大），或指定的地址或端口處於非激活狀態，或者數據報長度過長而導致必須分片但是IP首部指定了“不分片”選項導致無法分片。如果是TCP端口不可達，則會返回TCP RST，而不會返回此報文。如果是IP多播的情況，也不會返回此報文。
其中:
類型（Type） 必須設置為 3
代碼（Code） 字段用於指示具體導致源站不可達的原因。見下表。
Next-hop MTU 當需要分片但是DF(Do not Fragment)置位的錯誤發生時，包含了下一跳網絡的MTU的值。
IP header 用於源站根據收到的源站不可達報文來確定具體哪個數據報引起了源站不可達錯誤。

**參考**

**外部連結**
 RFC 792, Internet Control Message Protocol-  ICMP Sequence Diagramdate=20201106230229 - RFC 1122, Requirements for Internet Hosts -- Communication Layers- RFC 1716, Towards Requirements for IP Router- RFC 1812, Requirements for IP Version 4 Routers- RFC 6633, Deprecation of ICMP Source Quench Messages-  Filtering ICMP on firewalls-  IANAdate=20190627121159