网络探测工具(二)——traceroute

简述

搭建网络环境的时候,经常有想要知道报文从源到目的所经历的所有路由节点这样的需要。此时,traceroute小程序,后续简称为tracert,就有用武之地了。

功能

tracert,最初由大神Van Jacobson设计并实现(膜拜),可以用来探测出报文在网络中从源到目的所经过的所有三层路由节点。

原理

既然tracert用来探测路径,那么问题来了:它如何确定路径?

1. 确定路径

我们知道IP报文头有一个ttl字段,用来确定IP报文的存活时间。每经过一次转发,ttl数值减一,当ttl为0时,如果报文还没有到达目的,那么协议栈就会向源端回应一个ICMP ttl超时报文。知道了这个东东后,确定路径是否就有眉目了呢?
(1)向目的发送ttl=1的UDP报文,第一个路由节点收到报文后发现ttl=0,向源端回应一个ICMP ttl超时报文,源知道了第一个路由节点。
(2)向目的发送ttl=2的UDP报文,第一个路由节点收到报文后ttl=1,继续转发给第二个路由节点,第二个路由节点收到报文后ttl=0,向源端回应一个ICMP ttl超时报文,源又知道了第二个路由节点。
(3)向目的发送ttl=3的UDP报文……

2. 确定目的

通过上面步骤可以一直发送UDP报文直到报文到达目的,那么问题来了:
(1)挖掘机技术哪家强?
(2)源如何知道报文到达了目的并停止发报文?
关于问题(1),我想大家都知道那是布鲁西特大学(blue shit)最强。
接下来重点介绍问题(2)。
我们又知道,UDP报文头有一个字段叫目的端口,用来告诉目的端这个报文要请求的是哪个服务。当目的端服务(端口)不存在时,协议栈会向源发送一个ICMP端口不可达报文,告诉源,这儿没这服务,别来烦我。源又知道了目的是不是,呵呵。

好,到此为止,问题完美解决。

有无其他方案

单纯从IP报文的角度来说,四层协议常用有三中:ICMP(经常被认为是三层协议,why,不告诉你),UDP,TCP。
前面我们介绍从源发送的是UDP报文,那么能否用ICMP或者TCP报文替换?答案必须是肯定的,否则哪里来的乐趣?

1.发送ICMP报文

确定路径的原理和前面一致,利用ttl超时。那么如何确认到达了目的?
想想ping程序的实现:发送ICMP echo报文,回应ICMP echo reply。
非常好,源持续向目的发送ttl递增的ICMP echo报文:收到ICMP ttl超时报文时认为是路径上路由节点,收到ICMP echo replay时认为到达了目的。

2.发送TCP报文

首先要明确的原理肯定和前面一致;其次要明确的是肯定不能直接发送TCP报文,why?
TCP是面向连接的协议,发送TCP报文首先要和目的建立连接,tracert哪里知道目的端有啥服务。就算知道某个目的端有某个服务,但是换个目的端怎么办?有没有通用点方案?

办法都是憋出来的,硬憋肯定能憋出来。
先来想想为啥不能发TCP报文,因为发报文前要先建立连接。
那连接咋建立的?三次握手。啥叫三次握手,简单来说跟建基友的过程是一样的:

Created with Raphaël 2.1.0 源 源 目的 目的 嘿,我要当你基友,你说好不好?(syn报文) 目的想了一下,说: 恩,好啊;那我也要当你基友,你说好不好?(ack + syn报文) 源非常happy 恩,好!(ack报文)

就是这么简单,so easy,一对好基友非常友好非常暧昧的开始交往。
回到正题:既然不能发TCP报文的原因是它要先建立连接,那么,怎样才能不建立连接?
tracert直接开始第三次握手。也就是说,源向目的发送“恩,好!(ack报文)”这个消息。
目的端收到这个消息后心想,哪个白痴连握手都不会。然后它就告诉源咱俩得重新开始握手(rst报文)。

好了,问题解决:源持续向目的发送ttl递增的ack报文,收到超时回应后认为是路径上的路由节点,收到rst报文后认为到达目的端。

备注:
1. UDP及ICMP方式实现的tracert是经过先贤们验证的可行方案,TCP方式是我自己琢磨出来的(应该还有其他人琢磨出来,但是我没看过),还未实现,不确定能否成功,需要实现验证一下。
2. 具体的实现代码(c语言)等我完成后会贴出来。

你可能感兴趣的:(traceroute,tracert,icmp,tcpip)