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 使用差错类型报文
5.1 ping
ping 使用了查询报文中的请求报文(类型为 8)和应答报文(类型为 0),主要查询某个网络节点的连通性,如果出现网络不连通的情况,具体是什么问题,会在应答报文中附带相关的差错信息予以告知。比如网络不可达(Network Unreacheable)、主机不可达(Host Unreachable)等等,然后用户就可以根据这些信息来分析具体是哪个环节出现问题。
那么比较完整的流程是:
(1) 向目的服务器发送回显请求
首先,向目的服务器上执行ping命令,主机会构建一个 ICMP 回显请求消息数据包(类型是8,代码是0),在这个回显请求数据包中,除了类型和代码字段,还被追加了标识符和序号字段。标识符和序号字段分别是 16 位的字段。ping 命令在发送回显请求数据包时,会将进程号填写在标识符里。对于序号,每送出一个数据包数值就增加1。而且,回显请求的选项数据部分用来装任意数据。这个任意数据用来调整 ping 的交互数据包的大小。如下图在 192.168.1.10上执行 ping 192.168.1.1的命令:
ping 命令执行的时候,他的进程号是 43991:
通过 WireShark 抓包可以看出,上图中的 192.168.1.10 主机会构建一个 ICMP 回显请求消息数据包。
上图中我们可以看到 ICMP 的 Type(协议类型)是 8,Code(代码)是 0,Identifier(ping进程号) 是 43991,同时还有 Sequence Number 发送序号11,以及发送时间 。
(2) 目的服务器发送回显应答
当192.168.1.10送到 回显请求数据包后,192.168.1.1就会向发送方192.168.1.10发送回显应答(类型是0,代码是0),这个 ICMP 回显应答数据包在 IP 层来看,与被送来的回显请求数据包基本上一样。不同的只有源、目标 IP 地址字段被交换了,Type类型字段里填入了表示回显应答的0。通过 WireShark 抓包可以看出,如下图:
(3) 源服务器显示相关数据
如果源服务器可以接收到回显应答数据包,那我们就认为192.168.1.1是正常工作着的。进一步,记住发送回显请求数据包的时间,与接收到回显应答数据包的时间差,就能计算出数据包一去一回所需要的时间。这个时候ping命令就会将目的服务器的 IP 地址,数据大小,往返花费的时间打印到屏幕上。如下图:
可以看到,通过各层协议栈的层层封装和解封装,一个 ping 包从一台主机发送到另一台主机,包括请求包和应答包。其中,如果目标 MAC 地址未知的话,需要先发出 ARP 请求拿到,然后再进行封装。
5.2 traceroute
traceroute是类 Linux 系统自带的工具,Windows 上类似的工具是 tracert,两者有些许不同,tracert 默认使用 ICMP 报文探测,而 traceroute 默认使用 UDP,但是也可以使用 TCP/ICMP 三种报文探测。
traceroute 利用 ICMP 差错报文,主要用来确定这几件事:
- 确定通信双方路径上经过的路由器设备
- 确定 UDP 包是否成功达到目的地
- 发现路径 MTU
其工作原理:
我们通过执行 traceroute 192.168.1.1,来分析一下他的原理,它的原理就是利用 IP 包的 TTL 从 1 开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的方法。
**(1)**首先 traceroute 会将 IP 包的 TTL 设置 为 1,然后发送 UDP 包,他会填入一个端口号作为 UDP 目标端口号(默认是:33434-33534)。
**(2)**当目的主机收到 UDP 包后,会返回 ICMP 差错报文消息(类型 3,代码 3)。参照上面的表,该错报文类型是端口不可达,说明发送方发出的 UDP 包到达了目的主机。
这样的过程,traceroute 就可以拿到了所有的路由器 IP,这样子就可以看到从源主机到目的主机过程中的所有路由信息。
当然实际情况有的路由器禁用 ICMP ,那么他就根本不会返回这个 ICMP 差错报文,所以是看不到中间经过的路由IP的。
Tips:traceroute 在类 Unix/Linux 系统中默认使用的是 UDP 协议,也可以通过参数修改为使用 ICMP 协议;Windows 操作系统中只使用 ICMP 协议。
说了这么多,我们还是直接来看一张图吧,基本可以描述清楚 traceroute 的整个过程。如下图:
5.3 MTR
MTR 全称 my traceroute,相对以上两个其实是更好的网络排障工具,只是用的人不多,导致它不太出名。之所以说它好,是因为它结合了 ping 、nslookup、traceroute 三款工具的特性。
5.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,不管黑客有多少肉机,他都无可奈何了。
8. ICMP攻击及欺骗技术
所谓:"知己知彼,百战不怠",要学会防范就必须知道攻击是怎样的。使用ICMP攻击的原理实际上就是通过Ping大量的数据包使得计算机的CPU使用率居高不下而崩溃,一般情况下黑客通常在一个时段内连续向计算机发出大量请求而导致CPU占用率太高而死机。
基于ICMP的攻击可以分为两大类:
一是ICMP攻击导致拒绝服务(DoS);另外一个是基于重定向(redirect)的路由欺骗技术。 服务拒绝攻击是最容易实施的攻击行为,目前,基于ICMP的攻击绝大部分都可以归类为拒绝服务攻击,其又可以分成3个小类:
8.1 针对带宽的DoS攻击
针对带宽的DoS攻击,主要是利用无用的数据来耗尽网络带宽。Pingflood、pong、echok、flushot、fraggle 和 bloop是常用的ICMP攻击工具。通过高速发送大量的ICMP Echo Reply数据包,目标网络的带宽瞬间就会被耗尽,阻止合法的数据通过网络。ICMP Echo Reply数据包具有较高的优先级,在一般情况下,网络总是允许内部主机使用PING命令。
这种攻击仅限于攻击网络带宽,单个攻击者就能发起这种攻击。更厉害的攻击形式,如smurf和papa-smurf,可以使整个子网内的主机对目标主机进行攻击,从而扩大ICMP流量。使用适当的路由过滤规则可以部分防止此类攻击,如果完全防止这种攻击,就需要使用基于状态检测的防火墙。
8.2 针对连接的DoS攻击
针对连接的DoS攻击,可以终止现有的网络连接。针对网络连接的DoS攻击会影响所有的IP设备,因为它使用了合法的ICMP消息。Nuke通过发送一个伪造的ICMP Destination Unreachable或Redirect消息来终止合法的网络连接。更具恶意的攻击,如puke和smack,会给某一个范围内的端口发送大量的数据包,毁掉大量的网络连接,同时还会消耗受害主机CPU的时钟周期。
还有一些攻击使用ICMP Source Quench消息,导致网络流量变慢,甚至停止。Redirect和Router Announcement消息被利用来强制受害主机使用一个并不存在的路由器,或者把数据包路由到攻击者的机器,进行攻击。针对连接的DoS攻击不能通过打补丁的方式加以解决,通过过滤适当的ICMP消息类型,一般防火墙可以阻止此类攻击。
8.3 基于重定向(redirect)的路由欺骗技术
首先我们应该知道,微软的Windows98和NT系统都保持着一张已知的路由器列表,列表中位于第一项的路由器是默认路由器,如果默认路由器关闭,则位于列表第二项的路由器成为缺省路由器。缺省路由向发送者报告另一条到特定主机的更短路由,就是ICMP重定向。
攻击者可利用ICMP重定向报文破坏路由,并以此增强其窃听能力。除了路由器,主机必须服从ICMP重定向。如果一台机器想网络中的另一台机器发送了一个ICMP重定向消息,这就可能引起其他机器具有一张无效的路由表。如果一台机器伪装成路由器截获所有到某些目标网络或全部目标网络的IP数据包,这样就形成了窃听。通过ICMP技术还可以抵达防火墙后的机器进行攻击和窃听。
据笔者观察,目前所有基于ICMP路由欺骗的技术都是停留在理论上的论述, 没有找到相关的具体攻击实例和原程序
8.4预防攻击
8.4.1 配置防火墙以预防攻击
一旦选择了合适的防火墙,用户应该配置一个合理的安全策略。一般除了出站的ICMP Echo Request、出站的ICMP Source Quench、进站的TTL Exceeded和进站的ICMP Destination Unreachable之外,所有的ICMP消息类型都应该被阻止。
现在许多防火墙在默认情况下都启用了ICMP过滤的功能。如果没有启用,只要选中"防御ICMP攻击"、"防止别人用ping命令探测"就可以了。
8.4.2 配置系统自带的默认防火墙以预防攻击
虽然很多防火墙可以对PING进行过滤,但对于没有安装防火墙时我们如何有效的防范ICMP攻击呢?先面我们介绍一下配置一下系统自带的默认防火墙的预防攻击的方法。方法如下:
**第一步:**打开在电脑的桌面,右键点击"网上邻居→属性→本地连接→属性→Internet协议(TCP/IP)→属性→高级→选项-TCP/IP筛选-属性"。
第二步:"TCP/IP筛选"窗口中,点击选中"启用TCP/IP筛选(所有适配器)"。然后分别在"TCP端口、UDP端口和IP协议"的添加框上,点击"只允许",后按添加按钮,然后在跳出的对话框输入端口,通常我们用来上网的端口是:80、8080,而邮件服务器的端口是:25、110,FTP的端口是20、21,同样将UDP端口和IP协议相关进行添加。
**第三步:**打开"控制面板→管理工具→本地安全策略",然后右击"IP安全策略,在本地机器"选"管理IP筛选器和IP筛选器操作",在管理IP筛选器和IP筛选器操作列表中添加一个新的过滤规则,名称输入"防止ICMP攻击",然后按添加,在源地址选任何IP地址,目标地址选我的IP地址,协议类型为ICMP,设置完毕。
**第四步:**在"管理筛选器操作",取消选中"使用添加向导",添加,在常规中输入名字"Deny的操作",安全措施为"阻止"。这样我们就有了一个关注所有进入ICMP报文的过滤策略和丢弃所有报文的过滤操作了。
**第五步:**点击"IP安全策略,在本地机器",选择"创建IP安全策略-下一步-输入名称为ICMP过滤器",通过增加过滤规则向导,把刚刚定义的"防止ICMP攻击"过滤策略指定给ICMP过滤器,然后选择刚刚定义"Deny的操作",然后右击"防止ICMP攻击"并启用。
8.4.3通过对注册表的修改以预防攻击
通过对注册表的修改我们可以使ICMP更安全。修改注册表主要有两种方式: