首页 > 技术文章 > mtr和traceroute的区别,以及为什么traceroute不显示路径mtr却可以显示路径

zhangpeiyao 2021-10-21 15:40 原文

最近工作主要都是网络策略的开通和网络测试,在测试的过程当中发现当网络不通时,用traceroute来看路由路径的时候总是无法显示出来,于是就换了个工具-mtr,发现mtr可以正常显示出路由路径,帮助我解决了网络测试当中遇到的很多问题,十分的方便,于是想要记录一下,写一篇有关traceroute和mtr两个网络测试工具的区别和原理,达到融会贯通的效果。
首先先放两张我在测试过程当中两个工具的测试结果,可以看出两者的结果存在的区别,很明显mtr要比traceroute详细并且好用很多,于是我就上网开始查阅资料,想弄清两者的区别到底是什么。


下面通过网上查阅到的资料,来解释下有关两者的区别,以及一些原理:
如果你traceroute或者mtr两个工具都用过,肯定会比较偏向于使用mtr,因为总感觉traceroute不太好用,经常会出现***的情况。比如我们用IP: 61.135.185.32来做个测试,

使用traceroute得到的结果是:


但是如果用mtr:

通过mtr,我们可以很明确的看到从源到目的IP一共有12跳。但是traceroute却是一堆的******************

在继续下面的内容之前,要先讲一下traceroute和mtr等这种网络探测工具的实现方法:

它们通过发送具有较小ttl的探测数据包,然后侦听来自网关的ICMP“TTL=0”的答复,来跟踪IP数据包到达Internet上的路由。我们从ttl为1开始探测,然后增加1,直到得到ICMP“端口不可达”(或TCP重置或icmp应答或无响应等)。大致过程如下图:


主机1.1.1.10最后收到了1.1.1.1、2.2.2.2、2.2.2.10的icmp响应包,也就相当于知道了发送数据包经过的路由。

知道了实现原理,现在我们来探究它们之间的区别,目前最容易想到的办法:抓个包。

于是traceroute的数据包如下:(traceroute -n 61.135.185.32)

从数据包中可以看到:

traceroute默认请求使用UDP协议,而响应是ICMP协议。
traceroute发包方式是每次同一个TTL数据包连着发三次,并逐步增加TTL。而且请求端口和目的端口一直在变化。
再看一下mtr的数据包:(mtr -n -c 3 61.135.185.32)

从数据包中可以看到:

mtr默认请求和响应都是ICMP协议。
mtr发包方式是先每次发送一个逐步增加TTL的数据包,再循环3次。
这样对比下来之后,他们之间的区别显而易见。

但是你可能还会有下面几个疑问:

为什么上图traceroute第10跳之后,一直都是*?
为什么发送UDP请求包,会响应ICMP包?
为什么目的是同一个IP,traceroute和mtr返回的路径会不一样?

问1:为什么上图traceroute第10跳之后,一直都是*?
从上面的抓包可以看出来,traceroute和mtr的发包方式是不一样的,traceroute是udp包,mtr是icmp包。于是我们测试用traceroute发送icmp包。通过man命令得知使用参数 -I(大写的i)可使用ICMP探测。于是执行:

traceroute -n -I 61.135.185.32

神奇的发现结果和mtr一样了!看到这里,才打消我对traceroute的偏见。原来不是traceroute不好用,而是我使用的方法不当。至此,回到问题,我们大胆推测:从第10跳之后,第11跳这个路由器屏蔽了对UDP包的响应(甚至连ICMP都屏蔽了),而第12跳到了目标IP,它不是路由器,所以收到UDP之后,会尝试寻找主机中对应端口的UDP服务,因为没有此UDP服务,所以目的主机一般会通过icmp协议响应端口不可达,但这里没有返回任何信息(可能是安全策略),到第13跳,还是到了目的主机,依旧没有响应,如此直到第30跳结束(traceroute默认最多30跳)。接下来做个测试来验证假设:

首先在虚拟机192.168.2.104上tranceroute我的一台云主机198.x.x.82:

云主机上没有任何限制,所以可以看到tranceroute正常显示,一共有16跳。接下来我在云主机上配置了一条iptables规则如下:

我们再在虚拟机192.168.2.104上执行tranceroute命令,结果显示如下:
https://pic4.zhimg.com/80/v2-bb13dd1426c5a31a34edd4692605853f_720w.jpg
可以看到第16跳已经显示为了,且后续的结果均为,因为后面的请求都到了这台云主机,在云主机上抓包如下:

共收到 ttl=1到ttl=15的数据包各3个,即对应了tranceroute中的16-30的*。这足以证明之前的假设成立。
问2:为什么发送UDP请求包,会响应ICMP包?

这个东西,其实我也很好奇,但是静下心来想一想,这个ICMP是路由器发送的,并不是我们比较熟悉的主机。所以我们大胆推测:路由器在收到TTL为1的数据包时,会把该数据包TTL-1,此时TTL为0,就不再往后转发了,而是给源主机发送一个ICMP响应,告诉主机这个数据包TTL为0了也没到达目的地址。我们做个测试:使用nping命令发送UDP包给目标主机,然后设置TTL为一个达不到目标主机的值,观察到:

果真收到了路由器发来的ICMP响应。再试一下其他协议:


果然证明了刚刚的假设。路由器不管是什么协议,只要TTL在它那为0了,它就会给源主机发送ICMP响应。当然,前提是路由器没有禁用这个功能。

问3:为什么目的是同一个IP,traceroute和mtr返回的路径会不一样?

上面可以看到traceroute默认使用的UDP协议,返回的内容和mtr不一样,将traceroute改为icmp的方式探测,结果就一样了。这说明使用不同的协议数据包,路由器的转发会有区别。这时就引起了我的思考了,我们平时往往是因为业务服务出现问题了,才会用mtr去排查网络问题。所以假设你的业务是用HTTP协议的的话,它底层用的是tcp,而不是icmp。那么你就应该用tcp的方式探测,否则你得到的结果很可能是不准确的。我们用mtr中的tcp模式探测:

mtr -n -T 61.135.185.32

发现与mtr默认的icmp探测的结果是不一样的。这再一次证明了之前的理论:使用不同的协议数据包,路由器的转发会有区别。*

推荐阅读