可能是目前最全的講 ICMP 的文章了
對于 ICMP 協(xié)議,你想知道的,可能包括以下幾點:
- ICMP 是啥
- 為啥需要 ICMP
- ICMP 有哪些報文類型
- ICMP 報文格式長啥樣
- 有哪些命令用了 ICMP
- ICMP 有哪些內(nèi)核參數(shù)
- ICMP 的問題
帶著這些問題,下面我們就來一一解答。
1. ICMP 是啥
ICMP,全稱是 Internet Control Message Protocol,即互聯(lián)網(wǎng)控制報文協(xié)議,所謂控制,就是通過下發(fā)指令來感知和控制網(wǎng)絡(luò)環(huán)境,所以它一定是配合一個無法感知網(wǎng)絡(luò)環(huán)境的協(xié)議來工作的,這個協(xié)議就是 IP(包括 IPv4 和 IPv6)。
所以,ICMP 通常被認為是 IP 協(xié)議的一部分,它封裝在 IP 層中,使用 IP 協(xié)議進行傳輸。因此,嚴格來說,ICMP 既不是一個網(wǎng)絡(luò)層協(xié)議,也不是一個傳輸層協(xié)議,而是介于兩者之間的一個協(xié)議。
它的主要功能是傳輸網(wǎng)絡(luò)診斷信息,信息主要包括兩類:
- 一類是 查詢類報文 :主要用于信息的查詢和采集,比如采集傳輸路徑上的每個路由器都是誰,本次傳輸?shù)膱笪氖欠襁_到目的地等等。
- 另一類是 差錯診斷類報文 :主要用于診斷網(wǎng)絡(luò)故障,比如傳輸報文被丟棄的原因是什么等等。
2. 為啥需要 ICMP
我們都知道,IP 協(xié)議是一個不可靠協(xié)議,如果 IP 包在傳輸過程中出現(xiàn)錯誤,比如 checksum 對不上,擁塞,超時等等,那么 IP 包是會直接被丟棄的,之后也不會有進一步的努力來修正。
這是 IP 協(xié)議的一個設(shè)計準則決定的,也就是 best effort,盡力而為,這樣的好處是讓 IP 協(xié)議盡量保持簡單的形態(tài),只負責有效率的數(shù)據(jù)傳輸,而更多的質(zhì)量控制交給高層的協(xié)議去處理(比如 TCP)。
但高層能提供質(zhì)量控制的協(xié)議畢竟在少數(shù),所以就需要在下層有協(xié)議來輔助 IP 完成必要的網(wǎng)絡(luò)質(zhì)量管理。ICMP 協(xié)議自然就被提出來了。
通過 ICMP 協(xié)議,當 IP 包發(fā)生錯誤的時候,上層發(fā)送 IP 包的主機或路由器并不知道下層發(fā)生了錯誤,這個時候,下層的主機或路由器就可以通過發(fā)送 ICMP 包,將錯誤信息匯報給上層,從而讓上層的主機或路由器進行調(diào)整。
不過需要注意的是,ICMP 僅僅只能提供某些特定類型的錯誤信息匯報,并不能幫助 IP 協(xié)議成為可靠的協(xié)議。它能做的事還是有限,但用于基本的網(wǎng)絡(luò)質(zhì)量管理是足夠了。
3. ICMP 報文格式長啥樣
如下圖所示,ICMP 報文是被封裝在 IP 數(shù)據(jù)報中傳輸?shù)摹?/p>
IP 報頭中的 Protocol 字段為 1 即表示該報文攜帶的是 ICMP 報文。(此處只是為了說明問題,因此 IP 報頭是簡化了的)
進一步看,ICMP 報頭為 4 個字節(jié):
- 類型 type:占 1 個字節(jié),表示較大范圍類型分類的 ICMP 報文
- 代碼 code:占 1 個字節(jié),表示較小范圍類型分類的 ICMP 報文(type的細分)
- 校驗和 checksum:占 2 個字節(jié),ICMP checksum 的計算方法類似于 IP checksum,但是不同的是 IP 只校驗頭部,ICMP 校驗頭部+數(shù)據(jù)部分
后面緊接的 ICMP 數(shù)據(jù)部分,根據(jù)前面的類型和代碼字段的不同,具有不同的內(nèi)容。
4. ICMP 有哪些報文類型
ICMP 支持的報文類型非常多,詳細看下表:
類型字段指代了一大類,代碼字段又細分了幾大小類。
上面可能不夠明確,我們通過下面這兩張表來列舉一下,由于類型太多了,而且有些平時非常少見,因此,這里我們只列舉常見的一些類型。
第一張表:類型表
注:R表示查詢報文,E表示差錯報文
進一步,對于每種類型,又可以根據(jù)代碼字段細分多種子類型,請看第二張表:
第二張表:類型細分表
通過這兩張表,每一種類型的 ICMP 包的意思應(yīng)該都比較清楚了。
有一種可能不太好理解,這里再重點講解一下:
(1) 源端抑制
屬于差錯信息。如果某個源主機向目的主機快速地發(fā)送數(shù)據(jù)包,但目的主機來不及處理,就會向源主機發(fā)出該類型的 ICMP 包,提醒源主機放慢發(fā)送速度。
(2) 重定向
屬于差錯信息。如果某個源主機向網(wǎng)絡(luò)中發(fā)送一個 IP 包,路徑中某個路由器收到這個 IP 包,對照其路由表,發(fā)現(xiàn)自己不應(yīng)該接收該包(包需要原路返回,或者不是最佳路由路徑),就會向源主機發(fā)送該類型的 ICMP 包,提醒源主機修改自己的路由表,下次路由到另外一個更好的路由器。
(3) 需要分片但設(shè)置了不分片位
屬于差錯信息。如果某個源主機在發(fā)送一個 IP 包之前,對該 IP 包中的首部字段 DF 位設(shè)為 1,也就是“分片禁止位=1”,表示該包在傳輸?shù)倪^程中不允許分片,但是中間某個路由器允許傳輸?shù)淖畲舐窂?MTU 小于該包大小,需要分片才能傳輸,但是由于設(shè)置不分片位,路由器會將該包丟棄,并向源主機發(fā)送一個攜帶 MTU 信息的 ICMP 包,提醒源主機下次發(fā)包的大小不應(yīng)超過該 MTU 的值。
這種類型的 ICMP 包通常用來發(fā)現(xiàn)傳輸路徑上的 MTU 值。
(4) TTL超時
屬于差錯信息。超時定義了數(shù)據(jù)包在網(wǎng)絡(luò)中存活的最長時間,IPv4 中的 TTL 字段和 IPv6 中的 Hop Limit 字段都表示了這層意思,它們是一個整數(shù)值,會隨著經(jīng)過的路由器而遞減,當減為 0 時,就認為該 IP 包超時,然后當前減為 0 的路由器會向源主機發(fā)送 ICMP 包,通知它發(fā)生了超時錯誤。
5. 有哪些命令體現(xiàn)了 ICMP
ICMP 的這些包的類型,用戶可以充分用來診斷網(wǎng)絡(luò)的故障情況。
因此誕生了一些利用 ICMP 協(xié)議的網(wǎng)絡(luò)診斷工具,其中比較知名的就是 ping 和 traceroute。這兩工具分別利用兩種類型的 ICMP 報文:
- ping 使用查詢類型報文
- traceroute 使用差錯類型報文
(1) ping
ping 使用了查詢報文中的請求報文(類型為 8)和應(yīng)答報文(類型為 0),主要查詢某個網(wǎng)絡(luò)節(jié)點的連通性,如果出現(xiàn)網(wǎng)絡(luò)不連通的情況,具體是什么問題,會在應(yīng)答報文中附帶相關(guān)的差錯信息予以告知。比如網(wǎng)絡(luò)不可達(Network Unreacheable)、主機不可達(Host Unreachable)等等,然后用戶就可以根據(jù)這些信息來分析具體是哪個環(huán)節(jié)出現(xiàn)問題。
下面一張圖,顯示了一個 ping 包的完整流程:
可以看到,通過各層協(xié)議棧的層層封裝和解封裝,一個 ping 包從一臺主機發(fā)送到另一臺主機,包括請求包和應(yīng)答包。其中,如果目標 MAC 地址未知的話,需要先發(fā)出 ARP 請求拿到,然后再進行封裝。
關(guān)于 ping 命令的使用案例可以參考這篇文章:ping容易忽略的10點用法和排查問題技巧。
(2) traceroute
traceroute 是類 Linux 系統(tǒng)自帶的工具,Windows 上類似的工具是 tracert,兩者有些許不同,tracert 默認使用 ICMP 報文探測,而 traceroute 默認使用 UDP,但是也可以使用 TCP/ICMP 三種報文探測。
traceroute 利用 ICMP 差錯報文,主要用來確定這幾件事:
- 確定通信雙方路徑上經(jīng)過的路由器設(shè)備
- 確定 UDP 包是否成功達到目的地
- 發(fā)現(xiàn)路徑 MTU
確定通信雙方路徑上經(jīng)過的路由器設(shè)備 。就是利用上面提到的超時類型的 ICMP 報文來實現(xiàn)。traceroute 向目的地發(fā)送 IP 包,剛開始的時候,將 TTL 設(shè)置為 1,當經(jīng)過第一個路由器時,TTL -1 = 0 引發(fā)超時錯誤,第一個路由器回復(fù) ICMP 超時報文,源主機就可以知道路徑第一個路由器的信息,隨后 TTL 被設(shè)置為 2、3、4, ...,直到到達目的地,這樣,沿途每個路由器都會向源主機回復(fù) ICMP 超時報文,traceroute 就可以拿到所有的路由器信息了。
不過這里要 注意 ,并不是所有路由器都會返回 ICMP 報文,因為出于安全性考慮,大多數(shù)防火墻以及啟用了防火墻功能的路由器都默認配置為不返回任何 ICMP 報文,管理員也會主動配置,所以這時使用 traceroute 就不一定能拿到所有路由器信息了。
確定 UDP 包是否成功達到目的地 。使用上面的方法能拿到路由器信息,但并不能確定發(fā)的包是否到達目的地。traceroute 通過發(fā)送 UDP 包來解決了這個問題,因為 UDP 包的可用端口號范圍 <3000,所以就可以在發(fā)送 UDP 包的時候填入一個 >3000 的端口號,這樣,如果當包確實到達了目的地,由于端口不匹配,就會返回一個端口不可達的 ICMP 報文,源主機就可以確定包確實到了目的地了。
發(fā)現(xiàn)路徑 MTU 。這塊在上面講 “需要分片但設(shè)置了不分片位” 類型報文的時候已經(jīng)講過,traceroute 就是利用這種類型報文來逐一地確認傳輸路徑上各個路由器之間的 MTU 值。
關(guān)于 traceroute 命令的使用案例可以參考這篇文章:排查網(wǎng)絡(luò)問題,請務(wù)必掌握這款工具。
(3) MTR
MTR 全稱 my traceroute,相對以上兩個其實是更好的網(wǎng)絡(luò)排障工具,只是用的人不多,導(dǎo)致它不太出名。之所以說它好,是因為它結(jié)合了 ping 、nslookup、traceroute 三款工具的特性。
關(guān)于 MTR 的安裝和使用分析詳見這篇文章:這款網(wǎng)絡(luò)排查工具,堪稱神器!
(4) tcptraceroute
這塊工具從名稱就可以看出,是基于 TCP 的 traceroute,也就是它使用 TCP 包(具體是 TCP 的 SYN 包)來進行網(wǎng)絡(luò)探測,而不是 ICMP 包。
從上面我們已經(jīng)知道,traceroute -T 就是使用 TCP 包進行探測,所以 tcptraceroute 其實等效于 traceroute -T 。
使用 TCP 包進行探測的原因,主要是因為現(xiàn)代廣泛使用的防火墻,出于安全的考慮,都會攔截 UDP 包和 ICMP 包,而通常不會攔截 TCP SYN 包。所以使用 TCP 包探測能夠通過大多數(shù)的網(wǎng)絡(luò)設(shè)備,使探測結(jié)果更加精確。
6. ICMP 有哪些內(nèi)核參數(shù)
總結(jié)了下面一幅圖,其中比較常用的是 net.ipv4.icmp_echo_ignore_all,這是禁 ping 的一個參數(shù),禁 ping 有幾種方法,可以參考這篇文章:Linux禁止ping以及開啟ping的方法。
其他的參數(shù)大家有興趣也可以看看,遇到不懂的直接查這個圖即可。
7. ICMP 的問題
ICMP 協(xié)議是 IP 協(xié)議的助手,能夠為 IP 協(xié)議提供相關(guān)的故障診斷和控制信息,但 ICMP 仍然不能為 IP 提供可靠性,最常見的丟包(路由器緩沖區(qū)溢出)并不會觸發(fā)任何的 ICMP 信息,只能由其他協(xié)議如 TCP 來處理這種情況。
此外,正因為 ICMP 能夠查詢網(wǎng)絡(luò)設(shè)備相關(guān)的配置信息,并且使用簡單,黑客們都比較青睞使用 ICMP 報文來構(gòu)建攻擊報文。所以很多的網(wǎng)絡(luò)設(shè)備都會用防火墻來阻止 ICMP 報文,這讓很多診斷工具,比如上面介紹的幾種,都很難發(fā)揮用武之地。
常見的 ICMP 攻擊是 ICMP 泛洪攻擊,這是一種 DDoS 攻擊。簡單說就是攻擊者向一個子網(wǎng)的的廣播地址發(fā)送多個 ICMP echo 包,包的源地址偽裝成他想要攻擊的目的主機的 IP,然后該子網(wǎng)的所有主機的 ICMP reply 包都會送到被攻擊主機,該主機瞬時收到大量的 ICMP 回復(fù)包,消耗大量資源,來不及處理,便會進入癱瘓或無法提供正常服務(wù)。
解決 ICMP 泛洪攻擊最簡單的方法就是禁 ping 了。只要禁 ping,不管黑客有多少肉機,他都無可奈何了。