之所以說 ICMP 最容易被忽略,是因為,大部份的情況下,ICMP 只給底層的網路設備參考且被解決了。真要勞架使用者執行的話,恐怕不多,最具代表的,算是 ping 與 traceroute 這兩個工具了。下面,讓我們一起揭開 ICMP 的神秘面紗...
ICMP 協定之內容
ICMP 的全稱是 Internet Control Message Protocol 。從技術教度來說,ICMP 就是一個 "錯誤偵測與回報機制",其目的就是讓我們能夠檢測網路的連線狀況﹐也能確保連線的準確性﹐其功能主要有﹕
· 偵測遠端主機是否存在。
· 建立及維護路由資料。
· 重導資料傳送路徑。
· 資料流量控制。
ICMP 在溝通之中,主要是透過不同的類別( Type )與代碼( Code ) 讓機器來識別不同的連線狀況。常用的類別如下表所列﹕


ICMP 是個非常有用的協定﹐尤其是當我們要對網路連接狀況進行判斷的時候。下面讓我們看看常用的 ICMP 實例,以更好了解 ICMP 的功能與作用。
關于 PING
當關于這個命令應該很多人都用過了吧﹖它就是用來測試兩臺主機是否能夠順利連線的最簡單的工具﹕

在 Linux 使用 ping 命令﹐如果您不使用 -c N 參數來指定送出多少個 ICMP 封包的話﹐ping 命令會一直持續下去﹐直到您按 Ctrl + C 為止。從上面的命令結果我們可以確定連線是否成功之外﹐還可以根據它的 time 來判斷當前的連線速度﹐數值越低速度越快﹔在命令結束的兩行﹐還有一個總結﹐如果發現您的 packet loss 很嚴重的話﹐那就要檢察您的線路品質﹐或是上游的服務品質了﹔最后一行是 round-trip (來回)時間的最小值﹑平均值﹑最大值﹐它們的時間單位都是微秒 (ms)。不過﹐那個 mdev 是什么意思我也不知道~~
如果運用得當﹐ping 可以幫我們判斷出許多狀況。例如﹐我們要看一下跟遠方的機器是否連接得上﹐先可以 ping 一下對方的機器名稱﹔如果連接不上的話﹐我們可以 ping 對方的 ip ﹐如果 ip 可以 ping 得到﹐那么﹐很可能是 dns 不工作了﹔那么我們可以檢查本身主機的 dns 伺服器是否指定正確、以及 dns 伺服器是否設定正確。如果連 IP 都 ping 不了﹐那么﹐很可能是 IP 設定的問題了﹐也可能是網路的連線問題。檢查的步驟也有很多種﹐下面是方法之一﹕ bitsCN#com中國網管聯盟
1. ping 對方的 router (如過您知道其位址的話)﹐假如 ping 得上﹐那可能是對方機器和其相連網路的問題﹔
2. 如果 ping 不到對方的 router ﹐那么可以 ping 自己的 router。如果 ping 得上﹐那么好可能是 router 和 router 之間的問題﹔
3. 如果自己的 router 也 ping 不到﹐那么可能是自己的機器和 router 之間的問題﹐我們可以 ping 一下自己的 IP 。如果自己的 IP 可以 ping 得到﹐那么﹐可能是連線的問題﹐我們可以檢查一下網線、hub、等設備﹐看看有沒有損毀的狀況。
4. 同時﹐我們也可以 pin g一下網路上面其它的機器﹐也可以用其它機器 ping 一下 router ﹐來判別一下問題來自自己機器、還是網路、還是 router、等等。
5. 如果自己的 IP 都 ping 不到﹐那么可能是網路卡壞掉了或沒有正確設定﹐可以看看設備資源有沒有沖突﹐也可以看看設備有沒有被系統啟動。
6. 如果看來都沒問題﹐那么可以 ping 一下回圈位址 127.0.0.1 ﹐如果連這個都 ping 不了的話﹐這臺機器的 IP 功能根本就沒被啟動﹗那么﹐您就要先檢查一下網路功能有沒有選擇、IP 協定有沒有被綁定( bind )、等基本網路設定了。
從上面的過程中﹐我們不難看出 ping 這個命令真是非常有用的。然而,我們能 ping 一臺機器的時候﹐我們就可以確定連線是成功的﹐但如果不能 ping 的話﹐未必是連不上哦。嗯﹖怎么說呢﹖且聽我道來﹕使用 ping 命令的時候﹐事實上是送出一個 echo-request( type 8 ) 的 ICMP 封包﹐如果對方的機器能接收到這個請求﹐而且愿意作出回應﹐則送回一個 echo-reply( type 0 ) 的 ICMP 封包﹐當這個回應能順利抵達的時候﹐那就完成一個 ping 的動作。 bitsCN#com中國網管聯盟
很顯然﹐如果這個 echo-request 不能到達對方的機器﹐或是對方回應的 echo-reply 不能順利送回來﹐那 ping 就失敗。這情形在許多有防火墻的環境中都會碰到﹐如果防火墻隨便將 request 和 reply 攔下來就會導致 ping 失敗﹐但并不代表其它連線不能建立。另外﹐就算沒有防火墻作怪﹐對方也可以將機器設定為不回應任何 echo-request 封包﹐若在 Linux 上,只要用下面命令就可以了﹕
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
如果您不想別人 ping 您的機器﹐也可以如法泡制。但真的當您需要用 ping 命令來測試網路連線的時候﹐就做不到了﹐有利有弊啦。
關于 TRACEROUTE
除了用 ping 命令來檢查連線之外﹐還有另外一個非常厲害的工具我們可以使用的﹐就是 traceroute 命令了(在 windows 上面則稱為 tracert 命令)﹕

透過 traceroute 命令﹐我們可以找出通往目的地的所有經過的路由節點﹐并以數字將路由順序標識出來。若是您覺得回應很慢,那可加上 -n 參數﹐節點名稱將會以 IP 位址顯示﹐因為不需要進行名稱解析﹐回應速度當然會快一些。
從上面的 traceroute 結果﹐我們可以看到每一個節點都返回 3 個 round-trip 時間作參考。這樣﹐您就能夠判斷整個連線路由中﹐交通瓶頸所在的位置在哪里。您或許奇怪 traceroute 是如何揪出所有路由節點的呢﹖且聽我細說﹕ [
您是否有留意到 ping 命令的結果有一個 TTL 值﹖通常來說﹐Time To Live 都是以時間為單位的﹐但是在路由上面卻是以跳站數目為單位的。為了防止一個封包無限期呆在網路上路由﹐每一個封包都會被賦予一個 TTL 值﹐告訴它最多能經過多少個跳站。當封包被一個路由節點處理之后﹐它原來的 TTL 值就會被扣掉 1 ﹐這樣﹐如果封包的 TTL 降到 0 的時候﹐路由器就會丟棄這個封包﹐并且同時向來源地送出一個 time_exceeded( type 11 ) 的 ICMP 封包﹐以告知其封包的命運。
找到靈感了嗎﹖聰明的 traceroute 程式設計者正是利用了 ICMP 這個特殊功能﹐來找出每一個路由節點的﹕
1. 首先﹐traceroute 命令會向目標位址送出 UDP 偵測封包(在 Linux 中,可用 -I 改為 ICMP 封包)﹐但將第一個送出的封包之 TTL 設為 1 。這樣﹐第一個路由節點在處理這個封包的時候﹐減掉 1 ,并發現 TTL 為 0 ﹐于是就不處理這個封包﹐并同時送回一個 ICMP 封包。這樣﹐發送端就知道第一個路由節點在哪里了。
2. 當接得到第一個 ICMP 返回的時候﹐程式會檢查返回主機是否就是目標主機﹐如果不是﹐則再送出第二個封包﹐但 TTL 比上次增加 1 。
3. 這樣﹐第一路由節點接到的封包之 TTL 就不是 0 ﹐那么處理完畢后送給下一個節點﹐同時將 TTL 扣除 1 。這樣,當下一個站收到這個封包,再扣掉 TTL 為 0 ﹐也會送回 ICMP 封包﹐這樣﹐程式就知道第二個路由節點在哪里了。
4. 然后重復上一個動作﹐直到找到目標主機為止﹐或是封包的最大 TTL (通常為 30) 都用光為止﹐但您可以用 -m 參數來指定最大的 TTL 值。
怎樣﹖聰明吧﹗^_^
但是﹐在實作中﹐未必是所有路由設備都會﹑或愿意送回 ICMP 封包的。碰到這樣的情況﹐您就會看到第 8 個跳站的情形了(以星號顯示)。假如 traceroute 最后的結果一直維持著 * 符號﹐那可能是因為 ICMP 被對方的防火墻攔下來的結果。這樣的話﹐您可能無法完成防火墻后的路由追蹤了。
從上面的例子來觀察﹐由第 6 個跳站開始明顯降慢下來﹐而根據名稱看來﹐應該就是 ISP 連出 backbond 的節點。假如您發現從內部網路到自己的 router 之間的連線都很快﹐過了 router 之后就很慢﹐如果不是專線的線路出現了問題﹐那很可能到了要升級專線的時候了﹐或是這時候剛好碰到有人大量使用頻寬﹔假如速度過了 router 連到對方的機房還很快﹐然后就開始降下來﹐那您要好好審查一下當初和 ISP 簽訂的合約上﹐關于頻寬的保證問題是如何說的﹔但如果您發現連線到國外的網站﹐而速度是從進入對方國家之后才降下來的﹐那就沒什么辦法好想了。
其實 ICMP 協定還有許多實在上面的例子﹐這里不一一介紹了。能靈活運用 ICMP 協定﹐對我們了解和測試網路情況非常有幫助。
ICMP 封包格式
由于 ICMP 的類別翻多,且各自又有各自的代碼,因此,ICMP 并沒有一個統一的封包格式以供全部 ICMP 訊息使用,不同的 ICMP 類別分別有不同的封包欄位。以 echo-request 與 echo-reply 為例,它們的 ICMP 封包內容如下:

因此,只要網路之間能支援 IP ,那就可透過 ICMP 進行錯誤偵測與回報。
ICMP 協定之 RFC 文件
RFC-792﹑RFC-896﹑RFC-950﹑RFC-956﹑RFC-957﹑RFC-1016﹑RFC-1122﹑RFC-1305
習題﹕
1. 請問為何要有 ICMP ?其功能是甚么?
2. 請列舉常見的 ICMP TYPE 有哪些。
3. 請列舉 Distination Unreachable 的 ICMP CODE 有哪些。
4. 請描述 ping 是如何


