怎么样快速解析好几个 G 的 pcap 文件 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
请不要在回答技术问题时复制粘贴 AI 生成的内容
ChristopherY

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

  •  
  •   ChristopherY Jun 16, 2024 via Android 3860 views
    This topic created in 679 days ago, the information mentioned may be changed or developed.
    目前知道的 Python 库有 scapy ,dpkt 等

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

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



    请问各位大佬,有没有相关的工具或者优化方法能快速解析 pcap 文件?
    31 replies    2024-06-19 15:07:30 +08:00
    patrickyoung
        1
    patrickyoung  
       Jun 16, 2024 via Android
    tshark 或者 zed datalake
    patrickyoung
        2
    patrickyoung  
       Jun 16, 2024 via Android
    还有 packetbeat
    ChristopherY
        3
    ChristopherY  
    OP
       Jun 16, 2024 via Android
    @patrickyoung 最主要的还是想 Python 自己写函数去分析某个 pcap 文件,比如根据 src 、dst 、协议类型、mpdu id 或者 length 来筛选,然后进一步分析 pcap 文件。tshark 读取速度好像也一般,有没有最佳实践
    Rehtt
        4
    Rehtt  
       Jun 16, 2024 via Android
    有没有可能因为解析的字段比较少所以速度就快
    keakon
        5
    keakon  
       Jun 16, 2024
    不要用 Python 干这种事啊,换成 C 、Go 之类的去做,轻松快几个数量级。
    ChristopherY
        6
    ChristopherY  
    OP
       Jun 16, 2024 via Android
    @keakon 确实,想追求速度还得是 c 或 go
    ChristopherY
        7
    ChristopherY  
    OP
       Jun 16, 2024 via Android
    @Rehtt 是这样的,所以追求速度还是得用别的语言了
    qazwsxkevin
        8
    qazwsxkevin  
       Jun 16, 2024
    不知道要研究这份东西多久,如果经常发生,周期长,复盘次数多,不如写个脚本导入 mysql 吧,
    记得以前看文档,pcap 有工具可以转 json ,然后想办法再进 mysql 试试,
    在数据库表里里 fliter 东西,出结果范围快得不要不要的...
    要不就如 5 楼所说,c++撸一个
    QuinceyWu
        9
    QuinceyWu  
       Jun 16, 2024
    我最近也在做类似的事情:使用 scapy 实时解析 udp 的报文,udp 报文会分片,所以我起了一个线程和队列去做接收和解析的逻辑
    lysShub
        10
    lysShub  
       Jun 16, 2024
    解析出来的字段是啥意思? pcap 里面存的不就是原始的 eth 数据包吗,好像还附带有 ts ,if 几个信息
    ChristopherY
        11
    ChristopherY  
    OP
       Jun 16, 2024 via Android
    @lysShub 就是根据帧的格式,把原始数据解析成对应的字段信息。
    ChristopherY
        12
    ChristopherY  
    OP
       Jun 16, 2024 via Android
    @qazwsxkevin 我也见过用数据库先建索引的,这种貌似是反复读取最好的方法了。不过对于 wifi7 这种协议,可能需要自己手动写解析函数了?
    leonshaw
        13
    leonshaw  
       Jun 16, 2024 via Android
    自己写,只处理需要的协议和字段。wifi7 是物理层,跟抓包没关系。
    kuanat
        14
    kuanat  
       Jun 16, 2024 via Android
    https://github.com/google/gopacket

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

    如果是 pcap 离线文件,直接按照示例写就好了。
    kuanat
        15
    kuanat  
       Jun 16, 2024
    还有楼上说得不对,网络包是一层一层嵌套的,必须从外向内解析。

    当然理论上可以通过某层协议的标志从二进制的某个偏移开始解析,无视下层协议,但是这样做会损失很多信息,也不保证解析结果正确,与最初的目的不符。

    gopacket 这个库是可以自己写未知协议扩展的,比如原版里面没有 pppoe/ppp 的支持,我在自己的项目里加上了,可能也就二三十行代码。就是写清楚字节流多少偏移对应该协议的某个字段。如果是那种非定长编码的格式,需要先解析头部的长度信息,再解析对应的字段。
    lysShub
        16
    lysShub  
       Jun 16, 2024
    @ChristopherY 只要不解应用层的,还是挺简单的,go 可以用 gvisor.dev/gvisor/pkg/tcpip/header
    chengzishuai1
        17
    chengzishuai1  
       Jun 16, 2024
    gopacket 呢?
    ChristopherY
        18
    ChristopherY  
    OP
       Jun 16, 2024 via Android
    @kuanat 如果用 go 可以的话,那用 c 经典的库 libpcap 是不是也可以的,这方面有没有造好的轮子
    ChristopherY
        19
    ChristopherY  
    OP
       Jun 16, 2024 via Android
    @chengzishuai1 go 的库之前倒没试过,主要是用 c 和 Python 。看起来用 go 比较方便
    xgdgsc
        20
    xgdgsc  
       Jun 16, 2024 via Android
    cpp 或者 julia
    levelworm
        21
    levelworm  
       Jun 16, 2024
    @ChristopherY 很好奇 parsing 的瓶颈在哪里?如果从钻研技术角度来说(也就是不用外界的 library ),能不能用 C 来解决这部分瓶颈,然后和 Python 联动?
    ChristopherY
        22
    ChristopherY  
    OP
       Jun 16, 2024 via Android   1
    @levelworm 核心点在于把 pcap 文件的 raw data 根据不同层的协议解析成对应的字段信息。用 Python 现有的库都比较慢(可能是没找到合适的库)。所以确实最佳实践应该是用 c 的 libpcap 库来解析,然后再用 python 自定义函数进一步处理想要统计的信息吧。
    kuanat
        23
    kuanat  
       Jun 17, 2024
    @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 机制扇出,分配个多个线程来解析。如果是单线程肯定会非常慢。
    haoyunyinglai
        24
    haoyunyinglai  
       Jun 17, 2024
    要是我的话 肯定图方便直接上 suricata 然后解 json 日志了
    wsseo
        25
    wsseo  
       Jun 17, 2024
    github 上,gopacket/gopacket 在维护,是 fork 谷歌的 gopacket
    playboy0
        26
    playboy0  
       Jun 17, 2024
    @kuanat #14 在 10Gbps 网络上做实时处理没什么问题。
    请问 CPU 和内存消耗量是多少呢?谢谢
    kuanat
        27
    kuanat  
       Jun 17, 2024 via Android
    https://github.com/google/gopacket

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

    如果是 pcap 离线文件,直接按照示例写就好了。
    kuanat
        28
    kuanat  
       Jun 17, 2024 via Android
    @playboy0 #26

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

    由于整个内核 AF_PACKET 扇出数量和并发线程数是一致的,加上解析过程是 zerocopy ,几乎不会触发 gc ,内存占用没有印象了,应该非常稳定。
    playboy0
        29
    playboy0  
       Jun 18, 2024
    @kuanat #28 非常感谢您的回复,可以分享下您那边具体点的方案吗?是交换机端口镜像的吗,流量处理这边系统应该如何设置呢,谢谢
    kuanat
        30
    kuanat  
       Jun 18, 2024
    @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
        31
    playboy0  
       Jun 19, 2024
    @kuanat #30 非常感谢您的不吝赐教
    About     Help     Advertise     Blog     API     FAQ     Solana     1179 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 55ms UTC 23:50 PVG 07:50 LAX 16:50 JFK 19:50
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86