当我们从自己的电脑上访问某个网站,又或是两个不同网络的主机之间通信时,网络数据包会在很多路由器节点之间路由。traceroute
是一个网络诊断命令行工具,它能追踪数据包从源主机到目标主机经过的路由路径,显示中间经过的每一跳(HOP)路由器的IP地址及响应时间,这些信息可以用于辅助定位网络不通、路由环路错误、路由器网络拥塞等类型的网络故障。
我们知道IP数据包有一个TTL字段,表示该数据包可以经过的最大路由跳数。IP数据包每经过一跳,TTL值就会递减1,当TTL值减为0时,路由器会丢弃该数据包并返回ICMP Time Exceeded
给发送端。traceroute
工具利用了IP协议中的这一特性,当我们使用traceroute
工具时,它会向目标地址发送一系列TTL值从1开始递增的UDP探测数据包(默认最大探测30跳),每一跳路由器都会逐个返回ICMP超时响应,当收到ICMP Port Unreachable
时表示探测完成,这样我们就可以探测出整个网络链路中的每一跳路由器的相关信息了。
当然,traceroute
的探测并不总是成功的,我们实际使用时,经常能看到探测结果是* * *
,这代表traceroute
没有探测到这一跳路由器的任何信息,造成这种现象的原因有多种,例如路由器配置了防火墙规则,关闭了ICMP响应或是主动丢弃了UDP的探测包等。
此外,traceroute
的探测包并不一定使用UDP协议,traceroute
工作的核心机制是修改IP报文的TTL这一点不会变,至于传输层可能是UDP、ICMP或TCP。那么为什么traceroute
工具默认使用UDP协议呢?这是因为早期网络对UDP限制较少,目标主机通常也没有监听高UDP端口,因此traceroute
会向大于33434的UDP端口发送数据,便于使用ICMP Port Unreachable
作为探测的终止标记。traceroute
工具也支持通过参数配置使用TCP或ICMP协议作为探测包,真实网络环境中我们需要根据实际场景选择合适的探测协议。
以Ubuntu 24.04为例,由于系统没有预装traceroute
,我们可以使用以下命令从软件源中安装。
apt install traceroute
注:对于Windows操作系统,其实也有类似的tracert
工具,它们功能类似,但具体实现细节和命令行参数存在不同。
traceroute
的最简单使用方式如下,我们探测主机和www.gacfox.com (108.61.223.178)
之间的网络路由信息。
traceroute www.gacfox.com
traceroute to www.gacfox.com (108.61.223.178), 30 hops max, 60 byte packets
1 * * *
2 * * *
3 uscala-csla2-e1-ae2.14.it7.net (45.78.0.76) 0.270 ms uscala-csla2-e1-ae1.13.it7.net (45.78.0.74) 0.261 ms uscala-csla2-e1-ae2.14.it7.net (45.78.0.76) 0.223 ms
4 * * *
5 lax-b23-link.ip.twelve99.net (62.115.143.38) 0.903 ms 0.828 ms 0.765 ms
6 tky-b2-link.ip.twelve99.net (62.115.142.129) 106.896 ms tky-b2-link.ip.twelve99.net (62.115.116.199) 99.233 ms 99.198 ms
7 constantcompany-ic-358213.ip.twelve99-cust.net (62.115.41.151) 103.624 ms 111.591 ms 111.554 ms
8 10.71.3.30 (10.71.3.30) 104.033 ms 104.022 ms 111.649 ms
9 10.71.1.242 (10.71.1.242) 117.354 ms 10.71.4.2 (10.71.4.2) 103.010 ms 102.980 ms
10 * * *
11 108.61.223.178.vultrusercontent.com (108.61.223.178) 110.916 ms 103.135 ms 103.077 ms
上面traceroute
工具输出了很多行探测结果,其中每行都是数据包经过的一个路由器节点。对于1、2跳结果是* * *
,这可能是因为UDP探测包被丢弃了或ICMP被关闭了;第3跳显示我们的数据经过了路由器45.78.0.76
,它是我们主机所在本地ISP的路由器;第4跳没有回应;第5跳我们的数据经过62.115.143.38
路由器,twelve99.net
归属电信运营商Telia Carrier,这意味着我们的数据流量从洛杉矶进入Telia的网络;第6跳数据已经来到了东京,可以看到RTT一下增加了100ms左右,这符合美日间的光纤通信时延;第7跳数据已经从Telia网络抵达我们www.gacfox.com
这个网站所在的云服务商Vultr;第8、9跳进入了Vultr的内部网络;第10跳无回应;第11跳数据已经抵达我们的网站主机。
对于每一行,其内容分别是路由器IP 第1次ping延时 第2次ping延时 第3次ping延时
,默认情况下traceroute
工具会对探测到的路由器节点ping
3次。
traceroute
工具默认会进行DNS反查,如果我们不需要DNS反查信息,可以使用-n
选项将其关闭。
traceroute -n www.example.com
最大跳数可以使用-m
参数指定,探测次数使用-q
参数指定。下面命令我们设置最大跳数为20,每次探测发送4个数据包。
traceroute -m 20 -q 4 www.example.com
注意:跳数的默认值是30,探测次数默认值是3。
traceroute
的探测包默认使用UDP协议,我们也可以使用-T
使用TCP协议(SYN),或者指定-I
使用ICMP协议(ICMP ECHO)。如果你的网络对UDP不友好,可以尝试更换探测包的协议来获取更好的效果。这里要注意如果使用TCP协议,要求探测的目标TCP端口是打开的,traceroute
的探测包默认将发往80端口,我们也可以使用-p
参数额外指定端口。
traceroute -T -p 80 www.example.com
另外一点需要注意的是traceroute
使用TCP或ICMP探测包时,由于需要构造原始套接字(Raw Socket),因此需要root权限。