关于ICMP与ping:计算机网络中的侦察兵
关于ICMP与ping:计算机网络中的侦察兵
本文章主要内容引用自:1.刘超,趣谈网络协议 2.每天学习一个命令:traceroute 查看路由信息
ICMP协议的格式
在日常工作生活中,大家经常会遇到网络不通的情况,面对这种情况,我们首先会想到ping一下。那ping是如何工作的呢?
ping是基于ICMP协议工作的。 ICMP 全称 Internet Control Message Protocol,就是 互联网控制报文协议。这里面的关键词是“控制”,那具体是怎么控制的呢?
网络包在异常复杂的网络环境中传输时,常常会遇到各种各样的问题。当遇到问题的时候,总不能“死个不明不白”,要传出消息来,报告情况,这样才可以调整传输策略。这就相当于我们经常看到的电视剧里,古代行军的时候,为将为帅者需要通过侦察兵、哨探或传令兵等人肉的方式来掌握情况,控制整个战局。
ICMP报文是封装在IP包里面的。因为传输指令的时候,肯定需要源地址和目标地址。它本身非常简单。因为作为侦查兵,要轻装上阵,不能携带大量的包袱。
ICMP报文有很多的类型,不同的类型有不同的代码。 最常用的类型是主动请求为8,主动请求的应答为0。
查询报文类型
我们经常在电视剧里听到这样的话:主帅说,来人哪!前方战事如何,快去派人打探,一有情况,立即通报!
这种是主帅发起的,主动查看敌情,对应ICMP的 查询报文类型。例如,常用的 ping就是查询报文,是一种主动请求,并且获得主动应答的ICMP协议。 所以,ping发的包也是符合ICMP协议格式的,只不过它在后面增加了自己的格式。
对ping的主动请求,进行网络抓包,称为 ICMP ECHO REQUEST。同理主动请求的回复,称为ICMP ECHO REPLY。比起原生的ICMP,这里面多了两个字段,一个是 标识符。这个很好理解,你派出去两队侦查兵,一队是侦查战况的,一队是去查找水源的,要有个标识才能区分。另一个是 序号,你派出去的侦查兵,都要编个号。如果派出去10个,回来10个,就说明前方战况不错;如果派出去10个,回来2个,说明情况可能不妙。
在选项数据中,ping还会存放发送请求的时间值,来计算往返时间,说明路程的长短。
差错报文类型
当然也有另外一种方式,就是差错报文。
主帅骑马走着走着,突然来了一匹快马,上面的小兵气喘吁吁的:报告主公,不好啦!张将军遭遇埋伏,全军覆没啦!这种是异常情况发起的,来报告发生了不好的事情,对应ICMP的 差错报文类型。
我举几个ICMP差错报文的例子: 终点不可达为3,源抑制为4,超时为11,重定向为5。这些都是什么意思呢?我给你具体解释一下。
第一种是终点不可达。小兵:报告主公,您让把粮草送到张将军那里,结果没有送到。
如果你是主公,你肯定会问,为啥送不到?具体的原因在代码中表示就是,网络不可达代码为0,主机不可达代码为1,协议不可达代码为2,端口不可达代码为3,需要进行分片但设置了不分片位代码为4。
具体的场景就像这样:
- 网络不可达:主公,找不到地方呀?
- 主机不可达:主公,找到地方没这个人呀?
- 协议不可达:主公,找到地方,找到人,口号没对上,人家天王盖地虎,我说12345!
- 端口不可达:主公,找到地方,找到人,对了口号,事儿没对上,我去送粮草,人家说他们在等救兵。
- 需要进行分片但设置了不分片位:主公,走到一半,山路狭窄,想换小车,但是您的将令,严禁换小车,就没办法送到了。
第二种是源站抑制,也就是让源站放慢发送速度。小兵:报告主公,您粮草送的太多了吃不完。
第三种是时间超时,也就是超过网络包的生存时间还是没到。小兵:报告主公,送粮草的人,自己把粮草吃完了,还没找到地方,已经饿死啦。
第四种是路由重定向,也就是让下次发给另一个路由器。小兵:报告主公,上次送粮草的人本来只要走一站地铁,非得从五环绕,下次别这样了啊。
差错报文的结构相对复杂一些。除了前面还是IP,ICMP的前8字节不变,后面则跟上出错的那个IP包的IP头和IP正文的前8个字节。
而且这类侦查兵特别恪尽职守,不但自己返回来报信,还把一部分遗物也带回来。
- 侦察兵:报告主公,张将军已经战死沙场,这是张将军的印信和佩剑。
- 主公:神马?张将军是怎么死的(可以查看ICMP的前8字节)?没错,这是张将军的剑,是他的剑(IP数据包的头及正文前8字节)。
ping:查询报文类型的使用
接下来,我们重点来看ping的发送和接收过程。
假定主机A的IP地址是192.168.1.1,主机B的IP地址是192.168.1.2,它们都在同一个子网。那当你在主机A上运行“ping 192.168.1.2”后,会发生什么呢?
ping命令执行的时候,源主机首先会构建一个ICMP请求数据包,ICMP数据包内包含多个字段。最重要的是两个,第一个是 类型字段,对于请求数据包而言该字段为 8;另外一个是 顺序号,主要用于区分连续ping的时候发出的多个数据包。每发出一个请求数据包,顺序号会自动加1。为了能够计算往返时间RTT,它会在报文的数据部分插入发送时间。
然后,由ICMP协议将这个数据包连同地址192.168.1.2一起交给IP层。IP层将以192.168.1.2作为目的地址,本机IP地址作为源地址,加上一些其他控制信息,构建一个IP数据包。
接下来,需要加入MAC头。如果在本节ARP映射表中查找出IP地址192.168.1.2所对应的MAC地址,则可以直接使用;如果没有,则需要发送ARP协议查询MAC地址,获得MAC地址后,由数据链路层构建一个数据帧,目的地址是IP层传过来的MAC地址,源地址则是本机的MAC地址;还要附加上一些控制信息,依据以太网的介质访问规则,将它们传送出去。
主机B收到这个数据帧后,先检查它的目的MAC地址,并和本机的MAC地址对比,如符合,则接收,否则就丢弃。接收后检查该数据帧,将IP数据包从帧中提取出来,交给本机的IP层。同样,IP层检查后,将有用的信息提取后交给ICMP协议。
主机B会构建一个 ICMP 应答包,应答数据包的类型字段为 0,顺序号为接收到的请求数据包中的顺序号,然后再发送出去给主机A。
在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了 ICMP 应答包,则说明目标主机可达。此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。
当然这只是最简单的,同一个局域网里面的情况。如果跨网段的话,还会涉及网关的转发、路由器的转发等等。但是对于ICMP的头来讲,是没什么影响的。会影响的是根据目标IP地址,选择路由的下一跳,还有每经过一个路由器到达一个新的局域网,需要换MAC头里面的MAC地址。
如果在自己的可控范围之内,当遇到网络不通的问题的时候,除了直接ping目标的IP地址之外,还应该有一个清晰的网络拓扑图。并且从理论上来讲,应该要清楚地知道一个网络包从源地址到目标地址都需要经过哪些设备,然后逐个ping中间的这些设备或者机器。如果可能的话,在这些关键点,通过tcpdump -i eth0 icmp,查看包有没有到达某个点,回复的包到达了哪个点,可以更加容易推断出错的位置。
经常会遇到一个问题,如果不在我们的控制范围内,很多中间设备都是禁止ping的,但是ping不通不代表网络不通。这个时候就要使用telnet,通过其他协议来测试网络是否通。
Traceroute:差错报文类型的使用
traceroute(跟踪路由)是路由跟踪程序,用于确定 IP 数据报访问目标所经过的路径。traceroute 命令用 IP 存活时间 (TTL) 字段和 ICMP 错误消息来确定从一个主机到网络上其他主机的路由。
通过 traceroute 命令可以知道数据包从你的计算机到互联网另一端的主机是走的什么路径。当然每次数据包由某一同样的出发点(source)到达某一同样的目的地 (destination) 走的路径可能会不一样,但大部分时候所走的路由是相同的。
Linux 系统中是 traceroute, 在 Windows 中为 tracert。traceroute 通过发送小数据包到目的主机直到其返回,来测量其耗时。一条路径上的每个设备 traceroute 要测 3 次。输出结果中包括每次测试的时间 (ms) 和设备的名称及其 IP 地址。
使用
命令格式:
1 |
|
命令功能:
traceroute 预设数据包大小是 40Bytes,可设置。
具体参数格式:
1 |
|
命令参数:
1 |
|
工作原理
traceroute 命令利用 ICMP 及 IP header 的 TTL(Time To Live) 字段 (field)。
- traceroute 送出一个 TTL 是 1 的 IP datagram 到目的地(每次送出的为 3 个 40 字节的包,包括源地址,目的地址和包发出的时间),当路径上的第一个路由器 (router) 收到这个 datagram 时,它将 TTL 减 1。此时,TTL 变为 0 了,所以该路由器会将此 datagram 丢掉,并送回一个「ICMP time exceeded」消息(包括发 IP 包的源地址,IP 包的所有内容及路由器的 IP 地址),traceroute 收到这个消息后,便知道这个路由器存在于这个路径上
- 接着 traceroute 再送出另一个 TTL 是 2 的 datagram,发现第 2 个路由器
- ……
- traceroute 每次将送出的 datagram 的 TTL 加 1 来发现另一个路由器,这个重复的动作一直持续到某个 datagram 抵达目的地。当 datagram 到达目的地后,该主机并不会送回 ICMP time exceeded 消息,因为它已是目的地了。
- traceroute 如何得知目的地到达了呢?traceroute 在送出 UDP datagrams 到目的地时,它所选择送达的 port number 是一个一般应用程序都不会用的端口 (30000 以上),所以当此 UDP datagram 到达目的地后该主机会回送一个 (ICMP port unreachable) 的消息,而当 traceroute 收到这个消息时,便知道目的地已经到达了。所以 traceroute 在 Server 端也是没有所谓的 Daemon 程式。
traceroute 提取发 ICMP TTL 到期消息设备的 IP 地址并作域名解析。每次 traceroute 都打印出一系列数据,包括所经过的路由设备的域名及 IP 地址,三个包每次来回所花时间。
实例
最常用法
直接追踪路由
1 |
|
结果说明:
1 |
|
序列号从 1 开始,每条纪录就是一跳,每一跳表示一个网关,每行有三个时间,单位都是 ms,其实就是 -q
的默认参数。探测数据包向每个网关发送三个数据包后,网关响应后返回的时间;如果您用 traceroute -q 10 google.com
,表示向每个网关发送 10 个数据包。
traceroute 一台主机有时会看到一些行以星号表示,出现这样的情况,可能是防火墙封掉了 ICMP 的返回信息,得不到什么相关的数据包返回数据。
有时在某一网关处延时比较长,可能是某台网关比较阻塞,也可能是物理设备本身的原因。当然如果某台 DNS 出现问题时,不能解析主机名、域名时,也会有延时长的现象;您可以加 -n
参数来避免 DNS 解析,以 IP 输出数据。
如果在局域网中的不同网段之间,可以通过 traceroute 来排查问题所在,是主机的问题还是网关的问题。如果通过远程来访问某台服务器遇到问题时,用到 traceroute 追踪数据包所经过的网关,提交 IDC 服务商,也有助于解决问题;但目前看来在国内解决这样的问题是比较困难的,即使发现问题,IDC 服务商也不可能帮助解决。
跳数设置
1 |
|
不解析主机名
1 |
|
设置探测包数量
1 |
|
绕过正常的路由表直接发送到网络相连的主机
1 |
|
小结
- ICMP相当于网络世界的侦察兵。我讲了两种类型的ICMP报文,一种是主动探查的查询报文,一种异常报告的差错报文;
- ping使用查询报文,Traceroute使用差错报文。