赞
踩
使用python中的scapy库抓取并解析pcap包(五元组信息)
由于云厂商的链路监控做得实在是不咋地,所以我们决定自己实现一套网络链路监控系统。
目的效果:客户端安装agent,实时采集流量数据并且进行上报给服务器端,不管是HTTP、HTTPS、MySQL,以及底层的TCP、UDP,甚至是链路层的,都需要实时采集并上报。
由于我们团队使用Python的居多,所以第一版以Python为开发语言进行开发。一番调研之下,客户端的agent决定使用Scapy来进行流量的获取
Scapy是一个强大的,用Python编写的交互式数据包处理程序,它能让用户发送、嗅探、解析,以及伪造网络报文,从而用来侦测、扫描和向网络发动攻击。Scapy可以轻松地处理扫描(scanning)、路由跟踪(tracerouting)、探测(probing)、单元测试(unit tests)、攻击(attacks)和发现网络(network discorvery)之类的传统任务。
它可以代替hping,arpspoof,arp-sk,arping,p0f 甚至是部分的Nmap,tcpdump和tshark 的功能。
支持很多协议,比如ARP,BOOTP,Dot1Q,DHCP,DNS,GRE,HSRP,ICMP,IP, NTP,RIP,SNMP,STP,PPPoE,TCP,TFTP,UDP等,可以通过ls()查看支持的协议
简单的说,Scapy主要做两件事:发送报文和接收回应。
由于Scapy是Python的模块,所以可以使用pip进行安装
pip install scapy
注意:由于Scapy需要root权限才能发送数据包,所以建议使用root用户进行安装
安装完成可以直接在命令行中输入scapy测试是否安装成功:
>scapy INFO: Can't import matplotlib. Won't be able to plot. INFO: Can't import PyX. Won't be able to use psdump() or pdfdump(). WARNING: No libpcap provider available ! pcap won't be used WARNING: No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually INFO: No IPv6 support in kernel INFO: Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption. (Dot11) INFO: Can't import python-cryptography v1.7+. Disabled IPsec encryption/authentication. WARNING: IPython not available. Using standard Python shell instead. AutoCompletion, History are disabled. WARNING: On Windows, colors are also disabled aSPY//YASa apyyyyCY//YCa | sY//YSpcs scpCY//Pp | Welcome to Scapy ayp ayyyyyyySCP//Pp syY//C | Version 2.4.4 AYAsAYYYYYYYY///Ps cY//S | pCCCCY//p cSSps y//Y | https://github.com/secdev/scapy SPPPP///a pP///AC//Y | A//A cyPC | Have fun! p///Ac sC///a | PYCpc A//A | To craft a packet, you have to be a scccccp///pSP///p p//Y | packet, and learn how to swim in sY/y caa S//P | the wires and in the waves. cayCyayP//Ya pY/Ya | -- Jean-Claude Van Damme sY/PsYYCc aC//Yp | sc sccaCY//PCypaapyCP//YSs spCPY//YPSps ccaacs
注意:如果没有安装所有的可选包,Scapy会显示有些功能不能用,如:
INFO: Can't import matplotlib. Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No libpcap provider available ! pcap won't be used
WARNING: No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually
INFO: No IPv6 support in kernel
INFO: Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption. (Dot11)
INFO: Can't import python-cryptography v1.7+. Disabled IPsec encryption/authentication.
具体可参考:https://scapy.readthedocs.io/en/latest/installation.html#optional-dependencies
注意:Windows平台需要安装Winpcap才能进行嗅探sniff
进入scapy后,可用ls()来查看scapy支持的网络协议(由于输出内容太长,只截取部分以供参考)
可以看到耳熟能详的ARP,BOOTP,Dot1Q,DHCP,DNS,GRE,HSRP,ICMP,IP,NTP,RIP,SNMP,STP,PPPoE,TCP,TFTP,UDP等等都支持
注意:这里可以带参考,比如ls(IP)来查看IP包的各种默认参数
进入scapy后,可以用lsc()来查看scapy的函数集。
比较常用的函数有:
比如:(由于输出内容太长,只截取部分以供参考)
嗅探流量的数据包有两种方式:
sniff函数如下:
def sniff(count=0, store=1, offline=None, prn=None,filter=None, L2socket=None, timeout=None, opened_socket=None, stop_filter=None, iface=None,*args,**kargs)
参数含义:
注意:如果不设置count和timeout的话,那么sniff会卡在那里一直运行着,sniff后面的代码是不会运行的,一般是会配合prn回调函数,且store建议设置为0,不保存到内存
保存成pcap
wrpcap('xxx.pcap', package)
读取pcap
rdpcap('xxx.pcap')
比如:
>>> from scapy.all import * >>> packets = sniff(count=1) # 获取一个流量数据包 >>> wrpcap('test.pcpp', packets) # 保存成pcap >>> pcap_packets = rdpcap('test.pcap') # 读取pcap文件 >>> pcap_packets <test.pacp: TCP:1 UDP:0 ICMP:0 Other:0> >>> pcap_packets[0] <Ether dst=50:d2:f5:fd:85:e2 src=d4:6d:6d:1c:93:50 type=IPv4 |<IP version=4 ihl=5 tos=0x0 len=41 id=17191 fla gs=DF frag=0 ttl=64 proto=tcp chksum=0x574f src=192.168.31.179 dst=14.215.177.38 |<TCP sport=2894 dport=https seq=622811909 ack=621991385 dataofs=5 reserved=0 flags=A window=510 chksum=0x8563 urgptr=0 |<Raw load='\x00' | >>> pcap_packets[0].src 'd4:6d:6d:1c:93:50' >>> pcap_packets[0].dst '50:d2:f5:fd:85:e2' >>> pcap_packets[0].show() ###[ Ethernet ]### dst = 50:d2:f5:fd:85:e2 src = d4:6d:6d:1c:93:50 type = IPv4 ###[ IP ]### version = 4 ihl = 5 tos = 0x0 len = 41 id = 17191 flags = DF frag = 0 ttl = 64 proto = tcp chksum = 0x574f src = 192.168.31.179 dst = 14.215.177.38 \options \ ###[ TCP ]### sport = 2894 dport = https seq = 622811909 ack = 621991385 dataofs = 5 reserved = 0 flags = A window = 510 chksum = 0x8563 urgptr = 0 options = [] ###[ Raw ]### load = '\x00'
package[0]是查看第一个数据包的数据,package[0].show()是查看第一个数据包的详细信息
scapy是按照按照 TCP/IP 四层参考模型显示详细包信息的,即:链路层 [Ethernet]、网络层[IP]、传输层[TCP/UDP]、应用层[RAW]
通过上述输出结果,我们可以看出每个层的数据包有哪些属性可以取出。
这里P代表的是Ethernet层。P.dst (取出dst属性)、P.src (取出src属性)、P.type (取出type属性)
每一层都有一个 payload 属性,可以不断进入下一层。
p.payload:IP层(可用 p.payload.* 取出IP层的属性)
p.payload.payload:TCP/UDP层(可用 p.payload.payload.* 取出TCP/UDP层的属性)
p.payload.payload.payload:RAW层(可用 p.payload.payload.payload.* 取出RAW层的属性)
上面显示的是TCP的请求,下面的UDP的请求:
###[ Ethernet ]### dst = 14:43:d0:65:ae:a2 src = 88:b8:5d:bd:0d:7f type = IPv4 ###[ IP ]### version = 4 ihl = 5 tos = 0x0 len = 40 id = 28350 flags = frag = 0 ttl = 128 proto = udp chksum = 0x0 src = 192.168.1.56 dst = 192.144.236.192 \options \ ###[ UDP ]### sport = 59297 dport = ms_wbt_server len = 20 chksum = 0x6f27 ###[ Raw ]### load = '\xae;\xf8\x01\x04\x00\x04\x04\x00\x01\x07\x00'
发送数据包之前需要构建数据包
比如使用IP()就可以创建默认的数据包,也可以使用TCP()创建TCP包、使用UDP()创建UDP包等,具体可以通过ls()查看,使用 ls(IP()) 可以查看IP数据包可以有哪些参数
比如:
>>> ip_package = IP(dst='8.8.8.8') # 创建目的地址是8.8.8.8的数据包 >>> ip_package.show() # 查看数据包的信息 ###[ IP ]### version = 4 ihl = None tos = 0x0 len = None id = 1 flags = frag = 0 ttl = 64 proto = ip chksum = None src = 192.168.31.179 dst = 8.8.8.8 \options \ >>> ip_package.summary() # 查看数据包的概要信息 '192.168.31.179 > 8.8.8.8 ip'
可以使用 ‘/’ 操作符来给数据包加上一层。比如构造一个TCP数据包,在IP层指明数据包的目的地址。在TCP层可以设定数据包的目的端口等等。UDP数据包同理
比如:
>>> ip_package = IP(dst='8.8.8.8')/TCP(dport=(53)) # 创建目的地址是8.8.8.8的数据包,目的端口为53 >>> ip_package.show() ###[ IP ]### version = 4 ihl = None tos = 0x0 len = None id = 1 flags = frag = 0 ttl = 64 proto = tcp chksum = None src = 192.168.31.179 dst = 8.8.8.8 \options \ ###[ TCP ]### sport = ftp_data dport = (80, 443) seq = 0 ack = 0 dataofs = None reserved = 0 flags = S window = 8192 chksum = None urgptr = 0 options = []
构造完数据包就可以进行发送,有以下方法:
send(pkt):发送三层数据包,但不会受到返回的结果。
sr(pkt):发送三层数据包,返回两个结果,分别是接收到响应的数据包和未收到响应的数据包。
sr1(pkt):发送三层数据包,仅仅返回接收到响应的数据包。
sendp(pkt):发送二层数据包。
srp(pkt):发送二层数据包,并等待响应。
srp1(pkt):发送第二层数据包,并返回响应的数据包
比如:
>>> ip_package = IP(dst='8.8.8.8')/TCP(dport=(53))
>>> ans, unans = sr(ip_package)
Begin emission:
Finished sending 1 packets.
........*
Received 9 packets, got 1 answers, remaining 0 packets
>>> ans
<Results: TCP:1 UDP:0 ICMP:0 Other:0>
>>> unans
<Unanswered:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。