自己动手学TCP/IP--traceroute程序

traceroute程序主要是能列出到达目标主机所经过的路由。

traceroute最简单的基本用法是:traceroute hostname。

traceroute程序的设计是利用ICMP及IP header的TTL(Time To Live)栏位(field)。首先,traceroute送出一

个TTL是1的IP datagram到目的地,当路径上的第一个路由器(router)收到这个datagram时,它将TTL减1。

此时,TTL变为0了,所以该路由器会将此datagram丢掉,并送回一个ICMP time exceeded消息(包括发IP包

的源地址,IP包的所有内容及路由器的IP地址),traceroute 收到这个消息后,便知道这个路由器存在于这个

路径上,接着traceroute 再送出另一个TTL是2 的datagram,发现第2 个路由器...... traceroute 每次将送出的

datagram的TTL 加1来发现另一个路由器,这个重复的动作一直持续到某个

datagram 抵达目的地。当datagram到达目的地后,该主机并不会送回ICMP time exceeded消息,因为它已

是目的地了,那么traceroute如何得知目的地到达了呢?

traceroute在送出UDP datagrams到目的地时,它所选择送达的port number 是一个一般应用程序都不会用的

号码(30000 以上),所以当此UDP datagram到达目的地后该主机会送回一个ICMP port unreachable的消

息,而当traceroute 收到这个消息时,便知道目的地已经到达了。所以traceroute在Server端也是没有所谓

Daemon程式。

下面是traceroute发出的报文格式,一般情况下traceroute一次是发出去3个报文。

再来看看traceroute程序收到的ICMP超时报文。

数据包(70个字节)=以太网头(14个字节)+IP头(20个字节)+ICMP头(8个字节)+原IP头(20个字节)

+原数据报前8个字节

也就是说对于ICMP超时报文类型是11,是把原来traceroute程序发出去包的IP头+数据包前8个字节,都封装到

ICMP报文的数据字段里返回来了。为什么要采用这样的机制呢?这样做的好处就是可以在一个主机上支持多

个traceroute程序,试想一下一个traceroute程序发出去的数据包中源端口就和该进程绑定在了一起,对于接

收回的ICMP超时报文中数据段的内容包含了发送端的端口,这样就可以在客户端区分出原来的traceroute进

程。那么为什么要把IP字段也返回给客户端呢?原因是IP字段中有协议标识这个字段(1个字节),通过协议

标识字段就可以告诉客户端这个ICMP超时报文是TCP的还是UDP的,告诉客户端要用什么结构体去解包。

那么对于到达目的端而返回的目标端口不可达报文格式呢?

ICMP目标端口不可达报文和ICMP超时报文差不多,不过在ICMP头字段类型是3,代表不可达,代码是3代表

是目标端口不可达。ICMP报文数据段还是发回给客户端原IP头+数据段的前8个字节。

详细的源码可以查看 http://www.opensource.apple.com/source/network_cmds/network_cmds-307/traceroute.tproj/traceroute.c

标签:Linux, TCP/IP

评论已关闭