gitbook/趣谈网络协议/docs/8445.md
2022-09-03 22:05:03 +08:00

12 KiB
Raw Permalink Blame History

第7讲 | ICMP与ping投石问路的侦察兵

无论是在宿舍,还是在办公室,或者运维一个数据中心,我们常常会遇到网络不通的问题。那台机器明明就在那里,你甚至都可以通过机器的终端连上去看。它看着好好的,可是就是连不上去,究竟是哪里出了问题呢?

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
  • 端口不可达:主公,找到地方,找到人,对了口号,事儿没对上,我去送粮草,人家说他们在等救兵。
  • 需要进行分片但设置了不分片位:主公,走到一半,山路狭窄,想换小车,但是您的将令,严禁换小车,就没办法送到了。

第二种是源站抑制,也就是让源站放慢发送速度。小兵:报告主公,您粮草送的太多了吃不完。

第三种是时间超时,也就是超过网络包的生存时间还是没到。小兵:报告主公,送粮草的人,自己把粮草吃完了,还没找到地方,已经饿死啦。

第四种是路由重定向,也就是让下次发给另一个路由器。小兵:报告主公,上次送粮草的人本来只要走一站地铁,非得从五环绕,下次别这样了啊。

差错报文的结构相对复杂一些。除了前面还是IPICMP的前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通过其他协议来测试网络是否通这个就不在本篇的讲述范围了。

说了这么多你应该可以看出ping这个程序是使用了ICMP里面的ECHO REQUEST和ECHO REPLY类型的。

Traceroute差错报文类型的使用

那其他的类型呢是不是只有真正遇到错误的时候才能收到呢那也不是有一个程序Traceroute是个“大骗子”。它会使用ICMP的规则故意制造一些能够产生错误的场景。

所以,Traceroute的第一个作用就是故意设置特殊的TTL来追踪去往目的地时沿途经过的路由器。Traceroute的参数指向某个目的IP地址它会发送一个UDP的数据包。将TTL设置成1也就是说一旦遇到一个路由器或者一个关卡就表示它“牺牲”了。

如果中间的路由器不止一个当然碰到第一个就“牺牲”。于是返回一个ICMP包也就是网络差错包类型是时间超时。那大军前行就带一顿饭试一试走多远会被饿死然后找个哨探回来报告那我就知道大军只带一顿饭能走多远了。

接下来将TTL设置为2。第一关过了第二关就“牺牲”了那我就知道第二关有多远。如此反复直到到达目的主机。这样Traceroute就拿到了所有的路由器IP。当然有的路由器压根不会回这个ICMP。这也是Traceroute一个公网的地址看不到中间路由的原因。

怎么知道UDP有没有到达目的主机呢Traceroute程序会发送一份UDP数据报给目的主机但它会选择一个不可能的值作为UDP端口号大于30000。当该数据报到达时将使目的主机的 UDP模块产生一份“端口不可达”错误ICMP报文。如果数据报没有到达则可能是超时。

这就相当于故意派人去西天如来那里去请一本《道德经》结果人家信佛不信道消息就会被打出来。被打的消息传回来你就知道西天是能够到达的。为什么不去取《心经》呢因为UDP是无连接的。也就是说这人一派出去你就得不到任何音信。你无法区别到底是半路走丢了还是真的信佛遁入空门了只有让人家打出来你才会得到消息。

**Traceroute还有一个作用是故意设置不分片从而确定路径的MTU。**要做的工作首先是发送分组并设置“不分片”标志。发送的第一个分组的长度正好与出口MTU相等。如果中间遇到窄的关口会被卡住会发送ICMP网络差错包类型为“需要进行分片但设置了不分片位”。其实这是人家故意的好吧每次收到ICMP“不能分片”差错时就减小分组的长度直到到达目标主机。

小结

好了,这一节内容差不多了,我来总结一下:

  • ICMP相当于网络世界的侦察兵。我讲了两种类型的ICMP报文一种是主动探查的查询报文一种异常报告的差错报文
  • ping使用查询报文Traceroute使用差错报文。

最后,给你留两个思考题吧。

  1. 当发送的报文出问题的时候会发送一个ICMP的差错报文来报告错误但是如果ICMP的差错报文也出问题了呢
  2. 这一节只说了一个局域网互相ping的情况。如果跨路由器、跨网关的过程会是什么样的呢

欢迎你留言和我讨论。趣谈网络协议,我们下期见!