Tracert与Traceroute

时间:2024-01-30 08:08:56

Tracert与Traceroute

traceroute是一个检查网络路径的工具,最初由Van Jacobson实现。它现在已经成为Linux、Cisco IOS以及其他很多操作系统的基本网络工具之一,Windows下也有一个类似的工具tracert。下图是Linux执行traceroute的结果, 它能显示每一跳的IP地址及域名(如果反向查询成功),以及对应的往返时间。

traceroute3

traceroute与tracert的原理是很类似的,它们通过设置IP报文里的TTL字段,TTL在每个路由器里都会减1,因此到了指定的跳数 之后,TTL刚好减到0。如果这时候还没到达目的地,那么路由器会返回一个类型11的ICMP报文,表示time exceeded(TTL为0)。从而,原主机根据这个ICMP报文就能知道每一跳的IP地址。

但是,其实traceroute具体的实现方法与tracert是不同的,我昨晚在Packet Tracer做了下面的实现。首先看看实验的拓扑图,我做了两次实验,第一次从laptop2a使用tracert,目的地是dhcp(IP地址是 8.8.8.2);第二次从core2使用traceroute,目的地同样是dhcp。我的目的是观察到tracert与traceroute的不同。

sample-topology

tracert1

从上图可以看到,tracert使用的ICMP类型8报文,即ICMP Echo Request,与ping程序一样。可以看到,第一次TTL设为了1,可以预见这个报文将会在core2丢弃,并返回ICMP Time Exceeded报文。下图是返回的报文,可以见到ICMP报文里还会附上原来报文的内容。根据《TCP/IP详解》的说明,ICMP的差错报文需要附上 原来报文的IP报头,以及后面紧跟着的8个字节,不过现在的实现一般都把更多的字节附上。

tracert2

为什么必须多8个字节呢?因为这样做可以把ICMP Echo Request报文里的标识符字段和序列号字段包含进来,那么如果原来客户端同时开了两个tracert程序,客户端可以根据标识符字段区分交给哪个进程 处理。实际上,TCP/IP协议栈就是故意这样设计的,IP报头后面的ICMP报头,或者UDP报头,或者TCP报头,它们的前8个字节就已经包含了端口 号、序列号等所有能区分进程的信息,从而ICMP差错报文会把这些信息附上。

对于tracert来说,如果TTL大到可以到达目的地,那么目的地会返回一个ICMP Echo Reply(ICMP报文类型0),就像ping一样。这时,tracert就可以结束了。

traceroute则不一样,它不是使用ICMP Echo Request报文,从下图可以看出,它是使用UDP报文。UDP的源端口用于标识主机上不同的traceroute程序,原理刚才已经分析过了。目的端 口从33434开始,每一个报文会把目的端口增加1,直到33534,目的是为了区分返回的报文对应哪个发出的报文。

traceroute1

traceroute2

如果TTL不足以去到目的地,就和tracert的情况一样,路由器返回一个ICMP Time Exceeded报文。那么如果到达目的地会发生什么事呢?上图里有了答案,目的地返回一个类型3,代码也是3的ICMP报文,表示端口不可达。所以,我 们还可以知道多一个常识,即主机的33434到33534端口一般不能作为服务用途的,因为traceroute希望目的地返回端口不可达。 traceroute收到这个报文之后,就知道已经到达目的地,可以结束程序了。

总结一下,tracert是使用ICMP Echo Request报文去实现,traceroute是使用UDP报文去实现,不过基本原理都是利用IP报文的TTL字段。现在的互联网复杂很多,有些路由器 屏蔽了其中一种检查路径的方式(甚至两种都屏蔽),所以同时使用tracert和traceroute,再把结果合并,有时会更好。因 此,traceroute实际上更有优势,因为现代版的traceroute只要加-I选项就相当于tracert的功能。据说现在还有一种使用-P选项 的方式使用TCP报文的,但是我还没试过。