ping:最簡單的主動量測
在上一篇指南裡,你看到了兩種做法之間的分野:一種是觀察既有的流量(被動量測),另一種是注入你自己的探測流量、逼出一個回應(主動量測)。ping 就是最具代表性的主動探測,大概也是你這輩子跑過的第一個網路指令。它的概念簡單得近乎幼稚:送出一個小小的封包,禮貌地問一句「你在嗎?」,然後計時看回覆要多久才回來。那段往返的時間,就是 ping 報給你看的頭條數字。
在引擎蓋底下,ping 根本不用 TCP 也不用 UDP,它搭的是 ICMP,也就是網際網路控制訊息協定——網路層自己那套用來做診斷與回報錯誤的小型訊息系統。ping 送出一個 ICMP「回應請求」(Echo Request),目標若願意,就回送一個 ICMP「回應回覆」(Echo Reply),裡頭帶著同一份內容。沒有連線、沒有交握、沒有序號同步——就只是一個請求加一個回聲而已。由於 ICMP 緊貼在 IP 旁邊、而不是疊在某個傳輸層協定之上,ping 測的是非常底層的「能不能到達」。
ping 一口氣給了你兩項真正有用的量測。第一是往返時間(round-trip time),通常以毫秒為單位:那趟「去了又回」的旅程花了多久。第二是封包遺失:如果你送了 10 個 ping,卻只有 8 個回覆回來,那就是 20% 的遺失——這強烈暗示路徑上有某處正在丟棄封包。讓 ping 跑上一陣子,你還會看到抖動(jitter),也就是那些往返時間在一次次探測之間的變化量,這對語音與視訊極其重要。延遲、遺失、變化——三個數字,全來自一個微不足道的指令。
誠實地解讀往返時間
這裡是初學者第一個會出錯的地方:往返時間是一趟「來回」,不是「單向」的延遲。如果 ping 報出 40 毫秒,那是去程加回程合起來花了 40 毫秒。人們常假設單向延遲剛好是它的一半、也就是 20 毫秒,但那充其量只是個估計——在網際網路上,去程與回程往往走的是不同的路徑、有著不同的延遲,這種特性叫做「路徑不對稱」。ping 看不見這兩半各自的數值,它永遠只看得到總和。
再來,記住那段延遲是由哪些部分組成的。往返時間是好幾個你在基礎那一級就見過的片段之總和:傳播延遲(訊號實際走完那段距離所需的時間,受光速所限)、傳輸延遲(把位元一個個推上線路所需的時間),以及排隊延遲(在繁忙路由器內部的緩衝區裡等待所花的時間)。第一項由地理與物理寫死;最後一項則是網路一忙就會膨脹、就會劇烈擺盪的那一項。所以一個 ping 值在負載下從 40 毫秒跳到 200 毫秒,通常是在對你大喊「排隊延遲」,而不是路變長了。
traceroute:故意去濫用 TTL
ping 告訴你目的地可達、感覺有多遠,卻對中間那條路隻字不提。traceroute 補上了這個缺口:它揭露封包在前往目的地途中所經過的一連串路由器——也就是「跳」(hops)。最精彩的地方在於,traceroute 從來沒被授予任何特殊權限去做這件事,它整個把戲,靠的是刻意去濫用每個 IP 資料包裡一個不起眼的欄位:TTL,也就是存活時間(Time To Live)。
回想一下 TTL 平常是做什麼用的。每個 IP 封包都帶著一個小小的 TTL 計數器,而每一台轉送它的路由器都會把那個計數器減一。一旦 TTL 歸零,路由器就把封包丟棄,並且——這點至關重要——回送一個 ICMP「超過時間」(Time Exceeded)的錯誤給來源端。這原本純粹是設計來當安全閥的,好讓一個卡在路由迴圈裡的封包會死掉、而不是永遠繞圈圈。traceroute 發現這個安全閥可以被改造成一支手電筒:只要你刻意把 TTL 設得很低,就能讓一個封包在你指定的那台路由器上死掉,逼那台路由器親口報出自己的身分。
- 送出一個 TTL 設為 1 的探測。路徑上的第一台路由器把它減為 0、丟棄封包,並寄回一個 ICMP「超過時間」。那個錯誤的來源位址告訴你第 1 跳是誰,而它所花的時間就是你到第 1 跳的往返時間。
- 再送出一個 TTL 設為 2 的探測。這次它撐過了第一台路由器(被減為 1),卻在第二台那裡死掉,由第二台回報。第 2 跳現形。
- 持續把 TTL 加上去——3、4、5……——每次都多探進一跳,一路收集沿途每一台路由器的位址與時間。
- 直到某個探測終於抵達目的地本身、目的地以不同的方式回應(依工具版本而定,可能是「連接埠不可達」或「回應回覆」),就停下來。那整串跳點的清單,就是你追蹤到的路徑。多數工具每個 TTL 會送三個探測,這就是為什麼你會在每一行看到三個時間數字。
為什麼 traceroute 比看起來更脆弱
一份 traceroute 看起來很權威——一張乾淨、編了號的路由器清單——但它其實滿是誠實的但書,而誤讀它正是網路診斷中最常見的錯誤之一。第一個意外是:每一跳的時間常常看起來很怪,某個中間跳點顯示的往返時間,居然比後面某一跳還高。這並不代表路徑折返了。會這樣,是因為「產生一個 ICMP 超過時間」對路由器來說是低優先級的雜務;一台繁忙的核心路由器可能會慢吞吞地才回應自己這個 TTL 到期的探測,即便它正全速轉送你真正的流量。一個回應得慢的跳點,未必就是一個慢的跳點。
第二個但書是路徑的不穩定。現代網路會為了負載平衡,把流量分散到好幾條成本相同的鏈路上,所以 TTL 為 5 的第二個探測,走的路可能跟 TTL 為 5 的第一個探測不一樣。結果就是一份 traceroute 可能在同一跳上顯示出不同的路由器,甚至呈現出一條沒有任何單一封包真正走過的路徑。再加上每一則「超過時間」訊息的回程路徑都可能與去程不同,於是你看到的時間,其實混合了兩個方向,而 traceroute 永遠無法把它們拆開。
第三,沉默不等於故障。許多路由器與防火牆被設定為限制 ICMP 的速率、或乾脆完全不送 ICMP,所以某一跳可能顯示為三個星號——一個逾時——而流量其實正完美地穿過它。初學者一看到星號就慌了,宣告「問題在第 7 跳」,但更常見的情況是,第 7 跳只是一台不愛聊天、安靜的路由器。誠實的解讀是:traceroute 給你看的是一條「貌似如此」的路徑與各跳的粗略延遲,而不是一張保證準確、穩定、雙向的地圖。
它們的用武之地,以及它們止步之處
搭配著用,ping 與 traceroute 構成一套美妙又便宜的「初步勘查」工具組,而且它們天生就是一對。一個常見的工作流程是:先 ping 目的地,注意到有遺失、或往返時間肥大,再跑一個 traceroute,看看路徑大致在哪裡開始變長、或開始丟封包。如果往返時間在前六跳都還很小,到了第七跳卻陡然跳高並且維持高檔,那這個跳躍就是麻煩——也許是一條壅塞的鏈路,或一個瓶頸——真正所在位置的有力候選。
最後一層謙卑。由於這些工具完全倚賴 ICMP,它們給你看的是網路「願意承認」的東西,未必是真相。路由器把 ICMP 降級、防火牆把它過濾、負載平衡器把它打散——所以請把 ping 與 traceroute 當成一張快速而有啟發性的草圖,而不是一份法庭逐字稿。當這張草圖引出真正的疑問時,下一級那些更重的工具——用 Wireshark 之類擷取真正的封包、把「延遲對吞吐量」釘得精準——才是你前去尋求答案的地方。先用便宜的,再刻意地升級。