对于scapy对pcap包的处理在我之前的一篇博客中有写:
https://blog.csdn.net/qq_38231051/article/details/81460427
这里对用scapy包对大pcap文件处理做出了简单的解决方法,但scapy包处理这种大文件有一个没法忍的缺点就是:
没错,特别慢,基本一个1G的文件要15分钟+,每跑一次数据我就得去看一集数码宝贝....
然后果然被要求优化。
emmmm
我试了试,用scapy直接遍历不做任何操作得12分钟+,没办法,就只能另寻出路了。
其实在我用spcay包之前我就用过dpkt,但......
dpkt的资料是真的少啊啊啊,
还是靠着万能的google捞到了自己想要的东西。跑1G数据(含数据处理)2分钟。优化后基本80s吧,不是很记得了。。。
不说废话了。。。。
这里分两部分,读pcap和写pcap文件(用dpkt写pcap文件的资料也是特少,我是看源码发现他有这个函数的。。。。)
f = open('new1.pcap','rb')
pcap = dpkt.pcap.Reader(f)
for ts,buf in pcap:
pass
ts是timestemp时间戳,buf(二进制数据)是主体的数据包信息。
如果我们想获取每个数据包的ip地址应该怎么做呢?
#由buf这个二进制数据转化为Ethernet类的对象
eth = dpkt.ethernet.Ethernet(buf)
ip_src = eth.data.src #这里是获取这个数据包的源ip
#要注意的是,这里的源ip是以二进制的方式返回的,如果我们要获取点分十进制的ip地址
#可以这样做
def inet_to_str(inet):
try:
return socket.inet_ntop(socket.AF_INET,inet)
except:
return False#这里因为具体需要我把IPv6给丢弃了
#如果希望IPv6也能获取可以这样
#return socket.inet_ntop(socket.AF_INET6,inet)
ip_src = inet_to_str(eth.data.src)
ip_dst = inet_to_str(eth.data.dst)#目的ip
如果要获取数据包的其他信息的话可以在官文文档中查看
https://dpkt.readthedocs.io/en/latest/print_packets.html
这里简单的贴一部分我的代码:
#coding=utf-8
import dpkt
import socket
import time
def inet_to_str(inet):
try:
return socket.inet_ntop(socket.AF_INET,inet)
except:
return False
def getip():
f = open('new1.pcap','rb')#要以rb方式打开,用r方式打开会报错
pcap = dpkt.pcap.Reader(f)
for ts,buf in pcap:
print(ts)打印时间戳
eth=dpkt.ethernet.Ethernet(buf)
#这里也是对没有IP段的包过滤掉
if eth.type != dpkt.ethernet.ETH_TYPE_IP:
continue
ip = eth.data
ip_src = inet_to_str(ip.src)
ip_dst = inet_to_str(ip.dst)
print(ip_src+'-->'+ip_dst)
if __name__=='__main__':
getip()
这段代码在python3.6 centos7系统下运行没有问题
百度google了几次的我还以为dpkt不能写pcap文件呢,最后在dpkt官方文档看到了Writer方法,然后用dpkt.pcap.Writer在google找到了许多例子。
这是一个简单的例子:
f = open("new.pcap","wb")
writer = dpkt.pcap.Writer(test)
writer.writerpkt(eth,ts=ts)#参数意义可以对应上面的读文件中的两个参数
test.flush()
test.close()
这里只是一个整体的写法,我们来看一下细节方面,比如,我们怎么把一个数据包中的源地址和目的地址改为我们需要的:
test = open("new.pcap","wb")
writer = dpkt.pcap.Writer(test)
f=open("old.pcap",'rb')
packets = dpkt.pcap.Reader(f)
for ts,buf in packets:
eth = dpkt.ethernet.Ethernet(buf)
eth.data.src = socket.inet_pton(socket.AF_INET,"127.0.0.1")#这里是将点分十进制转化成二进制
eth.data.dst = socket.inet.pton(socket.AF_INET,"127.0.0.2")
writer.writepkt(eth,ts=ts)#如果不加ts参数的话,这个数据包的时间戳默认是当前时间!
test.flush()
test.close()
源码不方便贴,上面的代码我没测试过。。。。如果报错,可能是该数据包没有ip的src,dst地址,就需要像之前读pcap那个一样进行协议过滤。也可能是其他小问题。可以多去google看官方文档学习。也可以留言一起交流。
dpkt性能毫无疑问是比scapy更加有优势的,但dpkt这个包用起来远没有scapy包方便,如果只是小包处理的话,建议scapy,可以节省踩坑的时间。scapy中文资料也更加的多。如果要求性能的话我还是推荐dpkt。