我发现了windows的tracert命令的一个bug---ICMP重定向包详尽分析

hi朋友,如果你的好奇心没有因繁杂的生活而被消磨,如果你喜欢对计算机进行追根究底的研究,那么欢迎与我一起,进行一趟说走就走的ICMP协议底层之旅。

先把ICMP包结构贴在这里:

我们研究的是差错报告报文的类型5,也就是ICMP"重定向"报文,它有2个作用:对网络重定向,对主机重定向。

要理解这个报文的作用,先画出一张拓扑图:

实验是PC1 ping PC3,由于PC1的默认网关是路由器R1的f0/0口,所以数据包的流向是:PC1→R1→R6→PC3。

但很明显,R1的转发多此一举,PC1把数据包直接发给路由器R6的f0/0口即可。

所以R1会给PC1发出一个ICMP错误报文,本例是type=5,code=0,意为网络重定向,即告诉PC1:去往192.168.7.0/24这个网络(路由器有路由表),网关应该是192.168.0.4,wireshark抓包如下:

PC1收到后会更新路由表,下一跳指向192.168.0.4的MAC地址,数据包转由R6转发。

那么接下来就做实验。先运行wf.msc关闭防火墙,因为防火墙会禁用ICMP重定向包以防止中间人攻击风险。

用tracert命令跟踪数据包的路径,这是2次运行tracert命令的结果:

tracert命令的原理是,发出ICMP的ping包(type=8,code=0),但初始ttl=1,之后每次累加1,直到目的地。这样一来,途径的每个路由器将TTL-1,如果为0,就会向PC1发回"TTL过期"错误包(type=5,code=0),这样tracert命令就探测出了途径的所有路由器和主机。

分析上图。用wiershark抓包可以发现,第一次运行tracert命令,R1会向PC1返回ICMP重定向包(type=5,code=0),但随后仍然会继续转发此包,也就是说第一次ping能够到达目的地,但并非最优路径。

第二次运行tracert命令,由于之前收到了ICMP重定向包,所以修改了路由表,ping包的第一跳就是R6,随后到达目的地。

但我们只关注第一次运行tracert命令的结果。你发现了没有,路径是不对的,正确的应该是R2(192.168.0.1)→R6(192.168.0.4)→PC3(192.168.7.2)才对,可显示的结果缺失了中间的R6(192.168.0.4)。

一开始我也是百思不得其解,但仔细观察wireshark的抓包结果之后,终于知道了问题根源所在。

原来,tracert命令发出的第一个ping包的TTL=1,那么第二个ping包就应该是TTL=2,第三个ping包应该是TTL=3。。。

可这种累加策略却忽略了ICMP重定向包造成的"干扰",所以当第二个ping包的下一跳转向R6时,携带的TTL=2。

当数据包到达R6,会将TTL-1=1,由于并非为0,所以R6不会向PC1返回TTL过期的ICMP错误包,tracert命令也就探测不到R6的存在了。

这。。。算是tracert命令的一个bug吧。正确的方法是当路由表被ICMP重定向包修改,发出的第一个ping包的TTL应该被置为1。

对此,GNS3的VPCS虚拟设备就做得很好,清楚地显示了路径的修改过程:

另外,被ICMP重定向包修改的路由表是看不到的,因为Windows 在处理 ICMP Redirect 时,不会在永久或显示的路由表中增加一条可见路由项。被重定向的路由是**内核临时缓存(transient route)**中的一部分,只在内存中生效,不会显示在 route print 或 netstat -r 里。这个缓存属于 TCP/IP 协议栈内部(Route Cache 或 Neighbor Cache),更新仅在该目标主机或子网通信时生效,不会写入持久路由表。

但也有显示的方法------显示缓存表:

netsh interface ipv4 show destinationcache

还有资料提到另一种写法,记录于此:

netsh interface ipv4 show global

相关推荐
techdashen35 分钟前
Go 1.25 新特性:Flight Recorder —— 像黑匣子一样捕捉线上 Bug
java·golang·bug
悟空爬虫-彪哥1 天前
VRCFaceTracking安装和iPhone面捕配置教程,有bug
ios·bug·iphone
22信通小白2 天前
USRP初学者使用手册(基础配置及bug记录)——Linux+Clion(单台X310收发)
linux·运维·c++·5g·bug·信息与通信
麦哲思科技任甲林2 天前
需求还是bug?
bug·需求·需求变更
万粉变现经纪人3 天前
如何解决 pip install tensorflow-gpu 报错 未检测到 CUDA 驱动 问题
人工智能·python·深度学习·aigc·tensorflow·bug·pip
初圣魔门首席弟子4 天前
boost配置遇到的bug
bug
万粉变现经纪人4 天前
如何解决 pip install ta-lib 报错 本地 TA-Lib 库未安装 问题
数据库·python·scrapy·oracle·bug·pandas·pip
Cc_Debugger5 天前
【饿了么plus-table】开启多选时,点击下面的单选按钮,页面显示是全选的样子,bug
bug
龙卷风卷云5 天前
【BUG】Nginx使用upstream后端接口报 400
运维·nginx·bug
jiayi_19996 天前
[bug] unsupported GNU version! gcc versions later than 12 are not supported!
服务器·bug·gnu