当前位置:   article > 正文

Internet 控制报文协议 —— ICMPv4 和 ICMPv6 详解

Internet 控制报文协议 —— ICMPv4 和 ICMPv6 详解

ICMP 是一种面向无连接的协议,负责传递可能需要注意的差错和控制报文,差错指示通信网络是否存在错误 (如目的主机无法到达、IP 路由器无法正常传输数据包等。注意,路由器缓冲区溢出导致的丢包不包括在 ICMP 响应范围内,在 TCP 负责范围)。

ICMPv4 和 ICMPv6 分别指用于 IPv4 和 IPv6 的 ICMP 版本。在 IPv4 中,协议字段值为 1 表示该报文携带了 ICMPv4;在 IPv6 中,ICMPv6 报文位于扩展头部里,ICMPv6 扩展头部上一个头部包含了值为 58 的 “下一个头部” 字段。

ICMP 报文

所有 ICMP 报文都以 8 位的类型 (Type) 和代码 (Code) 字段开始,其后跟随的 16 位校验和 (Checksum) 字段涵盖整个报文。
img

类型字段用于确定特定的报文,ICMPv4 和 ICMPv6 的该字段值并不相同;代码字段进一步肯定报文的含义,ICMPv4 和 ICMPv6 的该字段值并不相同;校验和字段用于确定报文信息的正确性。

ICMP 报文可分为两类:有关 IP 数据报传递的 ICMP 报文 (差错报文) 和信息采集和配置的 ICMP 报文 (查询或者信息类报文)。

由类型字段决定的 ICMPv4 报文类型

img

(*) 标记的类型是最常见的,(+) 标记的可能包含 [RFC4884] 扩展对象,E 表示差错报文,I 表示查询 / 信息类报文。

ICMPv4 报文类型使用的代码
img

由类型字段决定的 ICMPv6 报文类型:差错报文的类型从 0-127,信息类报文类型为 128-255
img

ICMPv6 报文类型使用的代码
img

一般来说,对于传入的 ICMP 信息,查询或信息类将被操作系统自动处理,差错类报文传递给用户进程或传输层协议 (除去重定向报文和目的地不可达,前者导致主机路由表的自动更新,后者用于路径 MTU 发现机制)。

传入的 ICMPv6 报文处理规则如下:

  1. 未知的 ICMPv6 差错报文必须传递给上层产生差错报文的进程;

  2. 未知的 ICMPv6 信息类报文被丢弃;

  3. ICMPv6 差错报文将会尽可能多地包含到差错的原始 (违规) IPv6 报文,最终的差错报文大小不能超过最小的 IPv6 MTU (1280 字节);

  4. 在处理 ICMPv6 差错报文时,需要提取原始或违规数据包中的上层协议类型,用于选择适当的上层进程;

  5. 存在处理差错的特殊规则;

  6. IPv6 节点必须限制它发生 ICMPv6 差错报文的速率。

查询 / 消息类报文

由于某些 ICMP 的功能已经被其他特殊目的的协议代替,保存下来的广泛使用的 ICMP 查询 / 信息类报文是回显请求 / 应答报文 (常用的 “ping”),以及路由器发现报文。

回显请求 / 应答相对简单,收到回显请求之后,ICMP 的实现要求将任何收到的数据返回给发送者。其报文结构如下:

img

发送主机利用标识符来分离返回的应答 (如多个 ping 同时允许的时候,用于区分返回的应答)。

当一个 ping 实例运行时,序列号从 0 开始,每发送一个回显请求则加 1.

路由器发现则较为复杂,也就是与移动 IP 一起使用的那个。其主要目的是让一台主机学习到它所在的本地子网中所有路由器,从而选择一台作为默认路由器,也用于发现那些愿意充当移动 IP 代理的路由器。

img

地址数给出报文中路由地址块的个数,每个块包含一个 IPv4 地址及相应的优先水平 (优先水平是一个 32 位的有符号二进制补码整数,其值越大代表优先级越高。默认的优先水平是 0,特殊值 0x80000000 表示这个地址不应该用作有效的默认路由);

地址条目大小给出每个块的 32 位字数;

生命周期给出地址列表被认为有效的秒数;

序列号字段给出了自从初始化之后代理产生的这种扩展的个数;

注册字段给出了发送 代理愿意接受 MIPv4 注册的最大秒数 (0xFFFF 表示无穷大);

那些字母的含义:R (为 MIP 服务所需的注册)、B (代理太忙无法接受注册)、H (代理愿意充当本地代理)、F (代理愿意充当外地代理)、M (支持最小封装格式)、G (代理支持封装数据报的 GRE 隧道)、r (保留零)、T (支持反向隧道)、U (支持 UDP 的隧道)、X (支持撤销注册)、I (外地代理支持区域注册)。

差错报文

ICMP 差错报文不会对以下报文进行响应:

  1. 另一个 ICMP 差错报文;

  2. 头部损坏的数据报;

  3. IP 层的广播 / 组播数据报;

  4. 封装在链路层广播或者组播帧中的数据报;

  5. 无效或者网络为零的源地址数据报;

  6. 或除第一个之外的其他分片。

限制生成 ICMP 差错报文的原因是限制生成广播风暴。在 [RFC4443] 中,推荐采用令牌桶 (token bucket) 方法来限制 ICMP 报文速率。过程如下 (一令牌大小为一字节):

  1. 假设 “桶” 里保存了最大数量 “B” 的 “令牌”,如果 “令牌” 到达时 “桶” 满了,则 “令牌” 被丢弃;

  2. 当一个 N 字节的数据包达到,如果 “桶” 中多于 N 个 “令牌”,则删除 N 个 “令牌”,且数据包被发送到网络;如果 “桶” 中少于 N 个 “令牌”,则不删除 “令牌”,且认为这个数据包在流量限制之外。

ICMPv4 到 ICMPv6 的转换只有回显请求和回显应答报文被转换,为了执行这个转换,类型值 (8 和 0) 分别被转换到值 128 和 129。在转换之后,计算并应用 ICMPv6 的伪头部校验和。当转换 ICMPv4 差错报文时,只有下面的差错报文被转换了:目的不可达 (类型 3),超时 (类型 11),参数问题 (类型 12)。

ICMPv6 到 ICMPv4 的转换回显请求 (类型 128) 和回显应答 (类型 129) 报文被分别转换到 ICMPv4 回显请求 (类型 8) 和回显应答 (类型 0),更新校验和以体现类型值变化和缺少为头部计算,其他信息类报文将被丢弃。

IPv6 邻居发现

IPv6 中的邻居发现协议 (NDP 或者 ND) 中两个主要部分是:邻居请求 / 通告 (NS/NR),在网络和链路层地址之间提供类似于 ARP 的映射功能;路由器的请求 / 通告 (RS/RA),提供的功能包括路由器发现、移动 IP 代理发现、重定向,以及对一些自动配置的支持。

ND 报文就是 ICMPv6 报文,只是发送时 IPv6 的跳数限制字段值被设置为 255。接收者通过验证进来的 ND 报文有这个值,以防止被非本链路上的发送者尝试发送假冒本地 ICMPv6 欺骗。

路由器请求 / 通告

RS 报文结构很简单,用于请求链路上的路由器发送 RA 报文,RS 报文被发送到所有路由器组播地址 ff02::2。
img

RA 报文结构略为复杂,由路由器发送到所有节点的组播地址 ff02::1,或者发送到请求主机的单播地址 (为响应某个请求)。
img

当前跳数限制字段指定主机发送 IPv6 数据报的默认跳数限制;

M (托管) 字段表明本地 IPv6 地址分配是由有状态的配置来处理的,主机应避免使用无状态的自动配置;

O (其他) 字段标识其他有状态的信息使用一个有状态的配置机制;

H (本地代理) 字段标识发送路由器愿意充当一个移动 IPv6 节点的本地代理;

Pref (优先级) 字段给出将报文发送者作为一个默认路由器来使用的优先级层次 (01,高;00,中,默认;11,低;10:保留,未使用);

P (代理) 标志,当和实验性质的 ND 代理工具配合使用时被设置,为 IPv6 提供一个类似代理 ARP 的功能;

路由器生命周期字段表示发送路由器可以作为默认下一跳的时间,以秒为单位,可为 0;

可达时间字段给出一个节点到达另一个节点所需的毫秒数;

重传计时器字段规定主机延迟发送连续 ND 报文的时间,单位毫秒。

邻居请求 / 通告

ICMPv6 中的邻居请求 (NS) 报文有效的取代了 IPv4 中的 ARP 请求报文。其主要目的是将 IPv6 地址转换为链路层地址,也被用于检测附近的节点是否可达,它们是否可以双向到达。

NS 报文包含发送者想设法学习的链路层地址对应的 IPv6 地址,该报文可能包含源链路层地址选项,当请求是被发送到组播地址时,该选项必须包含在使用链路层寻址的网络中,对于单笔请求而言,该选项应该被包含。如果报文的发送者使用未指定的地址作为源地址,则不应该包括该选项。

img

NA 报文要么作为 NS 报文响应被发送;要么当一个节点的 IPv6 地址变化时被异步发送。要么被发送到请求节点的单播地址;要么当请求节点使用未指定的地址作为源地址时,被发送到所有节点的组播地址。

img

R 表示发送者是一个路由器;S 表示通告是为了响应一个请求;O 表示该报文的内容应覆盖其他缓存的地址映射;目标地址字段包含报文发送者的 IPv6 地址。

邻居不可达检测

邻居不可达检测用于管理邻居缓存,邻居缓存是个概念上的数据结构,用于保存 IPv6 到链路层地址的映射信息以及针对映射状态的信息。维护规程如下:

img

五个状态:INCOMPLETE,REACHABLE,STALE,DELAY,PROBE。

大致过程如下:

  1. 初始状态为 INCOMPLATE 或 STALE;

  2. 当一个 IPv6 节点有一个单播数据报需要发送到目的地时,它会检查其目标缓存,查看对应于目的地的条目是否存在;

  3. 如果存在且目的地是在链路上的,再查看邻居缓存,确定邻居状态是否为 REACHABLE;

  4. 如果是,使用直接交付方式发生数据报。如果没有邻居缓存条目,但目标似乎是在链路上,NUD 会进入 INCOMPLETE 状态,并发送一个 NS 报文;

  5. 成功收到一个请求 NA 报文便可以确定该节点是可大的,条目进入 REACHABLE 状态。

STALE 状态对应于目前还未确认的无效条目。当一个条目之前是 REACHABLE 状态,但已有一段时间未更新或者收到主动报文时,便进入 STALE。

DELAY 和 PROBE 是临时状态。DELAY 用于当一个数据包已经被发送,但 ND 目前尚无证据表明可能是到达的情况,该状态给上层协议一个机会来提供更多的证据。如果在 DELAY_FIRST_PROBE_TIME 后仍未收到证据,则进入 PROBE。

PROBE 状态 ND 会定期发送 NS 报文 (每 RetransTimer 毫秒,常数默认值 RETRANS_TIMER 等于 1000),如果在发送 MAX_UNICAST_SOLICIT (预设为 3) 个 NS 报文后还未收到任何证据,则删除条目。

安全邻居发现

安全邻居发现 (SEND) 是一组特殊的增强功能,旨在为 ND 报文提供额外的安全性。SEND 大致如下:

  1. 每个具备 SEND 的路由器有一个证书或者密码认证,它可以用来证明一台主机的身份;

  2. 每个主机配备一个信任锚 – 配置信息可以用来验证证书的有效性;

  3. 每个节点在配置它将使用的 IPv6 地址时,将会生成一个公钥 / 私钥对。

SEND 使用完全不同类型的称为密码生成地址 (CGA) 的 IPv6 地址。将一个 64 位的子网前缀和一个特殊构造的接口标识符相 “或”,便生成一个 IPv6 CGA。其中 CGA 接口标识符是通过 Hash1 安全散列函数计算出来的,它的输入是节点的公钥和一个特殊的 CGA 参数数据结构。

用来计算 CGA 的 SEND 方法如图:

img

伪随机序列字段初始化一个随机值,碰撞计数字段初始化为 0,扩展字段供之后使用。

Hash2 值必须有 (16*Sec) 个初始,Sec 是一个 3 位的参数,IANA 为 Sec 值维护一个注册表 [SI]。

SEND 定义了请求和通告报文用来帮助主机确定构成一个证书路径的证书,被主机用来验证路由器通告的真实性。

ND (邻居发现) 报文可能包含零个或多个选项,一些选项可以出现多次。所有的 ND 选项以 8 位类型和 8 位长度字段开始,支持长度可变的选项,最大到 255 字节。

img

ICMPv6 邻居发现选项

选项列表:
img

下面是各个选项的格式图:
img

源 / 目标链路层地址选项 (类型 1,2),源 (类型 1) 和目标 (类型 2) 链路层地址选项。长度字段值给出了整个选项的长度,包括地址,以 8 字节为单位。

img

前缀信息选项 (类型 3),前缀长度字段给出在配置中被视为有效的前缀字段中的位数 (多达 128 位);

L 位字段是 “在链路上” 的标志,并表示所提供的前缀是能用于在链路上判定的。如果没有设置,它对在链路上判定的使用没有做任何声明;

A 位字段就是 “自主自动配置” 标志,并表示所提供的前缀可用于自动配置;

R 位字段设置为 1 表示前缀字段包含发送路由器的整个全局 IPv6 地址,而不只是将前缀中的剩余位设置为 0 或者是它的本地链路地址;

有效生命周期和首选生命周期字段分别表示前缀能被用于在链路上判定和自动地址配置的秒数,0xFFFFFFFF 表示无穷大。

img

重定向头部选项 (类型 4),重定向头部选项被用于包含一份导致生成重定向报文的原始 (“违规”) IPv6 数据报。

img

MTU 选项 (类型 5),这个报文保留了 32 个比特位来存储 MTU,支持非常大的 MTU。此报文本来是用于诊断网络,但已被用于路径 MTU 发现。

img

通告间隔选项 (类型 7),通告间隔选项给出定期路由器通告报文间的时间。通告间隔字段定义了此报文到达网络上的发送者所发送的 RA 报文传输间的最大毫秒数。

img

本地代理信息选项 (类型 8),本地代理优先级字段是一个 16 位无符号证书,用于帮助移动节点预定通过 “本地代理地址发现应答” 报文提供给它的地址,值越大表示发送路由器作为一个本地代理的优先级程度越大,起始路由器的优先级被认为是 0 (最低)。本地代理生命周期字段也是 16 位无符号证书,指定该报文的发送者应考虑作为本地代理的秒数。

img

源和目标地址列表选项 (类型 9,10),这些被用来支持 IND,并提供了一个节点的 IPv6 地址的列表。只能包含用来发送报文的接口的地址。

img

CGA 选项 (类型 11),被用来和 SEND 一起携带 CGA 参数,这些参数是检验器执行 CGA 验证和签名验证所必需的。img

RSA 签名选项 (类型 12),被用来和 SEND 一起携带校验器能够使用的 RSA 签名,将它和 CGA 参数一起确定发送系统是否拥有与 CGA 公钥相关的私钥。密钥散列字段包含构建签名所使用的公钥经 SHA-1 散列后其结果的高 128 位;数字签名字段包含一个机遇下面这些值的标准化签名:SEND 的 CGA 报文类型标签,源 IP 和目的 IP 地址,ICMPv6 头部的开始 32 位字 (类型、代码和校验和字段),ND 协议的报文头和选项。

img

时间戳选项 (类型 13),选项给出了发送系统知晓的当天的当前时间,时间戳字段记录了自 1970 年 1 月 1 目 00:00UTC 以来的秒。

img

随机数选项 (类型 14),用于防范潜在的针对 SEND 的重放攻击,数值长度至少为 6 个长度。

img

信任锚选项 (类型 15),该选项包含一个证书路径的名称 (根),与 SEND 一起被主机用来验证 RA 报文的真实性。类型字段标识所使用的名称类型,当前定义的两个值:1,DERX.502 名称;2,全限定域名称 (FQDN)。名称字段采用名称类型字段定义的格式给出信任锚的名称。

img

证书选项 (类型 16),选项保存了和 SEND 一起使用的单独证书,用以提供证书路径。证书类型字段标识所使用的证书的类型。目前值定义了一个值:1,X.509v3 证书。

img

IP 地址 / 前缀选项 (类型 17),和 FMIPv6 报文一起使用。选项代码字段值表示哪种类型的地址被编码了:1. 旧的移交地址;2. 新的移交地址;3. 新访问路由器的 IPv6 地址;4. NAR 的前缀。前缀长度字段给出了 IPv6 地址字段中有效前导位个数。

img

链路层地址选项 (类型 19),和 FMIPv6 报文一起使用,选项代码字段值表示相关的链路层地址字段值是如何解释的:0. 通配符,即附近所有的 AP 都要求解析;1. 新的 AP 地址;2. 移动节点的地址;3. 新访问路由器的地址;4. RtSolPr/PrRtAdv 报文的源地址;5. 地址是当前路由器的;6. 对应到这个地址的 AP 没有可用的前缀信息;7. 编址的 AP 没有可用的快速切换。链路层地址字段包含由选项代码字段指定的地址。

img

邻居通告确认选项 (类型 20),选项代码字段值是 0,状态字段表示对主动邻居报文的处置。定义了如下值:1. 新移交地址 (NCoA) 是无效的 (执行地址配置);2. NCoA 是无效的 (采用 IP 地址选项中提供的 NCoA);3. NCoA 是无效的 (使用 NAR 第地址来代替 NCoA);4. 之前提供的移交地址 (PCoA)(没有发生绑定更新);128. 无法识别的链路层地址。

img

路由信息选项 (类型 24),表示通过一个特定路由器能够到达哪些不在链路上的前缀。前缀长度字段给出前缀字段中的有效先导位的个数。前缀字段标识个包含的前缀相关联的路由器相对于其他路由器的优先级,如果值为 2,则选项必须被忽略。路由生命周期字段给出了前缀被认为有效的秒数,所有值都为 1 表示无穷大。

img

递归 DNS 服务器选项 (类型 25),能够通过提供一个或多个 DNS 服务器的地址来增强无状态配置。生命周期字段给出了列表中的 DNS 服务器被认为是有效的时间长度,单位秒,所有值为 1 表示无穷大。

img

路由器通告扩展标志选项 (类型 26),长度字段目前被定义为 1,知道后续的位被分配。

img

切换密钥请求选项 (类型 27),它使用 SEND 保护信令信息的安全。填充长度字段给出在选项尾端用 0 填充的字节个数。算法类型字段表示用于计算认证者的算法。切换密钥加密公钥字段使用和 CGA 选项相同的格式解密了 FMIPv6 CGA 公钥。填充字段包含了值为 0 的字节以保证选项的长度是 9 字节的倍数。

img

切换密钥应答选项 (类型 28),它使用 SEND 保护信令信息的安全。密钥生命周期字段给出了切换密钥有效的秒数 (默认是 HK-LIFETIME 或者 43200s)。加密的切换密钥字段保存了一个对称密钥,是经过移动节点的切换密钥加密过的。加密格式是 RSAES-PKCS1-v1_5。

img

NDS 搜索列表选项 (类型 31),用来表示一个域名扩展到被添加到一台主机可能发起的 DNS 查询中。生命周期字段标识从报文被发送的时间开始,域名搜索列表被认为是有效的时长。域名搜索列表包含一个域名扩展的列表 (未压缩),作为从部分字符串构建的 GQDN 的默认形式。

ICMP 相关攻击

设计 ICMP 的攻击主要分为 3 类:泛洪、炸弹、信息泄露。泛洪指的是生成大量流量,导致针对一台或者多台计算机的有效 DoS 攻击。炸弹指的是发送经过特殊构造的报文,能导致 IP 或者 ICMP 的处理机制奔溃或终止。信息泄露本身并不会造成危害,但能够帮助其他攻击方法避免浪费时间或者被发现。

早期有一种称为 Smurf 的攻击,就是使用目的地址为广播地址的 ICMPv4,导致了大量计算机做出响应。

采用 ICMPv4 的回显请求 / 应答报文 (ping),有可能以这样一种方式来构建数据包分片,攻击如果涉及到 IPv4 头中的分片偏移字段,则将导致 IPv4 分片重组路由器的错误,称为泪滴攻击。

ICMP 目的不可达报文可造成现有连接 (如 TCP) 的拒绝服务,这些攻击有时被称为 Smack 或 Bloop 攻击。

还有一种涉及到修改 PTB 报文的攻击,可强制终端 TCP 运行时使用非常小的数据包,从而导致性能低下。

参考:

《TCP IP 详解卷 1:协议》

RFC 官方文档


注: 这样篇幅的文章,原作者至少写了几个小时,小半天时间没了

via:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/850658
推荐阅读
  

闽ICP备14008679号