利用python发送icmp包详解(ping)
日期: 2017-05-10 更新: 2020-04-08 分类: 编程记录
利用python发送icmp包详解(ping)
ps:个人理解如有错误请指导
ICMP是(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
通俗的讲就是Ping包,icmp网络层协议所以不存在端口的概念,协议号为1让上层知道.
tcp,udp,ip都是采用校验和的算法,只是校验的数据所有变化.icmp会将头部和数据部分一起进行校验
维基百科关于icmp的详细解释:
https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol]
这里关于校验和做了重要说明:
Checksum
Error checking data, calculated from the ICMP header and data, with value 0 substituted for this field. The Internet Checksum is used, specified in RFC 1071
RFC1071讲述详细的校验过程:
https://tools.ietf.org/html/rfc1071
1的补码 = 反码求和
计算icmp的校验和必须包含header和data
要发送一次icmp就必须包含图中的必选信息:
//定义ICMP头部
unsigned char i_type; //8位类型
unsigned char i_code; //8位代码
unsigned short i_cksum; //16位校验和, 从TYPE开始,直到最后一位用户数据,如果为字节数为奇数则补充一位
unsigned short i_id ; //识别号(一般用进程号作为识别号), 用于匹配ECHO和ECHO REPLY包
short i_seq ; //报文序列号, 用于标记ECHO报文顺序 可置0
unsigned int timestamp; //时间戳 选项数据部分 可以无
python格式化对照表
现在来讲一讲实现的主要思路:
想要发送ping包首先要构造出icmp的完整包,关键就是校验和的计算方法
1.首先icmp的校验和需要头部和数据部分相加再进行校验和的运算
2.头部和数据部分相加必须为偶数,奇数补0就不用关心他了,因为我们只想实现发包,算法不过多研究
3.利用struct格式化为网络字节(类型[b],代码[b],校验和[H],识别号[H],序列号[h])第一次校验时,校验和为0,识别号一直都是进程号(os.getpid()),这就是头部的8个字节,头部和数据相加需要为偶数字节,那数据最小可以是[h]
struct.pack(‘bbHHh’,8,0,0,self.__id,0)
4.def __doCksum(self,packet)
//校验和求法:
//把数据报看成16比特整数序列(按网络字节顺序)
//对每个整数分别计算其二进制反码,然后相加
//再对结果计算一次二进制反码而求得
一般程序为了计算方便会先相加,再加上进位,最后进行取反
5.再把cksum值带入原有包struct.pack(‘bbHHh’,8,0,cksum,self.__id,0)
接下来需要用python实现发送一次icmp包的过程:
1.需要用到socket库
2.格式化数据的库struct,array
3.生成进程id的库
1 | #coding=utf-8 |
wireshark抓包查看
requests:
reply:
如无特殊说明,均为原创内容。转载请注明出处!