使用Scapy解析pcap文件

7

我正在比较scapy和dpkt的速度。我有一个包含pcap文件的目录,我解析这些文件并计算每个文件中的http请求次数。以下是scapy代码:

import time
from scapy.all import *

def parse(f):
 x = 0
 pcap = rdpcap(f)
 for p in pcap:
    try:
        if p.haslayer(TCP) and p.getlayer(TCP).dport == 80 and p.haslayer(Raw):
            x = x + 1
    except:
        continue
print x

if __name__ == '__main__':\

  path = '/home/pcaps'
  start = time.time()
  for file in os.listdir(path):
    current = os.path.join(path, file)
    print current
    f = open(current)
    parse(f)
    f.close()
 end = time.time()
 print (end - start)

脚本速度非常慢(几分钟后就会卡住),与 dpkt 版本相比:
import dpkt
import time
from os import walk
import os
import sys


def parse(f):
 x = 0
 try:
    pcap = dpkt.pcap.Reader(f)
 except:
    print "Invalid Header"
    return
 for ts, buf in pcap:
        try:
            eth = dpkt.ethernet.Ethernet(buf)
        except:
            continue
        if eth.type != 2048:
             continue
        try:
            ip = eth.data
        except:
            continue

        if ip.p == 6:
            if type(eth.data) == dpkt.ip.IP:
                tcp = ip.data


                if tcp.dport == 80:
                    try:
                        http = dpkt.http.Request(tcp.data)
                        x = x+1
                    except:
                        continue

print x

if __name__ == '__main__':

path = '/home/pcaps'
start = time.time()
for file in os.listdir(path):
    current = os.path.join(path, file)
    print current
    f = open(current)
    parse(f)
    f.close()
end = time.time()
print (end - start)

我使用scapy的方式有问题吗?还是说scapy比dpkt更慢?


你不是已经大部分回答了自己的问题吗?如果第一个确实挂起而不仅仅是花费了很长时间,那么你要么有了答案,要么我们无法在没有输入数据的情况下判断。我会非常惊讶如果scapy最终不会引发Python异常,但我以前也曾感到惊讶。 - msw
1
我还没有回答我的问题,我想知道我的scapy代码是否有缺陷,或者是scapy真的比dpkt慢。我尝试了单个捕获,速度差异为x20。我的输入是大型pcap文件(300 MB+)。 - svink
尝试使用 from scapy.utils import PcapReader?这个不会一次读取所有的数据包。 - lilydjwg
@lilydjwg 是的,我尝试过使用PcapReader并将其作为迭代器使用,但没有看到明显的差异。with PcapReader('file.pcap') as pack: for p in pack: ..... - svink
1个回答

1
你激发了我比较的欲望。测试数据为2GB的PCAP文件,仅是简单的包计数测试。
基于之前处理类似大小文件所需的时间,我预期使用C++/libpcap来完成这个任务只需要不到10分钟。但这次我想先进行原型设计,而我在Python中的速度通常更快。
对于我的应用程序来说,流式传输是唯一的选择。我将同时读取几个这样的PCAP文件,并根据其内容进行计算。无法将所有数据都存储在内存中,因此我只比较流式调用。
scapy 2.4.5:
from scapy.all import *
import datetime

i=0
print(datetime.datetime.now())
for packet in PcapReader("/my.pcap"):
    i+=1
else:
    print(i)
    print(datetime.datetime.now())

dpkt 1.9.7.2:

import datetime
import dpkt
print(datetime.datetime.now())
with open(pcap_file, 'rb') as f:
    pcap = dpkt.pcap.Reader(f)
    i=0
    for timestamp, buf in pcap:
        i+=1
    else:
        print(i)
        print(datetime.datetime.now())

结果:

数据包数量相同。这很好。 :-)

dkpt - 少于10分钟。

scapy - 35分钟。

dkpt先执行。因此,如果磁盘缓存对一个软件包有帮助,那么它将对scapy有帮助。我之前只使用scapy完成了这个任务,需要超过40分钟。

总之,感谢您5年前的问题。今天仍然很重要。由于从scapy读取速度过慢,我差点放弃Python。dkpt似乎更具性能。

另外提供的替代软件包:

https://pypi.org/project/python-libpcap/ 我使用的是python 3.10,但0.4.0对我来说似乎有问题。

https://pypi.org/project/libpcap/ 我想比较一下这个软件包的时间,但我发现很难找到一个最小的示例。公平地说,我没有花太多时间。


深入挖掘后,我发现dpkt在该迭代中所做的工作比scapy少。现在我正在循环中执行dpkt.ethernet.Ethernet(buf),时间没有明显改变。当执行上述行并解包数据开头时,dpkt需要略微超过10分钟,而不是稍微低于10分钟。 - Evan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接