胆囊息肉

注册

 

发新话题 回复该主题

TCPIP协议ICMP协议及其应用 [复制链接]

1#
白癜风效果 http://baidianfeng.39.net/a_yqyy/190322/6985778.html

1ICMP协议概述

ICMP(InternetControlMessageProtocol)协议是因特网控制报文协议,ICMP常被认为是网络层协议,它的报文存在于IP数据报的数据部分,如图。

ICMP协议栈

因为ICMP是基于IP数据报的,所以跟TCP不同的是,它是不需要指定端口的,更没有建立连接一说。而且,通常来说ICMP协议都是内核帮你实现的,系统自身就支持了,并不像TCP/HTTP等还要自己开个服务监听对应端口啥的。可能有人会有疑问了,既然没有端口来标识了,那我有时候开多个ping进程,这些响应消息是怎么对应到不同的ping进程的?这个就是ICMP报文里面的标识符的作用了。标识符会在响应中带回来,这样发送方就能根据标识符将请求和应答匹配了。在ping中,这个标识符就是进程ID。

ICMP报文有多种类型,如地址掩码请求和应答、时间戳请求和应答、请求回显和回显应答等。ICMP报文通用格式如下,不同类型的报文内容有所不同。ICMP协议在ping,traceroute等工具中有典型应用,下面都分析一下。

ICMP报文格式

2Ping原理分析

ping使用的是ICMP的请求回显/回显应答类型的报文,格式如下。它的内容包括标识符、序列号以及回显数据3部分,报文大小默认为64字节(header的8字节+body的56字节)。

ICMP回显报文格式

请求回显类型是8,回显应答类型是0,他们代码都是0,校验和是包内容根据算法生成用于校验数据完整性。

标识符在Linux/macOS中用的是进程ID。

序列号在Linux/macOS中是从0递增的,每个进程独立的。

回显数据包括发送ping请求的时间戳(在macOS占8字节,在Linux占16字节),以及一串填充数据,在Linux这串数字默认是0x10...37,共40字节。在macOS中是0xa...37,共48字节。填充数据你也可以通过-ppattern指定,比如ping-pff..33.10,则填充数据全部是ff。

默认TTL是64,你可以通过-tttl指定TTL值。

ping请求时间=接收到回显应答的时间-应答回显数据中的时间

实例分析

在测试机ping我的虚拟机ping-c2..33.10,..33.10是我测试用的虚拟机IP,wireshark抓包如下:

Ping请求

Ping响应

可以验证前面的分析。第2对请求和应答跟第一对类似,只是序列号,校验和等不同罢了。

关于校验和

ICMP报文头部中的校验和生成/校验方式也比较简单。

生成:先将校验和置为0,然后将ICMP报文的header+body按16bit分组求和。如果结果溢出,则将高16位和低16位求和,直到高16位为0。最后求反就是检验和的值。

校验:将报文的header+body按16bit分组求和(包括校验和字段),看看结果是否全是1,如果不是,则校验失败。

ICMP校验和算法

如何自己写一个ping?可以参考下这位朋友的ping工具的python实现。Lingerhk:icmp_ping_tool.py

3Traceroute原理分析

traceroute用于查看IP数据报从一台主机传到另一台主机所经过的路由。其实,在IP数据报的头部的选项字段有一个IP记录路由选项(RR),它也可以记录路由。为什么不直接用它而是另外弄出个traceroute工具,这是因为:

1)IP首部长度限制,导致记录的IP地址最多9个,远远不够。

2)并不是所有路由器都支持记录路由选项,因此某些路径无法使用。

traceroute用到ICMP协议和TTL字段。TTL字段是数据报的生存周期,初始值通常默认是64,每个处理数据报的路由器都需要把TTL值减去1或者数据报在路由器停留的秒数(因为绝大多数路由器转发数据报时延都小于1秒,因此通常都是减去1,而且很多路由器的实现即便超过1秒也是减去1,因此可以把TTL看做一个跳站计数器)。路由器接收到一份IP数据报时,如果TTL为0或者1,则路由器不转发该数据报,而是丢弃并给源机器发送一份ICMP超时报文,而ICMP信息中的IP报文中源地址正是路由器的IP地址。

traceroute的原理就是:

先发送一份TTL为1的报文,这样第一个路由器会将TTL减1然后丢弃该报文,并发回一个ICMP超时报文,这样就得到了第一个路由器的IP地址;接着发送一个TTL为2的报文,可以得到第二个路由器的IP地址;继续该过程直到目的主机。

但是目的主机即便收到TTL为1的报文,它也不会丢弃该数据报并发回一份ICMP超时报文,因为此时数据报已经到了目的地。为了判断是否到达目的主机,traceroute发送的报文采用了UDP数据报,它选择一个很大的端口值如以上的,以保证没有其他应用程序使用该端口,然后目的主机会返回一个端口不可达的ICMP报文,这样就可以知道什么时候结束。

traceroute针对每个TTL会发3次UDP报文,并打印每次的往返时间。如果5秒内没有收到3次报文中任何一个的响应,则打印*号继续下一个TLL的报文发送。3次报文选择的UDP目的端口分别是,,,UDP报文数据长度为24字节,内容为全0(macOS环境)。

实例分析

运行traceroute.75..,可以看到wireshark抓包的前几跳信息,TTL最开始是1,然后是2...,端口是到,每个TTL发3次报文,在没有达到目的主机前,返回的是ICMP超时报文。到达主机后,则会返回ICMP端口不可达报文。

traceroute请求的UDP报文

traceroute响应的ICMP超时报文

traceroute目的主机响应的ICMP端口不可达报文

由于IP路由通常都是动态的,每个路由器都要判断数据报接下来要转发到哪个路由器,应用程序对路由策略并不控制。而traceroute程序的IP源站选路选项(-ggateway)可以实现发送者指定路由,比如指定必须经过哪些路由IP,这里就不展开了。

分享 转发
TOP
发新话题 回复该主题