TCP/IP 笔记 - ICMPv4和ICMPv6 : Internet控制报文协议

时间:2024-02-20 18:46:17

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

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

ICMP报文

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

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

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

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

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

ICMPv4报文类型使用的代码

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

ICMPv6报文类型使用的代码

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

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

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

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

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

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

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

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

查询/消息类报文

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

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

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

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

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

地址数给出报文中路由地址块的个数,每个块包含一个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。

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

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

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

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

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

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

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

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

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

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

邻居请求/通告 

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

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

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

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

邻居不可达检测

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

五个状态: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方法如图:

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

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

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

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

ICMPv6邻居发现选项

选项列表:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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官方文档