分类: LINUX
2013-09-05 15:47:05
原文地址:traceroute与tracert 作者:遇见0425
Tracert与Traceroute
traceroute是一个检查网络路径的工具,最初由Van Jacobson实现。它现在已经成为Linux、Cisco
IOS以及其他很多操作系统的基本网络工具之一,Windows下也有一个类似的工具tracert。下图是Linux执行traceroute的结果,
它能显示每一跳的IP地址及域名(如果反向查询成功),以及对应的往返时间。 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的不同。 从上图可以看到,tracert使用的ICMP类型8报文,即ICMP Echo
Request,与ping程序一样。可以看到,第一次TTL设为了1,可以预见这个报文将会在core2丢弃,并返回ICMP Time
Exceeded报文。下图是返回的报文,可以见到ICMP报文里还会附上原来报文的内容。根据《TCP/IP详解》的说明,ICMP的差错报文需要附上
原来报文的IP报头,以及后面紧跟着的8个字节,不过现在的实现一般都把更多的字节附上。 为什么必须多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,目的是为了区分返回的报文对应哪个发出的报文。 如果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报文.