怎么样快速解析好几个 G 的 pcap 文件

104 天前
 ChristopherY
目前知道的 Python 库有 scapy ,dpkt 等

scapy 能解析出来的字段比较多,但是速度很慢,大概每秒 1000 个包左右。

dpkt 比较快,每秒可以达到几十万个包。但是解析出来的字段比较少,需要自己手动解字段。



请问各位大佬,有没有相关的工具或者优化方法能快速解析 pcap 文件?
2520 次点击
所在节点    程序员
31 条回复
levelworm
104 天前
@ChristopherY 很好奇 parsing 的瓶颈在哪里?如果从钻研技术角度来说(也就是不用外界的 library ),能不能用 C 来解决这部分瓶颈,然后和 Python 联动?
ChristopherY
104 天前
@levelworm 核心点在于把 pcap 文件的 raw data 根据不同层的协议解析成对应的字段信息。用 Python 现有的库都比较慢(可能是没找到合适的库)。所以确实最佳实践应该是用 c 的 libpcap 库来解析,然后再用 python 自定义函数进一步处理想要统计的信息吧。
kuanat
104 天前
@ChristopherY #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 机制扇出,分配个多个线程来解析。如果是单线程肯定会非常慢。
daxin945
103 天前
要是我的话 肯定图方便直接上 suricata 然后解 json 日志了
wsseo
103 天前
github 上,gopacket/gopacket 在维护,是 fork 谷歌的 gopacket
playboy0
103 天前
@kuanat #14 在 10Gbps 网络上做实时处理没什么问题。
请问 CPU 和内存消耗量是多少呢?谢谢
kuanat
103 天前
https://github.com/google/gopacket

我之前在 go 经验的帖子里写过,这个库配合一些手动内存管理的技巧,在 10Gbps 网络上做实时处理没什么问题。

如果是 pcap 离线文件,直接按照示例写就好了。
kuanat
103 天前
@playboy0 #26

老 E5 单核 2G ,单个核心处理能力最高 100k pps 左右,包含业务逻辑。单纯解析时间中位数在 20us 左右。

由于整个内核 AF_PACKET 扇出数量和并发线程数是一致的,加上解析过程是 zerocopy ,几乎不会触发 gc ,内存占用没有印象了,应该非常稳定。
playboy0
102 天前
@kuanat #28 非常感谢您的回复,可以分享下您那边具体点的方案吗?是交换机端口镜像的吗,流量处理这边系统应该如何设置呢,谢谢
kuanat
102 天前
@playboy0 #29

流量来源是分光设备,旁路直接进服务器的光口网卡。什么都不用配置,网卡开启 promiscuous 混杂模式抓包就行了。端口镜像应该一样的道理。


这个项目是挺久之前的了,某集团安全审计相关,要做全协议流量分析。内部接入比较复杂,有类似 PPPOE/PPP 之类的认证,VLAN 既有二层也有三层。所以直接从出口分光出来做的。

这个事情本身不是我负责的,我就是去救火的。因为这个事情后来又做了针对某些协议的 DPI ,这玩意后来对外好像卖了接近一千万……

原本有个 DPDK 的方案,是很早之前从别的地方采购的,没人能维护。配套服务器是双路 E5 ,核心倒是多,只是频率很低,系统又是 CentOS 7 。基本上就是抱着死马当活马医的想法,姑且用 Go 一试。

系统太老了不想维护,所以 PF_RING 指望不上,就拿 AF_PACKET 替代了,实际测试下来没啥问题。这个做到后面发现 AF_PACKET/MMAP 其实和 PF_RING 原理几乎一样的。如果现在做的话,可能都是用 AF_XDP 了,性能估计还能翻番。

当时还用的是 google/gopacket 而不是后来有人维护的 gopacket/gopacket 。不过影响不大,整个库的基础功能很完善了,除了当时没有的几个协议做了一下解析实现。


技术上这个只要懂原理的话没什么难度,内核里用 BPF 去抓包,MMAP 内存在内核和应用之间共享,AF_PACKET 设定好扇出,把网卡的数据写入 MMAP 的内存,用户空间的应用通过 ZeroCopy 方式读就可以了。核心部分代码可能没有一百行。
playboy0
101 天前
@kuanat #30 非常感谢您的不吝赐教🥰

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1049906

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX