csatblogspotdotcom

Tuesday, January 19, 2016

tracepath显示no reply至Too many hops的分析

关于命令: Windows下有tracert,Linux下有对应的traceroute,而Ubuntu默认自带的没有traceroute而是tracepath,三者有联系也有区别;另外Linux下还有一个mtr。 三者是探测路径的命令,但Windows下的tracert使用ICMP,Linux下的tracepath使用UDP且不需要root权限(当且仅当UDP时无需root权限),Linux下的traceroute使用ICMP/TCP/UDP均可,但ICMP/TCP需superuser privileges;mtr使用ICMP无需superuser privileges;简单的说,traceroute的ICMP/TCP方式需要superuser privileges,其余都不需要; tracepath测试对方的UDP端口默认从44444开始,当然也可用-p指定起始端口(traceroute也用-p指定UDP起始端口),每发一个包目的端口+1,TTL也+1,正常情况下中间一跳返回:ICMP time exceeded in-transit,表示TTL用尽了,而最后目的地会返回ICMP IPdst*** udp port *** unreachable,如果中间或者目的地没有反应,则no reply直至30hops用尽--以上是tcpdump得到的结论 tracepath的发包规则究竟是怎样的呢?对tracepath 网关(没有一个包有回应)进行tcpdump的结果是,前4个包ttl为1,后面连续三个ttl为2,再后再+1,最后为30,30hops共发送91个UDP包,端口号从44444到44444+63后再从44444开始循环到44470,此时30hops用尽;再对tracepath DNS(前面几个有回应,后面没回应)进行tcpdump的结果:ttl=1时有了回应,但仍然继续发第二个(发且只发2),ttl>1时如果有回应就不再继续发,如果没回应,则继续,最多发3个包;另外发送端口是随机指定一个大端口,并保持不变;由于只要有一个包响应了就不会继续发,于是每行(每个ttl)对应的结果只有一个时间或者超时(显示no reply) traceroute的man里面提到如果UDP模式是默认的,而且端口号是指定53(不像tracepath从44444开始每次+1),但tcpdump发现并不是这样,端口是从33434开始递增且一直增不循环,发送端口每个包都随机一个大端口每次都不一样;对traceroute 网关(没有一个包有回应)进行tcpdump的结果是,每个ttl都会发送三个包,所有包目的端口从33434开始+1递增,共发送90个UDP包;而当中间节点或者目标有反应时也一样,仍然会发三个包;由于每个ttl永远都是三个包,三个包的回应者不一样怎么办?结果会显示出来,三个包的结果在同一行分别显示,超时的是*,有回应的就显示耗时 mtr的man介绍说是traceroute和ping的结合,执行命令后进入列表,列出每一跳,及对应的时延、丢包等情况,而且这个表是实时刷新的,结果一目了然。对该命令进行tcpdump后发现,该命令从ttl=1开始不停发包,直到ttl能到达目的地此时对方返回ICMP echo reply,如此循环往复直至退出命令 原因分析: 使用UDP进行trace受到两个制约:1.中间路由转发、2.目的地的反应 首先看目的地的反应,在同一局域网里面,网关是一个交换机,tracepath IP1可以,tcpdump发现ICMP IP1 udp port 44444 unreachable,nc -uvz IP1 44444没反应,tcpdump发现一样是有返回ICMP IP1 udp port 44444 unreachable的;而tracepath 网关就不行,一直noreply直至30hops,nc 网关显示succeeded,tcpdump发现两个命令执行后,其实网关都没有回应;接下来是tracepath IP2,一台win7主机,同时nc它的UDP端口,tcpdump发现一样没反应,到底是防火墙过滤了还是主机根本就没监听呢?到win7防火墙日志查看,没有相关的记录,包括drop丢弃和allow允许,都没有,说明根本就没出发防火墙过滤规则,是主机没监听而已;另外一个测试,ping IP2,由于win7主机防火墙没开相关规则,默认是拒绝ICMP的,ping命令发过来的ICMP全被防火墙drop掉了,win7下windump可以看见发过来的ICMP但主机根本没回应(上层协议不知道有ICMP过来,只是windump能检测到而已),发送端tcpdump也是看见发送不见回应,这样发送端会停在ping界面(Linux)或者显示超时(Windows);总之,不管是防火墙过滤了还是主机没监听,会造成发过来的UDP包不会受到回应,最后的结果是tracepath这个目标会一直显示no reply下去。 再来看中间的路由过滤。tracepath DNS 到第六跳后面就no reply了,tcpdump结果也显示后面的节点就没回应了,直到30hops,而使用ping -t number DNS测试发现number为6、7,直到10都是Time to live exceeded,11能通,而且直接ping是ttl=244,说明经过11个路由器才能到达目的地,在中间一跳就没反应了,到底是中间这个设备执行了包过滤没让过,还是后面的几跳包括目的地都不给反应呢?换一个端口测试:用-p 33434指定起始端口33434,能正确反馈!说明后续的所有节点包括目的地都是可以给出回应的,只是中间这个节点进行了包过滤:一看到UDP目的端口为4万多的包就直接drop,至于后续节点和目的地收到UDP目的端口为4万多的包之后会如何处理,不得而知,因为他们都躲在那个“问题节点”后面。后续又指定起始端口53(后续每个包+1直到+63后回到起始端口循环),前面几跳一样,但到了10跳又突然有了回应,后面又没了,直到第26跳有了回应后结束,tcpdump后发现,前面几个包有了exceeded回应,到了后面又没了回应,和默认端口44444情况下一样,但到了目的UDP端口增加到69时,69对应的tftp协议,这个包给到对方后对方回复了ICMP time exceeded in-transit,说明那个路由器的过滤规则是对tftp协议持开放态度的,允许其通过,但后续包的端口号增加了就又不行了,而到了后面又有了转机,53+63后,又回到了53,这时又让过了(53对应DNS服务),此时的ttl足够到达目的地,到了目的地(某公网DNS服务器)后,返回了FormErr,说明DNS服务器认为这个DNS查询包的格式不对,实际上这个包本身就只是测试包根本没有填好数据。至于中间这个进行包过滤的路由器的身份,由于tracepath出的地址,以及mtr出的地址都显示是一个内网地址,而且之前的几跳都是在内网,从这个路由器出去之后全是公网地址,有此可见这个进行包过滤的设备是内网与公网之间的一个“门户”,对流量进行了较严格的“审查”。 结论: 综上,可以得出结论,traceroute/tracepath探测路径可以用ICMP/TCP/UDP,其中只有UDP不需要superuser privileges,但这个命令也不好使,遇到中间路由器进行包过滤,或者目的地不理睬你的包,的情况下就显示no reply直到hops用尽了,解决办法?换命令,使用traceroute/tracert/mtr,使用他们的ICMP/TCP方式或者traceroute的UDP方式(能固定端口),或者换默认的起始端口:例如用-p 33434指定默认起始端口为33434,但网络环境千变万化,谁能保证指定的端口就一定可用呢?独立思考,仔细分析才是解决问题的关键 P.S. 过程中七猜八猜,还怀疑到是不是系统的bug,想过更新命令能不能解决问题。。。 后记: 隔了一天,今天,再Ubuntu安装了traceroute,发现第一次traceroute 公网DNS正常,后面几次都不行,全超时,而且每次都是本来该公网DNS给出回应就可以结束trace,多尝试几次发现有时候目标会给回应然后trace结束,再尝试用tracepath也一样,指定起始端口为33434,中间节点没问题,到了最后一下本该目标给回应的时候,目标有时能给回应,有时在后面某一跳出现,有时30hops结束了还不出现,nc -uvz 公网DNS 33434-33523,发现其中一些端口给了回应(命令显示succeeded表示目标没理这边,没显示表示有回送包,这里基本上是UDP port unreachable的包),再来nc测试这些端口发现目标给不给回应是随机的,连续发几个包,对方会回应一次,至于发多少次有一次,也看不出规律,tcpdump可以看到,traceroute的时候(默认起始端口为33434)中间节点都给了回应,目的地什么时候回应了,探测就结束了,这里的最后一次回应是UDP port unreachable的ICMP报文,这说明UDP探测方式情况下,目的地是不靠谱的,如果给出回应就OK,一直不给回应,UDP探测机制就不能有效探测 后记2: 为什么traceroute这类命令这么慢?有网友解释说因为路由器回复一个包需要生成,会每隔一段时间例如1秒处理一次,我想的话,路由器为转发而设计,做了相关优化,转发速度很快而且实时转发,但是生成一个包回复则比较费时,路由器也不会即时回复 后记3: traceroute/ping等命令可以设置ttl值或者最大hops数 ping参数-t指定发送ICMP报文的ttl值,如果转发设备发现ttl为1了,就不转发了,直接回复ttl exceeded(我想是因为转发节点收到包后先将ttl-1,然后发现ttl剩余0了,就回复ttl exceeded了);如果目的节点发现ttl为1,则会正常回复ICMP; traceroute参数-m指定最大ttl值即最大hops数,发送数据包最多到ttl为指定的值为止,除非目的节点有回应 所说的hops是从一个节点到另一个节点的一跳,而不是“转发一次”,手机网络工具小软件Fing中的traceroute可能将hops理解为了转发多少次,显示的hops数值会小1,这是不对的

Labels: , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home