icmp报文及用go实现

目录

一、概述

二、ICMP报文格式详解

2.1 什么是ICMP

2.2 ICMP报文格式

2.3 ICMP报文类型

2.4 实际报文举例

三、使用go实现icmp请求以及接收响应内容


一、概述

本文主要旨在学习icmp报文格式,以及通过go语言来实现ICMP发包。

二、ICMP报文格式详解

2.1 什么是ICMP

因特网控制报文协议ICMP(Internet Control Message Protocol)是一个差错报告机制,是TCP/IP协议簇中的一个重要子协议,通常被IP层或更高层协议(TCP或UDP)使用,属于网络层协议,主要用于在IP主机和路由器之间传递控制消息,用于报告主机是否可达、路由是否可用等。这些控制消息虽然并不传输用户数据,但是对于收集各种网络信息、诊断和排除各种网络故障以及用户数据的传递具有至关重要的作用。ICMP的功能是检错而不是纠错。

2.2 ICMP报文格式

CMP报文包含在IP数据报中,属于IP的一个用户,IP头部就在ICMP报文的前面,所以一个ICMP报文包括IP头部、ICMP头部和ICMP报文,IP头部的Protocol值为1就说明这是一个ICMP报文,ICMP头部中的类型(Type)域用于说明ICMP报文的作用及格式,此外还有一个代码(Code)域用于详细说明某种ICMP报文的类型,所有数据都在ICMP头部后面

  • type:类型,1字节,报文类型,用来标识报文
  • code:代码,1字节,提供报文类型的进一步信息
  • checksum:校验和,2字节,使用和IP相同的加法校验和算法,但是icmp校验仅覆盖ICMP报文
  • Message body:数据部分,长度可变,字段的长度的和内容,取决于消息的类型和代码

2.3 ICMP报文类型

1、类型比对表

typecode描述查询/差错
0--Echo(应答)响应0Echo Reply -- 回显应答(Ping应答)        查询
3--目的不可达0

Network Unreachable -- 网络不可达

差错
1Host Unreachable -- 主机不可达差错
2Protocol Unreachable --协议不可达差错
3Port Unreachable --端口不可达差错
4Fragmentation needed but no frag. bit set--要求分段并设置DF flag标志报文差错
5Source routing failed --源路由失败报文差错
6Destination network unknown --目的网络未知差错
7Destination host unknown --目的主机未知差错
8Source host isolated(obsolete)--源主机被隔离(作废不用)差错
9Destination network administratively prohibited -- 目的网络被强制禁止差错
10Destination host administratively prohibited --目的主机被强制禁止差错
11Network unreachable for TOS --对特定的TOS网络不可达报文差错
12Host unreachable for  TOS --对特定的TOS主机不可达报文差错
13Communiation administratively prohibited by filtering --由于过滤 网络流量被禁止报文差错
14Host precedence violation --主机越权报文差错
15Precedence cutoff ineffect --优先权终止生效报文差错
4--流量控制0Source quench --源端被关闭(基本流控制)差错
5--重定向0Redirect for network --对网络重定向差错
1Redirect for host --主机重定向差错
2Redirect for TOS and network --对服务类型和网络重定向差错
3Redirect for TOS and host --对服务类型和主机重定向差错
8--Echo请求0Echo request -- 回显请求(ping请求)查询
9-路由器通告0Router advertisement --路由器通告查询
10--路由器请求0Route solicitation --路由器的发现/选择/请求报文查询
11--ICMP超时0TTL equals 0 during transit --传输期间生存时间为0差错
1TTL equals 0 during reassembly --在数据报组装期间生存时间为0差错
12--参数问题0IP header bad(catchall error) --坏的IP首部(包括各种差错)差错
1Required options missing --缺少必须的选项差错
2不支持的长度报文差错
13--时间戳请求0Timestamp request(obsolete) --时间戳请求(作废不用)查询
14--时间戳应答Timestamp reply(obsolete) --时间戳应答(作废不用)查询
15--信息请求Information request(obsolete) --信息请求(作废不用)查询
16--信息应答0Information reply(obsolete) --信息应答(作废不用)查询
17--掩码请求0Address mask request --地址掩码请求查询
18--掩码应答0Address mask reply --地址掩码应答查询

2、ICMP分类

  • 差错报文

①目的不可达

目的不可达的类型字段值为3,代码字段有为0-15,也就是说若将目的不可达的ICMP报文再做一个细分,会将目的不可达的原因分为16种,并用不同ICMP差错报文进行表示。

  • code=0;代表着网络不可达,出现这个ICMP差错报文,就代表着报文在路由过程的时候出现了问题,比如报文的目的网络在路由器上没有相应的条目,于是该路由器就回送网络不可达的报文
  • code=1;代表主机不可达,这个报文的来源一般是目的主机所处的网关发送的,因为目的主机所处的网关没有找到对应的目的主机的IP地址,而无法转交该数据报文,所以将数据报文丢弃并回送该ICMP差错报文。
  • code=2;代表着协议不可达,这就说明数据交互的双方在协议上的出现了问题。
  • code=3;代表着端口不可达,这就说明数据包上指定的目的端口在目的主机上可能没有监听
  • code=4;代表一个原本需要分片的数据包,但是IP头部上的表示是不进行分片,由此就出现了错误。比如我们可以设置自己的网卡的MTU大小比网关的MTU大,那么我们发送过去的数据在被网关接收后可能会出现错误,因为网关网卡的最大接收MTU数比发送过来的数据包小,而且这个数据包还标识不进行分片,这就会出现错误。

②参数问题

参数问题的类型字段值为12,它主要是因为对IP头部中的字段值出现了问题,从而导致收到这些问题报文的主机返送一个参数问题的ICMP差错报文

  • ICMP控制报文
  • ①源站抑制

type=4,code=0

源站抑制是拥塞控制的一种方式,虽然TCP在端到端上使用了窗口机制和慢开始,拥塞避免和快重传对流量进行了控制,网关通过对链路上的链路情况进行监控,对信源发送源站抑制里面包含着目的网络的信息,当接收方接收该信息后根据目的网络信息知道去往该网络的链路发生拥塞,于是减少信息的发送。

  • ②路由重定向

type=5;code=0-3

路由重定向是指当主机发送给某个路由器的时候,这个路由器会判断自己是否是最佳的转发设备,如果根据它的路由信息发现其他的转发设备对于该主机来说最好,也就是能够更快的将数转发到目的对象,那么它就将发送路由重定向给这个主机让它将路由修改为更佳的路由。更佳路由的信息存储在ICMP的后4个字节上,

  • ICMP查询报文
  • ①请求和回应报文

type=8,code=0

需要注意的是请求和回应的ICMP报文使用到了ICMP头部的后4个字节,分为两个字段,即标识(和序列号,标识一般是发送该报文的进程号,标识和序列号是标识一对请求和回应报文,只有与某请求报文对应的回应报文,它们的标识与序列号才是相同的。

需要注意的是,请求和回应的ICMP数据包中的数据部分都是相同的。

  • ②路由询问或通告

路由询问的类型字段值为10,通告的类型字段值为9,只有一个代码0

该类型报文主要用于无盘工作站,没有办法保存网关的情况,它就只能靠发送路由询问,来询问网关信息。路由询问报文只用了ICMP头部的前面4个字节,但是路由通告使用了全部的8个字节。、后4个字节有三个字段,分别为“地址数,地址项长度,生存时间”,它们占用的长度是1B,1B,2B这三个字段记载着数据部分包含的路由条目数量,路由条目的长度(即IP地址的长度),以及路由条目在路由器上面的有效生存时间。

在该ICMP报文中,每个路由信息分为路由地址和优先级,各自占用4个字节,优先级越高越有可能成为该主机的默认网关。

  • ③时间戳请求与应答

时间戳的请求的类型字段为13,应答为14,只有一个代码0

它的头部与请求与回应的ICMP报文一致,但是数据部分它使用了12个字节,每4个字节记录一段时间信息,总共有三段,分别是“发送时间戳 ,接收时间戳,回送时间戳”,发送时间戳的信息由时间戳请求者记录,后面两个字段由回送者记录。字段里面记录的是有关当前时间的毫秒数的表示,发送者只要根据回送者发送的时间信息就可以很容易的求出往返时长。

  • ④地址掩码请求和应答

请求的类型字段值为17,应答的类型字段为18,只有一个代码0

它的ICMP头部与请求的ICMP包的头部相同,数据字段存储的是请求的子网掩码

 PS:

  1. Identifier(标识符):Identifier 是一个16位的字段,通常用于标识 ICMP Echo 请求和响应之间的匹配。当发送 ICMP Echo 请求时,Identifier 字段的值会被设置为一个特定的标识符(通常是随机生成的),然后在接收到 ICMP Echo 响应时,接收端会将相同的标识符字段包含在响应中,以便发送端能够识别与响应相关联的请求。

  2. Sequence Number(序列号):Sequence Number 是一个16位的字段,它通常用于按顺序对 ICMP Echo 请求和响应进行排序。每个 ICMP Echo 请求都会包含一个唯一的序列号,然后在接收到 ICMP Echo 响应时,接收端会将相同的序列号字段包含在响应中,以便发送端能够识别响应与哪个请求相对应。

这两个字段的组合(标识符和序列号)允许发送端将 ICMP Echo 请求与响应正确匹配,从而可以测量网络的延迟和连通性。当发送多个 ICMP Echo 请求时,这些字段的组合确保了每个响应都与特定的请求关联,并且可以按顺序排列。

需要注意的是,Identifier 和 Sequence Number 的确切含义可能因 ICMP 报文的类型和用途而有所不同。上述解释是针对 ICMP Echo 请求和响应的常见用法。其他类型的 ICMP 报文可能会使用这些字段以不同的方式

2.4 实际报文举例

1、请求响应

请求包

响应包

2、网络、主机、协议、端口不可达

三、使用go实现icmp请求以及接收响应内容

package mainimport ("bytes""container/list""encoding/binary""flag""fmt""log""net""os""time"
)type ICMP struct {Type        uint8Code        uint8Checksum    uint16Identifier  uint16SequenceNum uint16
}var (timeout int64size    intcount   inttyp     uint8 = 8code    uint8 = 0data    string
)func main() {//获取命令输入内容getCommandArgs()if len(os.Args) < 2 {log.Fatal("Usage: programname target_ip")}raddr, _ := net.ResolveIPAddr("ip", os.Args[len(os.Args)-1])desIP := raddr.String()//建立连接,以及最后释放连接conn, err := net.DialTimeout("ip:icmp", desIP, time.Duration(timeout)*time.Millisecond)if err != nil {log.Fatal(err)}defer conn.Close()//发送报文展示格式// statistic := list.New()icmp := *&ICMP{Type:        typ,Code:        code,Checksum:    0,Identifier:  0,SequenceNum: 0,}icmpdata := []byte(data)recv := make([]byte, 1024)statistic := list.New()sended_packets := 0var buffer bytes.Bufferbinary.Write(&buffer, binary.BigEndian, icmp)buffer.Write(icmpdata)icmp.Checksum = CheckSum(buffer.Bytes())buffer.Reset()binary.Write(&buffer, binary.BigEndian, icmp)buffer.Write(icmpdata)fmt.Printf("正在Ping %s [%s] 具有 %d 字节的数据:\n", raddr, conn.RemoteAddr(), len(data))for i := 0; i < count; i++ {t_start := time.Now()_, err := conn.Write(buffer.Bytes())if err != nil {log.Fatalln(err)continue}sended_packets++conn.SetReadDeadline((time.Now().Add(time.Second * time.Duration(timeout))))_, err = conn.Read(recv)if err != nil {fmt.Println("请求超时")continue}t_end := time.Now()dur := t_end.Sub(t_start).Nanoseconds() / 1e6 //计算请求时间// fmt.Printf("来自 %s 的回复: 字节 = %s 时间 = %dms\n", desIP, len(data), dur)fmt.Printf("来自 %s 的回复: 字节 = %d 时间 = %dms TTL = %d\n", conn.RemoteAddr(), len(data), dur, recv[8])statistic.PushBack(dur)defer buffer.Reset()}//最后统计请求包defer func() {fmt.Println("")var min, max, sum int64if statistic.Len() == 0 {min, max, sum = 0, 0, 0} else {min, max, sum = statistic.Front().Value.(int64), statistic.Front().Value.(int64), int64(0)}for v := statistic.Front(); v != nil; v = v.Next() {val := v.Value.(int64)switch {case val < min:min = valcase val > max:max = val}sum = sum + val}recved, losted := statistic.Len(), sended_packets-statistic.Len()fmt.Printf(" %s 的Ping统计信息\n  数据包: 已发送 = %d, 已接收 = %d, 丢失 = %d (%.1f%% 丢失),\n往返行程的估计时间(以毫秒为单位):\n  最短 = %dms, 最长 = %dms, 平均 = %.0fms\n",desIP,sended_packets, recved, losted, float32(losted)/float32(sended_packets)*100,min, max, float32(sum)/float32(recved),)}()}func getCommandArgs() {flag.Int64Var(&timeout, "w", 5, "请求超时时长, 单位秒")flag.StringVar(&data, "d", "this is icmp databody", "请求的数据内容")flag.IntVar(&count, "n", 4, "发送请求数")flag.Parse()
}func CheckSum(data []byte) uint16 {length := len(data)index := 0var sum uint32 = 0for length > 1 {sum += uint32(data[index])<<8 + uint32(data[index+1])length -= 2index += 2}if length != 0 {sum += uint32(data[index])}hi16 := sum >> 16for hi16 != 0 {sum = hi16 + uint32(uint16(sum))hi16 = sum >> 16}return uint16(^sum)}

使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/110107.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringMVC之JSR303和拦截器

认识JSR303 JSR303是一项Java标准规范&#xff0c;也叫做Bean Validation规范&#xff0c;提供了一种JavaBean数据验证的规范方式。在SpringMVC中&#xff0c;可以通过引入JSR303相关的依赖&#xff0c;来实现数据的校验。 在使用JSR303进行校验时&#xff0c;需要在需要校验的…

ETL与ELT理解

ETL ETL&#xff08; Extract-Transform-Load&#xff09;&#xff0c;用来描述将数据从来源端经过抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;、加载&#xff08;Load&#xff09;至目的端的过程。ETL模式适用于小数据量集。如果在转换过程…

回溯算法解决分割回文串

回溯算法解分割回文串 力扣131 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1&#xff1a; 输入&#xff1a;s "aab" 输出&#xff1…

安防监控视频系统EasyCVR+AI算法智能分析网关助力智慧校园建设

学生是祖国的未来&#xff0c;学校就是培育学生的地方。随着校园信息化建设的不断发展&#xff0c;信息服务在校园管理中的作用也越来越强。在保障学生安全与校园高效管理上&#xff0c;人工智能做出了极大贡献&#xff0c;旭帆科技安防监控系统/视频汇聚/云存储/AI智能视频分析…

mysql的索引分类

索引分类 在 MySQL 数据库&#xff0c;将索引的具体类型主要分为以下几类&#xff1a;主键索引、唯一索引、常规索引、全文索引。 分类 含义 特点 关键字 主键 索引 针对于表中主键创建的索引 默认自动创建 , 只能 有一个 PRIMARY 唯一 索引 避免同一个表中某数据列中…

多线程|多进程|高并发网络编程

一.多进程并发服务器 多进程并发服务器是一种经典的服务器架构&#xff0c;它通过创建多个子进程来处理客户端连接&#xff0c;从而实现并发处理多个客户端请求的能力。 概念&#xff1a; 服务器启动时&#xff0c;创建主进程&#xff0c;并绑定监听端口。当有客户端连接请求…

国家网络安全周2023时间是什么时候?有什么特点?谁举办的?

国家网络安全周2023时间是什么时候&#xff1f; 2023年国家网络安全宣传周将于9月11日至17日在全国范围内统一开展。其中开幕式等重要活动将在福建省福州市举行。今年网安周期间&#xff0c;除开幕式外&#xff0c;还将举行网络安全博览会、网络安全技术高峰论坛、网络安全微视…

JavaEE初阶(5)多线程案例(定时器、标准库中的定时器、实现定时器、线程池、标准库中的线程池、实现线程池)

接上次博客&#xff1a;JavaEE初阶&#xff08;4&#xff09;&#xff08;线程的状态、线程安全、synchronized、volatile、wait 和 notify、多线程的代码案例&#xff1a;单例模式——饿汉懒汉、阻塞队列&#xff09;_di-Dora的博客-CSDN博客 目录 多线程案例 定时器 标准…

后端/DFT/ATPG/PCB/SignOff设计常用工具/操作/流程及一些文件类型

目录 1.PD/DFT常用工具及流程 1.1 FC和ICC2 1.2 LC (Library compiler) 1.3 PrimeTime 1.4 Redhawk与PA 1.5 Calibre和物理验证PV 1.6 芯片设计流程 2.后端、DFT、ATPG的一些常见文件 2.1 LEF和DEF 2.2 ATPG的CTL和STIL 2.3 BSDL 2.4 IPXACT 2.5 CDL netlist 3.…

【去除若依首页】有些小项目不需要首页,去除方法

第一步 // // // // // // // // // // // // // // // // // // 修改登录页 Login.vue 中 大概144行 &#xff0c;注释掉原有跳转。替换为自己的跳转路径 // // // // // // // // // // // // // this.$router.push({ path: this.redirect || …

C语言--字符串旋转笔试题

C语言–字符串旋转笔试题 文章目录 C语言--字符串旋转笔试题一、字符串左旋1.1 思路11.2 思路1代码1.3 思路21.4 思路2代码 二、字符串旋转结果判断2.1 思路12.2 思路2 一、字符串左旋 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字…

SpringBoot+@EnableScheduling使用定时器的常见案例

记录一下SpringBootEnableScheduling使用定时器的常见案例 我的SpringBoot版本 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.5.RELEASE</version><…