內容簡介

traceroute是診斷網路問題時常用的工具。它可以定位從源主機到目標主機之間經過了哪些路由器,以及到達各個路由器的耗時。

本文首先介紹traceroute的基礎用法,然後深入淺出地介紹traceroute的實現原理。

traceoute用途

我們知道,兩台主機之間的通信,往往需要經過很多中間節點(如下圖所示)。

載入超時,點擊重試

當源主機A向目標主機B發送消息,發現消息無法送達。此時,可能是某個中間節點發生了問題,比如路由器02因負載過高產生了丟包。

此時,可以通過traceroute進行初步的檢測,定位網路包在是在哪個節點丟失的,之後才可以進行針對性的處理。

入門例子

假設想要知道,當我們訪問 iqiyi.com 時,經過了多少中間節點,那麼可以採用如下命令:

traceroute www.iqiyi.com

以下是輸出結果(osx下,為節省篇幅,省略部分輸出結果),後面會對輸出結果進行講解。

traceroute: Warning: www.iqiyi.com has multiple addresses; using 121.9.221.96
traceroute to static.dns.iqiyi.com (121.9.221.96), 64 hops max, 52 byte packets
1 xiaoqiang (192.168.31.1) 1.733 ms 1.156 ms 1.083 ms
2 192.168.1.1 (192.168.1.1) 2.456 ms 1.681 ms 1.429 ms
# ... 忽略部分輸出結果
9 121.9.221.96 (121.9.221.96) 6.607 ms 9.049 ms 6.706 ms

首先,域名 iqiyi.com 對應多個IP地址,這裡採用了其中一個IP地址 121.9.221.96,對應的主機名是 static.dns.iqiyi.com

從當前主機,到目標主機,最多經過64跳(64 hops max),每次檢測發送的包大小為52位元組(52 byte packets)

traceroute: Warning: www.iqiyi.com has multiple addresses; using 121.9.221.96
traceroute to static.dns.iqiyi.com (121.9.221.96), 64 hops max, 52 byte packets

接下來的輸出比較有規律。每一行包含三部分:序號 + 主機 + 耗時。

行首是序號,表示這是經過的第N個中間節點。序號後面是節點的主機名+IP地址。最後是到達節點所耗費的時間。

1 xiaoqiang (192.168.31.1) 1.733 ms 1.156 ms 1.083 ms
2 192.168.1.1 (192.168.1.1) 2.456 ms 1.681 ms 1.429 ms

注意,每次檢測都同時發送3個數據包,因此列印出來三個時間。此外,如果某一個數據報超時沒有返回,則時間顯示為 *,此時需要特別注意,因為有可能出問題了。

以第1跳為例(家裡的路由器),主機名是 xiaoqiang,IP地址是 192.168.31.1,檢測數據包到達路由器的時間分別是 1.733 ms 1.156 ms 1.083 ms。

1 xiaoqiang (192.168.31.1) 1.733 ms 1.156 ms 1.083 ms

第2、3 ... N 跳類似,最後一跳為目標主機。

9 121.9.221.96 (121.9.221.96) 6.607 ms 9.049 ms 6.706 ms

實現原理簡析

主機之間通信,網路層IP數據報的首部中,有個TTL欄位(Time To Live)。TTL的作用是,設置IP數據報被丟棄前,最多能夠經過的節點數。

此外,每經過一個中間節點,再向下一個節點轉發數據前,都會將TTL減1。如果TTL不為0,則將數據報轉發到下一個節點;否則,丟棄數據報,並返回錯誤。

假設TTL設置為N,當前轉發到第M個節點:

  • 第1個節點:將TTL設置為N-1。如果TTL != 0,則將數據報傳遞給第2個節點;否則丟棄數據報,並向源主機報錯。
  • 第2個節點:將TTL設置為N-2。如果TTL != 0,則將數據報傳遞給第3個節點;否則丟棄數據報,並向源主機報錯。
  • 。。。
  • 第M個節點:將TTL設置為N-M。如果TTL != 0,則將數據報傳遞給第3個節點;否則丟棄數據報,並向源主機報錯。
  • 。。。

如果源主機收到出錯的回報,則知道數據報已經到達第M個節點。此時,記錄下第M個節點的IP,以及數據報往返的耗時。

到這裡,可以引出traceroute的實現原理(非嚴謹):

從源主機向目標主機發送IP數據報,並按順序將TTL設置為從1開始遞增的數字(假設為N),導致第N個節點(中間節點 or 目標主機)丟棄數據報並返回出錯信息。源主機根據接收到的錯誤信息,確定到達目標主機路徑上的所有節點的IP,以及對應的耗時。

來個簡單的圖例。假設源主機A到目標主機B之間有2個中間節點,也就是說,A到B一共需要經過3跳。那麼,traceroute的檢測時序如下:

實現原理深入剖析

前面簡單闡述了traceroute的實現原理,下面進一步介紹實現細節。這裡主要回答3個問題:

  1. 問題一:傳輸層採用的是UDP,還是TCP?
  2. 問題二:當TTL為0時,接收節點會丟棄接數據報,並向源主機報錯。這裡的報錯信息是什麼?
  3. 問題三:假設到達目標主機一共有N跳,且TTL剛好設置為N,那麼,目標主機成功收到數據報,此時並沒有錯誤回報,traceroute如何確定已經到達目標主機?

問題一:UDP還是TCP

答案是UDP。為什麼呢?讀者同學可以想一下。

問題二:報錯信息是什麼

這裡的報錯信息是ICMP(Internet Control Message Protocol)報文,它用於在主機、路由之間傳遞控制信息。

上面的定義有點難理解。簡答的來講,就是兩台主機之間約定的暗號,用來告訴對方一些事情,比如「您訪問的主機不存在」之類的。

如下所示,ICMP數據報是封裝在IP數據報中進行傳遞的。(此時,IP數據報首部的協議欄位設置為1,表示當前傳遞的是ICMP報文。)

ICMP報文通用格式如下,主要關注Type、Code兩個欄位。

  • Type欄位:ICMP報文類型。比如超時錯誤(Time Exceeded Message)、目標主機不可達錯誤(Destination Unreachable Message)等。
  • Code欄位:子類型。比如,導致目標主機不可達錯誤的原因可能有多種,比如主機錯誤(code=1),埠錯誤(code=3)等。

IP數據報未到達目標主機,且TTL被置為0時,返回的就是超時錯誤(Time Exceeded Message),此時Type=11,code=0。

traceroute收到ICMP報文,發現Type=11,code=0,記錄下發送節點的IP和耗時。

問題三:報文是否到達目標主機

文章開頭的圖,假設TTL設置為大於3的數,此時IP數據報安全抵達目標主機B,並沒有發生超時錯誤。這種情況下,traceroute如何知道已經到達了目標主機?

先來回顧下UPD用戶數據報的首部(非完整),它包含了源埠、目標埠。

traceroute發送UDP報文時,將目標埠設置為較大的值( 33434 - 33464),避免目標主機B上該埠有在實際使用。

當報文到達目標主機B,目標主機B發現目標埠不存在,則向源主機A發送ICMP報文(Type=3,Code=3),表示目標埠不可達。

源主機A收到差錯報文,發現Type=3,Code=3,知道已經到達目標主機B。記錄下IP、耗費,檢測結束。

寫在後面

traceroute是比較實用的網路工具,排查錯誤時經常用到,掌握它的用法、實現原理很有必要。

建議讀者朋友實際動手嘗試下,同時採用wireshark抓下包分析下,加深對實現原理的理解。

為便於講解,部分內容可能不夠嚴謹,如有錯誤敬請指出。

參考鏈接

RFC792

tools.ietf.org/html/rfc

What UDP ports to open for UDP traceroute?

learningnetwork.cisco.com

推薦閱讀:

查看原文 >>
相关文章