• ICMP经常被认为是IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。
  • ICMP报文通常被IP层或更高层协议TCP或UDP使用。
  • 一些ICMP报文把差错报文返回给用户进程
 
ICMP报文是在IP数据报内部被传输的,如:

 

 
ICMP报文的类型

 

 

  • 所有报文的前4个字节都是一样
    • 8位类型+8位代码+16位校验和
    • 校验和
      • 和IP首部校验算法相同
      • 反向二进制求和
  • 剩余
    • 类型
      • 15个不同类型字段
      • 描述特定类型的ICMP报文
    • 代码
      • 使用代码字段的值来进一步描述不同的条件
 
ping--类型8,代码0-->请求回显
 
回显应答<--类型0,代码0--ping
 
不同类型由类型字段和代码字段共同决定;

 

分类
  • 查询报文
    • 查询报文如果出错会产生一个差错报文
  • 差错报文
    • 有时需要做特殊处理
    • 永远不会产生一个差错报文
      • 差错报文会继续产生差错报文,形成死循环
 
不会产生ICMP差错报文:
  • ICMP差错报文(但是, ICMP查询报文可能会产生 ICMP差错报文)。
  • 目的地址是广播地址(见图3 - 9)或多播地址(D类地址,见图1 - 5)的IP数据报。
  • 作为链路层广播的数据报
  • 不是IP分片的第一片(将在11 . 5节介绍分片)。
  • 源地址不是单个主机的数据报。这就是说,源地址不能为零地址、环回地址、广播地
    址或多播地址。
 
ICMP地址掩码请求与应答

 
ICMP地址掩码请求用于无盘系统在引导过程中获取自己的子网掩码
 
ICMP地址掩码请求和应答报文的格式如图:

 

ICMP报文中的标识符和序列号字段由发送端任意选择设定,这些值在应答中将被返回。
这样,发送端就可以把应答与请求进行匹配。
 
ICMP时间戳请求与应答

  • ICMP时间戳请求允许系统向另一个系统查询当前的时间
    • 返回的建议值是自午夜开始计算的毫秒数
    • 协调的统一时间(Coordinated Universal Time, UTC)
  • ICMP报文的好处是它提供了毫秒级的分辨率
    • 如某些Unix系统提供的rdate命令只能提供秒级的分辨率。
  • 缺陷
    • 返回的时间是从午夜开始计算的,因此调用者必须通过其他方法获知当时的日期

 

 
 
请求端填写发起时间戳,然后发送报文。应答系统收到请求报文时填写接收时间戳,在
发送应答时填写传送时间戳。但是,实际上,大多数的实现把后面两个字段都设成相同的值
(提供三个字段的原因是可以让发送方分别计算发送请求的时间和发送应答的时间)。
 
 
请求与应答报文:
  • ICMP报文中都有标识符和序列号。
  • 发送端应用程序在标识字段内存入一个唯一的数值,以区别于其他进程的应答。
  • 序列号字段使得客户程序可以在区分哪个请求对应哪个应答。
 
ICMP端口不可达差错

ICMP差错报文, 端口不可达报文,它是 ICMP目的不可到达报文中的一种,以此来看一看ICMP差错报文中所附加的信息。
 
用例:
  • UDP
    • UDP的规则之一是,如果收到一份UDP数据报而目的端口与某个正在使用的进程不相符,
      那么UDP返回一个ICMP不可达报文。
  • TFTP
    • 可以用 TFTP来强制生成一个端口不可达报文
 
对于 TFTP服务器来说, UDP的公共端口号是 69。但是大多数的 TFTP客户程序允许用
connect命令来指定一个不同的端口号。这里,我们就用它来指定 8888端口:

 

connect命令首先指定要连接的主机名及其端口号,接着用 get命令来取文件。敲入 get
命令后,一份 UDP数据报就发送到主机 svr4上的8 8 8 8端口。 tcpdump命令引起的报文交换结果:

 

过程分析:
  • 在UDP数据报送到 svr4之前,要先发送一份ARP请求来确定它的硬件地址(第1行)。
  • 接着返回ARP应答(第2行)
  • 然后才发送UDP数据报(第3行)
  • 一个ICMP端口不可达差错是立刻返回的(第 4行)
  • 但是, TFTP客户程序看上去似乎忽略了这个ICMP报文,而在5秒钟之后又发送了另一份 UDP数据报(第 5行)。
  • 在客户程序放弃之前重发了三次
  • 跟在每个 UDP后面的数字 20指的是UDP数据报中的数据长度。
 
注意:
  • 在tcpdump的输出中保留ARP请求和应答是为了提醒我们,这些报文交换可能在第一个IP数据报从一个主机发送到另一个主机之前是必需的
  • ICMP报文是在主机之间交换的,而不用目的端口号,而每个20字节的UDP数据报
    则是从一个特定端口2924发送到另一个特定端口8888。
 
 
UDP端口不可达中ICMP报文:
 

 

ICMP规则:
  • ICMP差错报文必须包含生成该差错报文的数据报IP首部(包含任何选项)以及后续8个字节(如UDP首部)
    • 这个信息对于 ICMP差错的接收方来说是必要的,可以更多地了解导致差错的原因。
    • 这是因为TCP和UDP都在它们的首部前8个字节中存入源端口号和目的端口号
  • 尽管ICMP规则允许系统返回多于8个字节的产生差错的IP数据报中的数据,但一般只返回8个字节。
 
ICMP不可达报文的一般格式:

 

IP首部:得到源地址和目的地址
前8个字节:源端口号和目的端口号
 
tcpdump输出时间序列图:

 

当ICMP差错报文返回时,为啥应用程序(tftp)一直重发?
  • 网络编程中,BSD系统不把socket接收到的ICMP报文中的UDP数据通知TFTP
  • 即应用程序根本就不知道ICMP差错报文存在?
 
 
ICMP报文的处理

icmp覆盖范围很广,从致命差错到信息差错。
因此应用程序对每个ICMP报文的处理都是不一样的。

 

ping程序

该程序发送一份 ICMP回显请求报文给主机,并等待返回 ICMP回显应答.
回显
  • 类型:8
  • 代码:0
 
ping作用:
  • 可以作为诊断工具查看网络问题
  • 还能测出往返时间,
  • 检测IP记录路由和时间戳选项
 
ICMP回显请求和回显应答报文

 

 
Unix系统在实现ping程序时是把 ICMP报文中的标识符字段置成发送进程的id号。
序列号从0开始,每发送一次新的回显请求就加 1。
 
ping输出
zane@zane-V:~$ ping zane-V
PING zane-V (127.0.1.1) 56(84) bytes of data.
64 bytes from zane-V (127.0.1.1): icmp_seq=1 ttl=64 time=0.022 ms
64 bytes from zane-V (127.0.1.1): icmp_seq=2 ttl=64 time=0.023 ms
64 bytes from zane-V (127.0.1.1): icmp_seq=3 ttl=64 time=0.023 ms
64 bytes from zane-V (127.0.1.1): icmp_seq=4 ttl=64 time=0.023 ms
64 bytes from zane-V (127.0.1.1): icmp_seq=5 ttl=64 time=0.025 ms
64 bytes from zane-V (127.0.1.1): icmp_seq=6 ttl=64 time=0.025 m

 

当返回ICMP回显应答时,打印出 序列号 和 TTL(位于IP首部中的生存时间字段),并计算往返时间;
 
IP记录路由选项
  • 提供-R选项,以提供记录路由的功能。
    • 会频繁使用默认路由
过程:
  • 使得ping程序在发送出去的IP数据报中设置IP的RR选项(该IP数据报包含ICMP回显请求报文)。
  • 每个处理该数据报的路由器都把它的IP地址放入选项字段中
  • 当数据报到达目的端时,IP地址清单应该复制到ICMP回显应答中,
  • 这样返回途中所经过的路由器地址也被加入清单中。
  • 当 ping程序收到回显应答时,它就打印出这份IP地址清单
 
问题:ip首部中只有有限的空间来存放IP地址。
答:路由的IP地址不是放在IP报文首部中,而是放在IP报文中的选项字段中
 
我们从图 3 - 1可以看到,IP首部中的首部长度字段只有 4 bit,因此整个IP首部最长只能包括 15个32 bit长的字(即60个字
节)。由于 IP首部固定长度为 20字节, RR选项用去 3个字节(下面我们再讨论),这样只剩下37个字节(60-20-3)来存放
IP地址清单,也就是说只能存放9个IP地址。
 
[root@zane1 ~]# ping -R 192.168.56.12
PING 192.168.56.12 (192.168.56.12) 56(124) bytes of data.
64 bytes from 192.168.56.12: icmp_seq=1 ttl=64 time=1.19 ms
RR:     192.168.56.10
        192.168.56.12
        192.168.56.12
        192.168.56.10
 
64 bytes from 192.168.56.12: icmp_seq=2 ttl=64 time=0.250 ms    (same route)
64 bytes from 192.168.56.12: icmp_seq=3 ttl=64 time=0.190 ms    (same route)
64 bytes from 192.168.56.12: icmp_seq=4 ttl=64 time=0.248 ms    (same route)
64 bytes from 192.168.56.12: icmp_seq=5 ttl=64 time=0.208 ms    (same route)
64 bytes from 192.168.56.12: icmp_seq=6 ttl=64 time=0.331 ms    (same route)
64 bytes from 192.168.56.12: icmp_seq=7 ttl=64 time=0.274 ms    (same route)
64 bytes from 192.168.56.12: icmp_seq=8 ttl=64 time=0.250 ms    (same route)

 

 
  • ping程序是对两个 TCP/IP系统连通性进行测试的基本工具。
  • 它只利用ICMP回显请求和回显应答报文,而不用经过传输层(TCP/UDP)
  • Ping服务器一般在内核中实现 ICMP的功能。
 
 
Traceroute程序

 
  • Traceroute程序可以让我们看到 IP数据报从一台主机传到另一台主机所经过的路由。
  • Traceroute程序还可以让我们使用 IP源路由选项
 
Traceroute程序使用
  • ICMP报文
  • IP首部中的TTL字段(生存周期)。
 
原理:
当路由器收到一份IP数据报,如果其TTL字段是0或1,则路由器不转发该数据报
相反,路由器将该数据报丢弃,并给信源机发一份ICMP“超时”信息。
Traceroute程序的关键在于包含这份 ICM 信息的IP报文的信源地址是该路由器的IP地址
 
Traceroute 操作过程
  • 它发送一份 TTL字段为1的IP数据报给目的主机
    • 处理这份数据报的第一个路由器将 TTL值减1,丢弃该数据报并发回一份超时ICMP报文
    • 这样就得到了该路径中的第一个路由器的地址
  • 然后 Traceroute程序发送一份TTL值为2的数据报,这样我们就可以得到第二个路由器的地址。
  • 继续这个过程直至该数据报到达目的主机。
    • 但是目的主机哪怕接收到TTL值为1的IP数据报,也不会丢弃该数据报并产生一份超时ICMP报文,这是因为数据报已经到达其最终目的地。
    • 那么我们该如何判断是否已经到达目的主机了呢?
      • Traceroute程序发送一份UDP数据报给目的主机,但它选择一个不可能的值作为UDP端口号(大于 30 000),使目的主机的任何一个应用程序都不可能使用该端口。
      • 因为,当该数据报到达时,将使目的主机的 UDP模块产生一份“端口不可达”错误的 ICMP报文。
  • Traceroute程序所要做的就是区分接收到的ICMP报文是超时还是端口不可达,以判断什么时候结束。
 
Traceroute输出
[root@zane1 ~]# traceroute www.baidu.com
traceroute to www.baidu.com (180.97.33.108), 30 hops max, 60 byte packets
 1  10.0.2.2 (10.0.2.2)  0.135 ms  0.054 ms  0.050 ms
 2  10.0.2.2 (10.0.2.2)  1.918 ms  1.833 ms  1.766 ms

 

  • 输出第1个无标号的行给出了
    • 主机名及其IP地址
    • TTL字段最大值
    • 发送的数据报大小
  • 输出的后面两行:
    • TTL值+主机名或路由器名称+主机/路由器IP
    • 对于每个TTL值发送3分数据报,打印往返时间
 
ICMP超时报文
类型:11

 

注意事项
  • 并不能保证现在的路由也是将来所要采用的路由,甚至两份连续的 IP数据报都可能采用不同的路由。
  • 第二,不能保证 ICMP报文的路由与traceroute程序发送的UDP数据报采用同一路由。
  • 第三,返回的 ICMP报文中的信源 IP地址是UDP数据报到达的路由器接口的 IP地址。
 
 
posted on 2017-08-03 11:10  Aiapple  阅读(472)  评论(0编辑  收藏  举报