可能是目前最全的讲 ICMP 的文章了

网络 网络管理
对于 ICMP 协议,你想知道的,可能包括以下几点,带着这些问题,下面我们就来一一解答。

对于 ICMP 协议,你想知道的,可能包括以下几点:

  • ICMP 是啥
  • 为啥需要 ICMP
  • ICMP 有哪些报文类型
  • ICMP 报文格式长啥样
  • 有哪些命令用了 ICMP
  • ICMP 有哪些内核参数
  • ICMP 的问题

带着这些问题,下面我们就来一一解答。

1. ICMP 是啥

ICMP,全称是 Internet Control Message Protocol,即互联网控制报文协议,所谓控制,就是通过下发指令来感知和控制网络环境,所以它一定是配合一个无法感知网络环境的协议来工作的,这个协议就是 IP(包括 IPv4 和 IPv6)。

所以,ICMP 通常被认为是 IP 协议的一部分,它封装在 IP 层中,使用 IP 协议进行传输。因此,严格来说,ICMP 既不是一个网络层协议,也不是一个传输层协议,而是介于两者之间的一个协议。

它的主要功能是传输网络诊断信息,信息主要包括两类:

  • 一类是 查询类报文 :主要用于信息的查询和采集,比如采集传输路径上的每个路由器都是谁,本次传输的报文是否达到目的地等等。
  • 另一类是 差错诊断类报文 :主要用于诊断网络故障,比如传输报文被丢弃的原因是什么等等。

2. 为啥需要 ICMP

我们都知道,IP 协议是一个不可靠协议,如果 IP 包在传输过程中出现错误,比如 checksum 对不上,拥塞,超时等等,那么 IP 包是会直接被丢弃的,之后也不会有进一步的努力来修正。

这是 IP 协议的一个设计准则决定的,也就是 best effort,尽力而为,这样的好处是让 IP 协议尽量保持简单的形态,只负责有效率的数据传输,而更多的质量控制交给高层的协议去处理(比如 TCP)。

但高层能提供质量控制的协议毕竟在少数,所以就需要在下层有协议来辅助 IP 完成必要的网络质量管理。ICMP 协议自然就被提出来了。

通过 ICMP 协议,当 IP 包发生错误的时候,上层发送 IP 包的主机或路由器并不知道下层发生了错误,这个时候,下层的主机或路由器就可以通过发送 ICMP 包,将错误信息汇报给上层,从而让上层的主机或路由器进行调整。

不过需要注意的是,ICMP 仅仅只能提供某些特定类型的错误信息汇报,并不能帮助 IP 协议成为可靠的协议。它能做的事还是有限,但用于基本的网络质量管理是足够了。

3. ICMP 报文格式长啥样

如下图所示,ICMP 报文是被封装在 IP 数据报中传输的。

IP 报头中的 Protocol 字段为 1 即表示该报文携带的是 ICMP 报文。(此处只是为了说明问题,因此 IP 报头是简化了的)

进一步看,ICMP 报头为 4 个字节:

  • 类型 type:占 1 个字节,表示较大范围类型分类的 ICMP 报文
  • 代码 code:占 1 个字节,表示较小范围类型分类的 ICMP 报文(type的细分)
  • 校验和 checksum:占 2 个字节,ICMP checksum 的计算方法类似于 IP checksum,但是不同的是 IP 只校验头部,ICMP 校验头部+数据部分

后面紧接的 ICMP 数据部分,根据前面的类型和代码字段的不同,具有不同的内容。

4. ICMP 有哪些报文类型

ICMP 支持的报文类型非常多,详细看下表:

类型字段指代了一大类,代码字段又细分了几大小类。

上面可能不够明确,我们通过下面这两张表来列举一下,由于类型太多了,而且有些平时非常少见,因此,这里我们只列举常见的一些类型。

第一张表:类型表

注:R表示查询报文,E表示差错报文

进一步,对于每种类型,又可以根据代码字段细分多种子类型,请看第二张表:

第二张表:类型细分表

通过这两张表,每一种类型的 ICMP 包的意思应该都比较清楚了。

有一种可能不太好理解,这里再重点讲解一下:

(1) 源端抑制

属于差错信息。如果某个源主机向目的主机快速地发送数据包,但目的主机来不及处理,就会向源主机发出该类型的 ICMP 包,提醒源主机放慢发送速度。

(2) 重定向

属于差错信息。如果某个源主机向网络中发送一个 IP 包,路径中某个路由器收到这个 IP 包,对照其路由表,发现自己不应该接收该包(包需要原路返回,或者不是最佳路由路径),就会向源主机发送该类型的 ICMP 包,提醒源主机修改自己的路由表,下次路由到另外一个更好的路由器。

(3) 需要分片但设置了不分片位

属于差错信息。如果某个源主机在发送一个 IP 包之前,对该 IP 包中的首部字段 DF 位设为 1,也就是“分片禁止位=1”,表示该包在传输的过程中不允许分片,但是中间某个路由器允许传输的最大路径 MTU 小于该包大小,需要分片才能传输,但是由于设置不分片位,路由器会将该包丢弃,并向源主机发送一个携带 MTU 信息的 ICMP 包,提醒源主机下次发包的大小不应超过该 MTU 的值。

这种类型的 ICMP 包通常用来发现传输路径上的 MTU 值。

(4) TTL超时

属于差错信息。超时定义了数据包在网络中存活的最长时间,IPv4 中的 TTL 字段和 IPv6 中的 Hop Limit 字段都表示了这层意思,它们是一个整数值,会随着经过的路由器而递减,当减为 0 时,就认为该 IP 包超时,然后当前减为 0 的路由器会向源主机发送 ICMP 包,通知它发生了超时错误。

5. 有哪些命令体现了 ICMP

ICMP 的这些包的类型,用户可以充分用来诊断网络的故障情况。

因此诞生了一些利用 ICMP 协议的网络诊断工具,其中比较知名的就是 ping 和 traceroute。这两工具分别利用两种类型的 ICMP 报文:

  • ping 使用查询类型报文
  • traceroute 使用差错类型报文

(1) ping

ping 使用了查询报文中的请求报文(类型为 8)和应答报文(类型为 0),主要查询某个网络节点的连通性,如果出现网络不连通的情况,具体是什么问题,会在应答报文中附带相关的差错信息予以告知。比如网络不可达(Network Unreacheable)、主机不可达(Host Unreachable)等等,然后用户就可以根据这些信息来分析具体是哪个环节出现问题。

下面一张图,显示了一个 ping 包的完整流程:

可以看到,通过各层协议栈的层层封装和解封装,一个 ping 包从一台主机发送到另一台主机,包括请求包和应答包。其中,如果目标 MAC 地址未知的话,需要先发出 ARP 请求拿到,然后再进行封装。

关于 ping 命令的使用案例可以参考这篇文章:ping容易忽略的10点用法和排查问题技巧。

(2) traceroute

traceroute 是类 Linux 系统自带的工具,Windows 上类似的工具是 tracert,两者有些许不同,tracert 默认使用 ICMP 报文探测,而 traceroute 默认使用 UDP,但是也可以使用 TCP/ICMP 三种报文探测。

traceroute 利用 ICMP 差错报文,主要用来确定这几件事:

  • 确定通信双方路径上经过的路由器设备
  • 确定 UDP 包是否成功达到目的地
  • 发现路径 MTU

确定通信双方路径上经过的路由器设备 。就是利用上面提到的超时类型的 ICMP 报文来实现。traceroute 向目的地发送 IP 包,刚开始的时候,将 TTL 设置为 1,当经过第一个路由器时,TTL -1 = 0 引发超时错误,第一个路由器回复 ICMP 超时报文,源主机就可以知道路径第一个路由器的信息,随后 TTL 被设置为 2、3、4, ...,直到到达目的地,这样,沿途每个路由器都会向源主机回复 ICMP 超时报文,traceroute 就可以拿到所有的路由器信息了。

不过这里要 注意 ,并不是所有路由器都会返回 ICMP 报文,因为出于安全性考虑,大多数防火墙以及启用了防火墙功能的路由器都默认配置为不返回任何 ICMP 报文,管理员也会主动配置,所以这时使用 traceroute 就不一定能拿到所有路由器信息了。

确定 UDP 包是否成功达到目的地 。使用上面的方法能拿到路由器信息,但并不能确定发的包是否到达目的地。traceroute 通过发送 UDP 包来解决了这个问题,因为 UDP 包的可用端口号范围 <3000,所以就可以在发送 UDP 包的时候填入一个 >3000 的端口号,这样,如果当包确实到达了目的地,由于端口不匹配,就会返回一个端口不可达的 ICMP 报文,源主机就可以确定包确实到了目的地了。

发现路径 MTU 。这块在上面讲 “需要分片但设置了不分片位” 类型报文的时候已经讲过,traceroute 就是利用这种类型报文来逐一地确认传输路径上各个路由器之间的 MTU 值。

关于 traceroute 命令的使用案例可以参考这篇文章:排查网络问题,请务必掌握这款工具。

(3) MTR

MTR 全称 my traceroute,相对以上两个其实是更好的网络排障工具,只是用的人不多,导致它不太出名。之所以说它好,是因为它结合了 ping 、nslookup、traceroute 三款工具的特性。

关于 MTR 的安装和使用分析详见这篇文章:这款网络排查工具,堪称神器!

(4) tcptraceroute

这块工具从名称就可以看出,是基于 TCP 的 traceroute,也就是它使用 TCP 包(具体是 TCP 的 SYN 包)来进行网络探测,而不是 ICMP 包。

从上面我们已经知道,traceroute -T 就是使用 TCP 包进行探测,所以 tcptraceroute 其实等效于 traceroute -T 。

使用 TCP 包进行探测的原因,主要是因为现代广泛使用的防火墙,出于安全的考虑,都会拦截 UDP 包和 ICMP 包,而通常不会拦截 TCP SYN 包。所以使用 TCP 包探测能够通过大多数的网络设备,使探测结果更加精确。

6. ICMP 有哪些内核参数

总结了下面一幅图,其中比较常用的是 net.ipv4.icmp_echo_ignore_all,这是禁 ping 的一个参数,禁 ping 有几种方法,可以参考这篇文章:Linux禁止ping以及开启ping的方法。

其他的参数大家有兴趣也可以看看,遇到不懂的直接查这个图即可。

7. ICMP 的问题

ICMP 协议是 IP 协议的助手,能够为 IP 协议提供相关的故障诊断和控制信息,但 ICMP 仍然不能为 IP 提供可靠性,最常见的丢包(路由器缓冲区溢出)并不会触发任何的 ICMP 信息,只能由其他协议如 TCP 来处理这种情况。

此外,正因为 ICMP 能够查询网络设备相关的配置信息,并且使用简单,黑客们都比较青睐使用 ICMP 报文来构建攻击报文。所以很多的网络设备都会用防火墙来阻止 ICMP 报文,这让很多诊断工具,比如上面介绍的几种,都很难发挥用武之地。

常见的 ICMP 攻击是 ICMP 泛洪攻击,这是一种 DDoS 攻击。简单说就是攻击者向一个子网的的广播地址发送多个 ICMP echo 包,包的源地址伪装成他想要攻击的目的主机的 IP,然后该子网的所有主机的 ICMP reply 包都会送到被攻击主机,该主机瞬时收到大量的 ICMP 回复包,消耗大量资源,来不及处理,便会进入瘫痪或无法提供正常服务。

解决 ICMP 泛洪攻击最简单的方法就是禁 ping 了。只要禁 ping,不管黑客有多少肉机,他都无可奈何了。

 

责任编辑:赵宁宁 来源: Linux云计算网络
相关推荐

2017-10-17 12:43:17

前端CSS布局

2017-05-15 12:58:00

编程javaapl

2021-08-27 10:14:22

机器学习工具手册人工智能

2018-09-12 09:34:11

ZooKeeper概念集群

2018-07-04 09:42:19

Docker概念容器

2020-11-02 10:50:21

爬虫Python网络

2024-01-03 16:28:46

WinDbg命令调试

2023-02-26 00:00:01

Spring数据库组件

2023-02-26 10:14:51

Spring第三方库

2019-11-12 13:16:37

GitHub代码开发者

2018-11-05 08:10:30

Netty架构模型

2017-12-15 10:00:46

前端框架Vue.js

2018-07-16 15:05:43

Redis内存数据库

2021-11-03 16:10:16

RedisJava内存

2020-04-14 10:50:47

FlutterGithub

2021-02-26 10:16:55

鸿蒙HarmonyOS应用开发

2021-06-09 07:56:51

JvmJVM面试题Java

2023-01-11 08:24:32

2019-05-27 08:09:43

WiFi无线信道上网

2017-06-26 10:18:43

点赞
收藏

51CTO技术栈公众号