Linux【7】-连接网络-4-5-路由追踪(traceroute)

通过traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径。当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不一样,但基本上来说大部分时候所走的路由是相同的。linux系统中,我们称之为traceroute,在MS Windows中为tracert。 traceroute通过发送小的数据包到目的设备直到其返回,来测量其需要多长时间。一条路径上的每个设备traceroute默认要测3次。输出结果中包括每次测试的时间(ms)和设备的名称(如有的话)及其IP地址。

一、安装

如果执行过程中没有traceroute 命令,可通过

yum -y install traceroute 

命令安装下(root权限在线安装)

二、用法

在大多数情况下,我们会在linux主机系统下,直接执行命令行:

traceroute hostname

2.1 命令功能

traceroute指令让你追踪网络数据包的路由途径,预设数据包大小是40Bytes,用户可另行设置。

具体参数格式:traceroute [-dFlnrvx][-f<存活数值>][-g<网关>...][-i<网络界面>][-m<存活数值>][-p<通信端口>][-s<来源地址>][-t<服务类型>][-w<超时秒数>][主机名称或IP地址][数据包大小]

2.2 命令参数

  • -d 使用Socket层级的排错功能。
  • -f 设置第一个检测数据包的存活数值TTL的大小。
  • -F 设置勿离断位。
  • -g 设置来源路由网关,最多可设置8个。
  • -i 使用指定的网络界面送出数据包。
  • -I 使用ICMP回应取代UDP资料信息。
  • -m 设置检测数据包的最大存活数值TTL的大小。
  • -n 直接使用IP地址而非主机名称。
  • -p 设置UDP传输协议的通信端口。
  • -r 忽略普通的Routing Table,直接将数据包送到远端主机上。
  • -s 设置本地主机送出数据包的IP地址。
  • -t 设置检测数据包的TOS数值。
  • -v 详细显示指令的执行过程。
  • -w 设置等待远端主机回报的时间。
  • -x 开启或关闭数据包的正确性检验。

2.3 使用实例

实例1:traceroute 用法简单、最常用的用法

tanqianshan[Desktop]$ traceroute www.baidu.com 
traceroute: Warning: www.baidu.com has multiple addresses; using 39.156.66.18
traceroute to www.a.shifen.com (39.156.66.18), 64 hops max, 52 byte packets
 1  192.168.1.1 (192.168.1.1)  2.013 ms  1.121 ms  0.979 ms
 2  * * *
 3   (117.135.50.237)  4.737 ms
     (117.135.50.125)  5.064 ms  3.780 ms
 4  221.183.53.229 (221.183.53.229)  4.082 ms  3.612 ms  11.210 ms
 5  221.183.37.217 (221.183.37.217)  25.710 ms
    221.183.37.133 (221.183.37.133)  29.590 ms  28.871 ms
 6  221.183.49.126 (221.183.49.126)  28.228 ms
    221.183.49.142 (221.183.49.142)  27.165 ms *
 7  * 111.13.0.174 (111.13.0.174)  32.163 ms
    39.156.27.5 (39.156.27.5)  31.116 ms
 8  39.156.67.17 (39.156.67.17)  30.007 ms

说明:

  1. 记录按序列号从1开始,每个纪录就是一跳 ,每跳表示一个网关,我们看到每行有三个时间,单位是 ms,其实就是-q的默认参数。探测数据包向每个网关发送三个数据包后,网关响应后返回的时间;如果您用 traceroute -q 4 www.58.com ,表示向每个网关发送4个数据包。

  2. 有时我们traceroute 一台主机时,会看到有一些行是以星号表示的。出现这样的情况,可能是防火墙封掉了ICMP的返回信息,所以我们得不到什么相关的数据包返回数据。

  3. 有时我们在某一网关处延时比较长,有可能是某台网关比较阻塞,也可能是物理设备本身的原因。当然如果某台DNS出现问题时,不能解析主机名、域名时,也会 有延时长的现象;您可以加-n 参数来避免DNS解析,以IP格式输出数据。

  4. 如果在局域网中的不同网段之间,我们可以通过traceroute 来排查问题所在,是主机的问题还是网关的问题。如果我们通过远程来访问某台服务器遇到问题时,我们用到traceroute 追踪数据包所经过的网关,提交IDC服务商,也有助于解决问题;但目前看来在国内解决这样的问题是比较困难的,就是我们发现问题所在,IDC服务商也不可能帮助我们解决。

实例2:跳数设置

tanqianshan[Desktop]$ traceroute -m 3 www.baidu.com
traceroute: Warning: www.baidu.com has multiple addresses; using 39.156.66.14
traceroute to www.a.shifen.com (39.156.66.14), 3 hops max, 52 byte packets
 1  192.168.1.1 (192.168.1.1)  2.329 ms  1.149 ms  1.050 ms
 2  * * *
 3   (117.135.50.125)  5.315 ms  6.290 ms  19.317 ms

实例3:显示IP地址,不查主机名

tanqianshan[Desktop]$ traceroute -n www.baidu.com
traceroute: Warning: www.baidu.com has multiple addresses; using 39.156.66.18
traceroute to www.a.shifen.com (39.156.66.18), 64 hops max, 52 byte packets
 1  192.168.1.1  5.045 ms  2.304 ms  1.624 ms
 2  117.185.9.20  2.424 ms  2.965 ms  2.890 ms
 3  117.135.50.237  5.071 ms  3.913 ms
    117.135.50.125  3.774 ms
 4  221.183.53.225  10.270 ms  5.471 ms
    221.183.53.229  3.389 ms
  ...

实例4:探测包使用的基本UDP端口设置6888

tanqianshan[Desktop]$ traceroute -p 6888 www.baidu.com
traceroute: Warning: www.baidu.com has multiple addresses; using 39.156.66.18
traceroute to www.a.shifen.com (39.156.66.18), 64 hops max, 52 byte packets
 1  192.168.1.1 (192.168.1.1)  2.423 ms  1.249 ms  1.226 ms
 2   (117.185.9.20)  3.452 ms  3.388 ms  2.726 ms
 3   (117.135.50.125)  4.600 ms  4.672 ms
     (117.135.50.237)  5.313 ms
 4  221.183.53.229 (221.183.53.229)  11.403 ms  6.586 ms
    221.183.53.225 (221.183.53.225)  4.423 ms
 5  221.183.37.217 (221.183.37.217)  30.951 ms
 ...

实例5:把探测包的个数设置为值4

tanqianshan[Desktop]$ traceroute -q 4 www.baidu.com
traceroute: Warning: www.baidu.com has multiple addresses; using 39.156.66.18
traceroute to www.a.shifen.com (39.156.66.18), 64 hops max, 52 byte packets
 1  192.168.1.1 (192.168.1.1)  3.716 ms  2.304 ms  1.443 ms  1.466 ms
 2   (117.185.9.20)  2.878 ms  3.223 ms  3.145 ms  4.256 ms
 3   (117.135.50.125)  7.472 ms
     (117.135.50.237)  5.997 ms  6.712 ms  3.819 ms
 4  221.183.53.225 (221.183.53.225)  4.963 ms
 ...

实例6:绕过正常的路由表,直接发送到网络相连的主机

tanqianshan[Desktop]$ traceroute -r www.baidu.com
traceroute: Warning: www.baidu.com has multiple addresses; using 39.156.66.18
traceroute to www.a.shifen.com (39.156.66.18), 64 hops max, 52 byte packets
traceroute: sendto: Network is unreachable
 1 traceroute: wrote www.a.shifen.com 52 chars, ret=-1
 *traceroute: sendto: Network is unreachable
traceroute: wrote www.a.shifen.com 52 chars, ret=-1
 *traceroute: sendto: Network is unreachable
traceroute: wrote www.a.shifen.com 52 chars, ret=-1

报的是网络不可达。

实例6:把对外发探测包的等待响应时间设置为3秒

tanqianshan[Desktop]$ traceroute -w 3 www.baidu.com
traceroute: Warning: www.baidu.com has multiple addresses; using 39.156.66.18
traceroute to www.a.shifen.com (39.156.66.18), 64 hops max, 52 byte packets
 1  192.168.1.1 (192.168.1.1)  1.708 ms  1.390 ms  1.406 ms
 2  * * *
 3   (117.135.50.125)  4.091 ms  6.139 ms
     (117.135.50.237)  4.992 ms

三、原理

现实世界中的网络是由无数的计算机和路由器组成的一张的大网,应用的数据包在发送到服务器之前都要经过层层的路由转发。而Traceroute是一种常规的网络分析工具,用来定位到目标主机之间的所有路由器

3.1 几个基本概念

  • IP协议:IP协议是TCP/IP协议族中最核心的部分,它的作用是在两台主机之间传输数据,所有上层协议的数据(HTTP、TCP、UDP等)都会被封装在一个个的IP数据包中被发送到网络上。

  • ICMP:ICMP全称为互联网控制报文协议,它常用于传递错误信息,ICMP协议是IP层的一部分,它的报文也是通过IP数据包来传输的。

  • TTL:TTL(time-to-live)是IP数据包中的一个字段,它指定了数据包最多能经过几次路由器。从我们源主机发出去的数据包在到达目的主机的路上要经过许多个路由器的转发,在发送数据包的时候源主机会设置一个TTL的值,每经过一个路由器TTL就会被减去一,当TTL为0的时候该数据包会被直接丢弃(不再继续转发),并发送一个超时ICMP报文给源主机。

具体到traceroute的实现细节上,有两种不同的方案:

3.2 基于UDP实现

在基于UDP的实现中,客户端发送的数据包是通过UDP协议来传输的,使用了一个大于30000的端口号,服务器在收到这个数据包的时候会返回一个端口不可达的ICMP错误信息,客户端通过判断收到的错误信息是TTL超时还是端口不可达来判断数据包是否到达目标主机,具体的流程如图:

  1. 客户端发送一个TTL为1,端口号大于30000的UDP数据包,到达第一站路由器之后TTL被减去1,返回了一个超时的ICMP数据包,客户端得到第一跳路由器的地址。
  2. 客户端发送一个TTL为2的数据包,在第二跳的路由器节点处超时,得到第二跳路由器的地址。
  3. 客户端发送一个TTL为3的数据包,数据包成功到达目标主机,返回一个端口不可达错误,traceroute结束。

Linux和macOS系统自带了一个traceroute指令,可以结合Wireshark抓包来看看它的实现原理。首先对百度的域名进行traceroute:traceroute www.baidu.com,每一跳默认发送三个数据包,我们会看到下面这样的输出:

对该域名的IP:115.239.210.27进行traceroute,此时Wireshark抓包的结果如下:

注意看红框处的内容,跟第一张图对比,可以看到traceroute程序首先通过UDP协议向目标地址115.239.210.27发送了一个TTL为1的数据包,然后在第一个路由器中TTL超时,返回一个错误类型为Time-to-live exceeded的ICMP数据包,此时我们通过该数据包的源地址可知第一站路由器的地址为10.242.0.1。之后只需要不停增加TTL的值就能得到每一跳的地址了。

然而一直跑下去会发现,traceroute并不能到达目的地,当TTL增加到一定大小之后就一直拿不到返回的数据包了:

其实这个时候数据包已经到达目标服务器了,但是因为安全问题大部分的应用服务器都不提供UDP服务(或者被防火墙挡掉),所以我们拿不到服务器的任何返回,程序就理所当然的认为还没有结束,一直尝试增加数据包的TTL。

目前在网上找到许多开源iOS traceroute实现大多都是基于UDP的方案,实际用起来并不能达到想要的效果,所以我们需要采用另一种方案来实现。

3.3 基于ICMP实现

上述方案失败的原因是由于服务器对于UDP数据包的处理,所以在这一种实现中我们不使用UDP协议,而是直接发送一个ICMP回显请求(echo request)数据包,服务器在收到回显请求的时候会向客户端发送一个ICMP回显应答(echo reply)数据包,在这之后的流程还是跟第一种方案一样。这样就避免了我们的traceroute数据包被服务器的防火墙策略墙掉。

采用这种方案的实现流程如下:

  1. 客户端发送一个TTL为1的ICMP请求回显数据包,在第一跳的时候超时并返回一个ICMP超时数据包,得到第一跳的地址。
  2. 客户端发送一个TTL为2的ICMP请求回显数据包,得到第二跳的地址。
  3. 客户端发送一个TTL为3的ICMP请求回显数据包,到达目标主机,目标主机返回一个ICMP回显应答,traceroute结束。

可以看出与第一种实现相比,区别主要在发送的数据包类型以及对于结束的判断上,大体的流程还是一致的。

值得一提的是在Windows系统中也有traceroute程序,它的名字叫做tracert,tracert就是用采用这种方法来实现的,感兴趣的话可以自行尝试一下,这里就不再演示了。

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn