主机存活探测程序
一、ICMP协议原理
1.什么是icmp协议
因特网控制报文协议ICMP(Internet Control Message Protocol)是一个差错报告机制,是TCP/IP协议簇中的一个重要子协议,通常被IP层或更高层协议(TCP或UDP)使用,属于网络层协议,主要用于在IP主机和路由器之间传递控制消息,用于报告主机是否可达、路由是否可用等。这些控制消息虽然并不传输用户数据,但是对于收集各种网络信息、诊断和排除各种网络故障以及用户数据的传递具有至关重要的作用。
2.ICMP工作原理
当数据包处理过程出现差错时,ICMP向数据包的源端设备报告这个差错,它既不会纠正这个差错,也不会通知中间的网络设备。因为ICMP报文被封装在IP数据包内部,作为IP数据包的数据部分通过互联网传递。IP数据包中的字段包含源端和最终的目的端,并没有记录报文在网络传递中的全部路径(除非IP数据包中设置了路由记录选项)。因此当设备检测到差错时,它无法通知中间的网络设备,只能向源端发送差错报告。
3.报文格式
每一个ICMP消息都将包含引发这条ICMP消息的数据包的完全IP包头,ICMP报文则作为IP数据包的数据部分封装在IP数据包内部。ICMP包头中包含的三个固定字段就是源端设备确定发生错误的类型的主要依据。
- Type字段表示ICMP消息的类型;
- Code字段表示ICMP消息类型细分的子类型;
- Checksum字段表示ICMP报文的校验和。
4.实现方法
(1)ping命令
能验证网络的连通性
会统计响应时间和TTL(IP包中的Time To Live,生存周期)
(2)tracert命令
traceroute也是基于ICMP协议实现的。
功能:
打印出可执行程序主机,一直到目标主机之前经历多少路由器。
二、代码实现
from scapy.all import * from random import randint from optparse import OptionParser from scapy.layers.inet import IP, ICMP def Scan(ip): ip_id = randint(1,65535) icmp_id = randint(1,65535) icmp_seq = randint(1,65535) packet = IP(dst=ip,ttl=64,id=ip_id)/ICMP(id=icmp_id,seq=icmp_seq)/b'rootkit' result = sr1(packet,timeout=1,verbose=False) if result: for rcv in result: scan_ip = rcv[IP].src print(scan_ip+'……''host is up') else: print(ip + '……''host is down') def main(): parser = OptionParser() parser.add_option('-i',type='string',dest='IP')# 获取IP地址参数 options,args = parser.parse_args() print("scan for "+options.IP+"\n") #判断是单台还是多台主机 #IP中存在-,则为多台主机 if '-' in options.IP: #循环遍历需要扫描的IP for i in range(int(options.IP.split('-')[0].split('.')[3]),int(options.IP.split('-')[1])+1): Scan(options.IP.split('.')[0]+'.'+options.IP.split('.')[1]+'.'+options.IP.split('.')[2]+'.'+str(i)) time.sleep(0.2) else: Scan(options.IP) print("\nfinished\n") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("interrupted by user, killing all threads")
运行结果: