目前知道的 Python 库有 scapy ,dpkt 等scapy 能解析出来的字段比较多,但是速度很慢,大概每秒 1000 个包左右。dpkt 比较快,每秒可以达到几十万个包。但是解析出来的字段比较少,需要自己手动解字段。请问各位大佬,有没有相关的工具或者优化方法能快速解析 pcap 文件?

tshark 或者 zed datalake

还有 packetbeat

最主要的还是想 Python 自己写函数去分析某个 pcap 文件,比如根据 src 、dst 、协议类型、mpdu id 或者 length 来筛选,然后进一步分析 pcap 文件。tshark 读取速度好像也一般,有没有最佳实践

有没有可能因为解析的字段比较少所以速度就快

不要用 Python 干这种事啊,换成 C 、Go 之类的去做,轻松快几个数量级。

确实,想追求速度还得是 c 或 go

是这样的,所以追求速度还是得用别的语言了

不知道要研究这份东西多久,如果经常发生,周期长,复盘次数多,不如写个脚本导入 mysql 吧, 记得以前看文档,pcap 有工具可以转 json ,然后想办法再进 mysql 试试, 在数据库表里里 fliter 东西,出结果范围快得不要不要的... 要不就如 5 楼所说,c++撸一个

我最近也在做类似的事情:使用 scapy 实时解析 udp 的报文,udp 报文会分片,所以我起了一个线程和队列去做接收和解析的逻辑

解析出来的字段是啥意思? pcap 里面存的不就是原始的 eth 数据包吗,好像还附带有 ts ,if 几个信息

就是根据帧的格式,把原始数据解析成对应的字段信息。

我也见过用数据库先建索引的,这种貌似是反复读取最好的方法了。不过对于 wifi7 这种协议,可能需要自己手动写解析函数了?

自己写,只处理需要的协议和字段。wifi7 是物理层,跟抓包没关系。

github.com/google/gopacket我之前在 go 经验的帖子里写过,这个库配合一些手动内存管理的技巧,在 10Gbps 网络上做实时处理没什么问题。如果是 pcap 离线文件,直接按照示例写就好了。

还有楼上说得不对,网络包是一层一层嵌套的,必须从外向内解析。当然理论上可以通过某层协议的标志从二进制的某个偏移开始解析,无视下层协议,但是这样做会损失很多信息,也不保证解析结果正确,与最初的目的不符。gopacket 这个库是可以自己写未知协议扩展的,比如原版里面没有 pppoe/ppp 的支持,我在自己的项目里加上了,可能也就二三十行代码。就是写清楚字节流多少偏移对应该协议的某个字段。如果是那种非定长编码的格式,需要先解析头部的长度信息,再解析对应的字段。

只要不解应用层的,还是挺简单的,go 可以用 gvisor.dev/gvisor/pkg/tcpip/header

gopacket 呢?

如果用 go 可以的话,那用 c 经典的库 libpcap 是不是也可以的,这方面有没有造好的轮子

go 的库之前倒没试过,主要是用 c 和 Python 。看起来用 go 比较方便

cpp 或者 julia

很好奇 parsing 的瓶颈在哪里?如果从钻研技术角度来说(也就是不用外界的 library ),能不能用 C 来解决这部分瓶颈,然后和 Python 联动?

核心点在于把 pcap 文件的 raw data 根据不同层的协议解析成对应的字段信息。用 Python 现有的库都比较慢(可能是没找到合适的库)。所以确实最佳实践应该是用 c 的 libpcap 库来解析,然后再用 python 自定义函数进一步处理想要统计的信息吧。

#18 用什么都可以,取决于你哪种语言比较熟练。C 版本的 libpcap 我没用过,考虑到是 tcpdump 在维护的,肯定是没问题的。Go 版本虽然两年没更新了,但协议这个东西又不会变……另外我觉得你其实考虑复杂了,gopacket/libpcap 都是强在抓包,至于你是不是用它做解析不关键,用它做解析的原因就是它们把协议相关的数据结构都定义好了。换个表达方式,你现在以字节形式读取到某个包(忽略到 pcap 文件格式解析),它一定是代表着某个多层嵌套的数据结构:[ L1_Header : L1_Payload [ L2_Header : L2_Payload [ L3_Header : L3_Payload [ ... ] ] ]然后假设 L1 是来自三层的,然后有 IP/ICMP/IGMP 几种协议,就拿 IP/ICMP/IGMP 的数据结构去套上面的字节流,匹配到就可以拆包了,L1_Payload 就是 [] 里面 L2/L3... 的内容,继续下一层解析就是了。像 dpkt 这种数据不足,肯定是各种协议 Header 的数据结构定义不完善。scapy 我用过但是印象不深了,我估计慢的主要原因是它没法做到像 C/Go 这样可以手动分配内存,然后 one pass 把多层结构一次解析出来。但是 scapy 大概每次都要遍历匹配所有协议,来判断下一层是什么。这个解析过程本质上和按照某个特定格式读取二进制文件没什么区别。提高解析效率除了解析单个包层面的优化,主要是靠多线程。特别是实时抓包实时处理,靠内核 AF_PACKET 机制扇出,分配个多个线程来解析。如果是单线程肯定会非常慢。

要是我的话 肯定图方便直接上 suricata 然后解 json 日志了

github 上,gopacket/gopacket 在维护,是 fork 谷歌的 gopacket

#14 在 10Gbps 网络上做实时处理没什么问题。请问 CPU 和内存消耗量是多少呢?谢谢