目录
介绍
traceroute 主要用来追踪从某个节点到某个指定目标ip的路径上的各个节点的信息,通过捕获各个节点发来的icmp ttl 超时报文来获取路径上的各个节点的信息。
icmp 差错报文
ip头 ttl 字段
IP报文首部的TTL字段:
TTL是 Time To Live的缩写,该字段指定IP包被路由器丢弃之前允许通过的最大网段数量。TTL是IPv4报头的一个8 bit字段。TTL的作用是限制IP数据包在计算机网络中的存在的时间。TTL的最大值是255,TTL的一个推荐值是64。
原理
traceroute的实现都借助了TTL:通过向目的地址发送一系列的探测包,设置探测包的TTL初始值分别为1,2,3…,根据返回的超时通知(icmp超时差错报文:ICMP Time Exceeded Message)得到源地址与目的地址之间的每一跳路由信息。在传输过程中每经过一个路由器,TTL的值都会减1,当TTL为0时,发回一个ICMP超时通知(ICMP Time Exceeded Message)。
基于UDP的 traceroute
Traceroute程序发送一份UDP数据报给目的主机,但它选择一个不可能的值作为UDP端口号(大于30000),使目的主机的任何一个应用程序都不可能使用该端口。如果存在目的主机使用该udp目的端口,由于udp的特性,则接受该报文,不一定会有响应报文回复。如果使用目的主机没有监听的udp端口,则目的主机会产生一份“端口不可达”错误的ICMP报文,发送给client。
第一个数据包,TTL=1,这样第一跳路由器收到后,要转发出去时,会将TTL减一,即TTL=0, 就丢弃,然后第一跳路由器就返回一个ICMP超时的错误信息,
所以,客户端通过判断收到ICMP端口不可达报文来确定数据包已到达目的地,如果是收到ICMP超时错误信息报文,说明还没到达目的地,就会将TTL加1,以此类推。
基于ICMP的 traceroute
基于ICMP报文的traceroute是这样实现的:让你在客户端输入 traceroute 命令+ip时, 客户端就发起一个ICMP回显请求报文,第一个数据包,TTL=1,这样第一跳路由器收到后,要转发出去时,会将TTL减一,即TTL=0, 就丢弃,然后第一跳路由器就返回一个ICMP超时的错误信息,客户端收到后,会判断是否收到ICMP 回显应答 报文? 如果还没收到,就会继续发送 回显请求报文,TTL加1进行尝试,当到底服务器后,服务器就会发送 ICMP 回显应答报文。
基于TCP的 traceroute
TCP模式:TCP [SYN]探测数据包(假设:目标端口为Web服务的80) + 中间网关发回 ICMP TTL 超时数据包 + 目标主机发回TCP [SYN ACK/或者rst 报文(tcp使用rst表明端口不可达)] 数据包。
TCP traceroute 向外发送的是 TCP SYN 数据包,这样做最大的好处就是穿透防火墙的几率更大因为 TCP SYN 看起来是试图建立一个正常的 TCP 连接。
icmp差错报文
格式
参考: RFC792
nat/lb设备对于icmp差错报文的处理
- 内网访问外网的场景:
nat-xy 是一个nat设备。
router-x 和 host-x 是外网的交换机和主机。
router-y 和 host-y 是内网的交换机和主机。
外网交换机以及路由器上存在内网的网段的路由;同样内网的交换机和路由器上存在外网的路由。
(为了避免icmp差错报文由于rp_filter开启,不存在sip的路由而被丢弃)
流量:
host-y 去访问 host-x;
经过nat-xy,将会sip从host-y转换为 host-y’
host-y----->host-x, 经过 nat设备,变为了 host-y’---->host-x; 此时在 host-x 或者 route-x 上产生了icmp差错报文:
外层:dip为 host-y’,sip为 host-x 或者 route-x 。
内层为: host-y’---->host-x
经过 nat设备的转换后,变为:
外层:dip为 host-y,sip为 host-x 或者 route-x ;
内层:host-y—>host-x
- 外网访问内网的场景
router-y/host-y 生成的icmp差错报文的格式为:
外层: router-y/host-y----->host-x
内层:host-x------->host-y
经过nat设备之后,转换如下:
外层: xxx/----->host-x
内层:host-x------->host-y’
注:外层的sip是期望在外网可见的。因为sip不可见的报文在外网的设备上可能会被丢弃(host-x本身作为dip在外网就是可见的,所以不考虑转换dip)。
如果router-y在外网可见,那么使用route-y即可。
如果router-y在外网不可见,那么就将router-y转换为一个可见的对应的ip地址。
此中host-y应该是外网不可见的,那么就应该将host-y的sip转换为 host-y’
注意事项
- 并不能保证现在的路由也是将来所要采用的路由,甚至两份连续的IP数据报都可能采用不同的路由。
如果在运行程序时,路由发生改变,就会观察到这种变化,这是因为对于一个给定的TTL,如果其路由发生变化,traceroute程序将打印出新的IP地址。 - 不能保证ICMP报文的路由与traceroute程序发送的UDP数据报采用同一路由。
这表明所打印出来的往返时间可能并不能真正体现数据报发出和返回的时间差(如果UDP数据报从信源到路由器的时间是1秒,而ICMP差错报文用另一条路由返回信源用了3秒时间,则打印出来的往返时间是4秒)。 - 返回的ICMP差错报文中的信源IP地址是UDP数据报到达的路由器接口的IP地址。
记录的IP地址指的是发送接口地址。由于每个定义的路由器都有2个或更多的接口,因此,从A主机到B主机上运行traceroute程序和从B主机到A主机上运行traceroute程序所得到的结果可能是不同的。
应用
使用traceroute获取特定流的路径
如下所示;通过下列方法 发送特定流的 tcp/udp 流量,查看其路径。
对于 TCP 的 traceroute:
traceroute -T IP -p PORT -s SIP --sport=SPORT
对于 udp 的 traceroute:
traceroute -U IP -p PORT -s SIP --sport=SPORT
注:traceroute 查看流的正向的路径,只能确定单向的路径。由于同一条流,正反向经过的设备可能不一致。traceroute只能确定正向流经过的节点,对于反向流经过的节点无法确定。
其他
基于tcp的 traceroute
https://juejin.cn/post/7086315715963125790
nat设备如何处理icmp差错报文:
https://www.rfc-editor.org/rfc/rfc5508