只要接触过网络的人,相信对ping命令并不陌生 。该命令可以用来检测本机到目标机的网络是否连通,是一种很常见的网络监测手段。对网络熟悉一点的人可能还知道ping命令的工作原理。
让我们看看ping命令的介绍:
DESCRIPTION ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to elicit an ICMP ECHO_RESPONSE from a host or gateway. ECHO_REQUEST datagrams (``pings'') have an IP and ICMP header, followed by a struct timeval and then an arbitrary number of ``pad'' bytes used to fill out the packet. ping works with both IPv4 and IPv6. Using only one of them explicitly can be enforced by specify‐ ing -4 or -6. ping can also send IPv6 Node Information Queries (RFC4620). Intermediate hops may not be allowed, because IPv6 source routing was deprecated (RFC5095).
以上是man打印的ping命令详情介绍。从中可知,ping使用了ICMP协议中的回送请求(echo-rquest)和回送应答(echo-reply)报文。
众所周知,IP协议没有差错报告或差错纠正机制,同时IP协议还缺少主机和管理查询所需要的机制。网际控制报文协议(ICMP)是设计来弥补上述缺憾的。
arping与ping类似,只是arping向目标主机发送arp数据包,用以检测一个IP是否在网络中已被使用。具体使用方式如下所示:
arping -I ens192 192.168.90.10
其中,I参数用来指定网口。
接下来,让我们使用Scapy实现一个简易版本的arping工具:
#!/usr/bin/python from scapy.all import * import sys def arping(target_ip): conf.verb=0 ans, unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=target_ip),timeout=2) collection = [] for snd, rcv in ans: result = rcv.sprintf(r"%ARP.psrc% %Ether.src%") collection.append(result) return collection if __name__ == '__main__': if len(sys.argv) > 1: for ip in sys.argv[1:]: print 'ARPING %s from localhost' % (ip) print 'Unicast reply from %s' % arping(ip) else: print 'please input target ip\n'
以上仅仅是作为测试而用,所以没有对输入参数和输出结果进行太多的校验。把该脚本保存为arping文件,并赋予可执行权限,使用效果如下所示:
[root@node kali]# ./arping 192.168.90.22 ARPING 192.168.90.22 from localhost Unicast reply from ['192.168.90.22 00:0c:39:39:9c:cc']
上述arping实现的具体步骤如下:
-
构造ARP请求报文。填入发送方的物理地址、发送方的IP地址(Scapy会自动填入发送方地址信息)以及目标IP地址。目标物理地址字段全部填入0。
-
使用数据链路层协议对ARP报文进行封装。以发送方物理地址作为源地址,以物理广播地址作为目的地址。
-
使用srp方法发送链路帧,超时时间配置为2秒。
-
分析srp方法返回的结果。
小结
在局域网中,如果目标主机对ICMP报文进行了屏蔽,但是此时我们又需要知道与该主机的连通性,那么可以尝试使用arping进行测试。