■湖北枝江市職業教育中心 楊華 杜國金
根據平時的工作實踐挖掘以下幾種工具的路由探測功能。
Traceroute 是Linux 和Mac OS 等系統默認提供的路由追蹤小程序,Tracert 是Windows系統默認提供的路由追蹤小程序。二者的功能相同,都能探測數據包從源地址到目的地址經過的路由器的IP 地址。Traceroute/Tracert 的實現都借助了TTL:通過向目的地址發送一系列的探測包,設置探測包的TTL 初始值分別為1,2,3…,根據返回的超時通知(ICMP Time Exceeded Message)得到源地址與目的地址之間的每一跳路由信息。雖然兩者輸出結果一致,但在實現原理上還有著顯著的差別。

圖1 端口不可達路由跟蹤
Traceroute 借助UDP 協議,Tracert 借助ICMP 協議。
Traceroute 使用UDP 包進行探測,目標端口號默認為33434,每次探測目標端口號加1。Traceroute 故意使用了一個大于 30000(因UDP 協議規定端口號必須小于30000,所以目標主機收到數據包后唯一能做的事就是返回一個“端口不可達”的ICMP 報文)的目標端口號,以保證目標地址收到數據包后能夠返回一個“端口不可達”的ICMP 報文,于是源地址就可將端口不可達報文當作跟蹤結束的標志,這是巧妙運用了UDP協議的本身特征達到探測路由的目的(如圖1 所示)。
但有時Traceroute 并不能到達目的地,當TTL 增加到一定大小之后就一直拿不到返回的數據包了,主要是因為安全問題,在運營商的路由器上,對UDP 與ICMP 的數據包處理非常謹慎,兩者待遇大不一樣。
為了利于故障排除,ICMP ECHO Request/Reply 是不會封的,而UDP 則不同。UDP 常被用來做網絡攻擊,因為UDP 無需連接,因而沒有任何狀態約束它,比較方便攻擊者偽造源IP、偽造目的端口發送任意多的UDP 包。
所以運營商為安全考慮,對于UDP 端口常常采用白名單ACL,就是只有ACL 允許的端口才可以通過,沒有明確允許的則統統丟棄,比如允許DNS/DHCP/SNMP 等。
其實這個時候數據包已經到達目標服務器了,但是因為安全問題大部分的應用服務器都不提供UDP 服務(或者被防火墻擋掉),所以我們拿不到服務器的任何返回,程序就理所當然的認為還沒有結束,一直嘗試增加數據包的TTL。
目前許多開源iOS Traceroute 實現大多都是基于UDP 的方案,實際用起來并不能達到想要的效果,所以我們需要采用另一種方案來實現。

圖2 Traceroute 和Tracert 兩者對比

圖3 ICMP 協議數據包路由選項
Tracert 使用ICMP 請求回顯(ICMP Echo Request)數據包進行探測,每跳默認發送3 個探測包,在未能到達路由器或未返回ICMP 超時通知的情況下,相應的延時位置會以“*”顯示。每個探測包都有唯一的標識號,ICMP 數據包使用Seq 進行標識。源地址以目的地址返回的ICMP 回應答復(ICMP Echo Reply)作為跟蹤結束標志,這比Traceroute 采用“端口不可達”作為結束標志可靠多了。兩者對比如圖2所示。
除了以上專業的路由跟蹤工具,在其它的網絡命令中也有此功能的體現,如Ping 和Pathing 命令。
命令格式:Ping-r count Record route for count hops.
在“記錄路由”字段中記錄傳出和返回數據包的路由。盡管Ping 工具也可以進行偵測,但是因為IP 頭的限制,Ping 不能完全的記錄下所經過的路由器,因為“記錄路由”字段最大值是40 字節,而每個IP 要占有4 個字節,另外加三個點分符,每個IP 占用bit 位4*83=35;40*8/35=9(取整),所有最多只記錄9 條路由記錄。


看一下發出的請求包:在發出的ICMP 包中的IP 頭中使用了0x07 的源地址路由選項(如圖3 所示),說明ICMP 的路由是根據返回包的記錄的源地址選項來實現路由記錄的,從返回的包中的路由記錄中可以看出和顯示的路由信息完全一致。
但是我們知道,通過源路由選項我們得出的結果是從222.42.254.182 返回我們主機的包,其記錄的路由實際上是Router3 到PC0 的路由,而不是PC0 到Router3 的路由,這就有差別了。


圖4 網絡拓撲-接口
Tracert 則是通過遞增TTL 來實現的路由檢測,那么他是一個標準的由我們的主機到Router3 的路由。
一個回路,一個去路,我們想像一下,如果可以結合這兩個命令繪制完整的網絡路由接口圖,如圖4 所示,我們只知道目標Router3 的IP,確可以得到完整的網絡路由接口圖,這對于網絡故障的排查是大有幫助的。
遺憾的是,由于本身ICMP 協議包大小的限制,有時略顯不足。
(1)由于ICMP 協議包最多只能保留9 條路由記錄,所以超過9 條就無能無力了。
(2)由于一個是回路,一個是去路,因此可能選擇的路由路徑是不一致的,即使是一致的,也會產生不同的結果。為什么呢?因為路由都是多接口的,從一個接口收到包以后,轉發到另一個接口上,由于Ping 方式獲取的是包返回的路由,所以記錄的都是這個路由的返回時候收到包的接口,而TTL 遞增方式則是記錄的發送包的時候收到的路由接口地址。
(3)對于Ping,發送的是一個echo request 包,ICMP type=8,code=0,當被Ping 者接到相關ICMP 包的時候,返回ICMP type=0,code=0 的響應包。
而對于 Tracert,包發出去后,途經的每個站點都會返回一個 ICMP type=11,code=0(表示傳輸中TTL=0)的包回去,只有到了終點,才會返回一個 ICMP type=3,code=3。
因此,Ping 和Tracert雖然原理上都是利用ICMP包,但使用的ICMP 類型不一樣,所以可能會出現Ping通,但Tracert 不通的情況,反之亦然。
【小技巧】如果到達目網絡的路由設備不超過4 個,可以直接通過Ping-r-9 來進行跟蹤,因為去的數據包一去一回剛好把來去的路由接口記錄下來,這樣整個詳細的網絡拓撲就出來了,如下面命令所示:

正在Ping 222.42.254.182 具有32 字節的數據:


圖5 運行結果
PathPing 命令是一個路由跟蹤分析工具,它將Ping和Tracert 命令的功能與這兩個工具所不提供的其他信息結合起來,綜合了二者的功能。PathPing 會先顯示中間的通過的路由器(類似Tracert 命令得到的信息),然后分別對每個中間路由器(節點)發送一定數量的Ping包,通過統計它們對Ping 包響應的數據包來分析通信質量。

正在計算統計信息,已耗時 100 秒...
指向此處的源此節點/鏈接
如圖5 所示命令,運行結果反映出數據包從源主機到目標主機所經過的路徑、網絡延時以及丟包率,顯示在任何特定路由器或鏈接處的數據包的丟失程度,可據此確定存在網絡問題的路由器或子網,幫助我們解決網絡問題。
(1)這種方式可能要花費一定的時間成本,它每次給中間節點發送的Ping 包可能數量很大(根據筆者抓包顯示達到了上千個),如果中間節點又很多,那結果可想而知,所以要有足夠的耐心等待了。
(2)如果路由器對Ping關閉了響應,那么該節點的丟包率會達到100%,所以這種一般就是關閉了Ping 回復。
(3)對Ping 包丟棄程度只是節點本身對Ping 的處理,并不一定影響他的通信,你可以看到,關閉Ping 回復命令節點的下一個節點返回到數據是正常的,說明回復的包都成功發送回來。