ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SIP抓包利器pcapsipdump:从噪声中按会话切分pcap的实战指南

SIP抓包利器pcapsipdump:从噪声中按会话切分pcap的实战指南 简介面向VoIP运维、SIP协议开发者与网络排障人员这一基于libpcap的开源SIP嗅探工具会监听指定网络接口自动区分通话会话将SIP与RTP流量分别写入命名清晰的独立pcap文件便于使用tcpdump、Wireshark等工具逐会话复盘信令与媒体流。压缩包共16个文件整体仅15KB代码量精炼。核心逻辑集中在pcapsipdump.cpp、calltable.cpp与对应头文件中两个C源文件加上一个libpcap检测脚本check_libpcap.c组成代码主干Makefile负责构建init、sysconfig、spec以及debian、solaris等配置分别覆盖服务启动、RPM打包和跨平台适配目录分层清楚方便按发行版差异排查问题。README、ChangeLog、LICENSE等文档对编译选项、syslog日志行为和发布历史做了必要说明有助于快速接入现有监控告警系统。整体组织紧凑适合以最小成本掌握会话级抓包思路。目前已有298人学习下载适合需要做SIP抓包分析、RTP会话留存或VoIP安全审计的中高级开发者参考。1. pcapsipdump 是给谁用的一条命令把 SIP 会话从噪声里捞出来做 VoIP 运维、SIP 网关联调或者呼叫中心排障的人大概率都经历过这种场景在网关上 tcpdump 抓了五分钟pcap 文件动辄几百 MB里面混着 RTP 语音流、RTCP 统计包和十几路无关的呼叫信令。想定位某一通异常呼叫得先用 Wireshark 的 SIP 过滤器从头筛一遍再手动跟踪 UDP 流来回折腾大半天。pcapsipdump 就是冲着这个痛点来的它是一个基于 libpcap 的 SIP 抓包工具在抓包的同时按「呼叫」为单位把报文切成独立的 pcap 文件信令和媒体包归到一个文件里文件名直接带上时间戳和会话标识抓完就知道哪路呼叫在哪不用再二次过滤。适合的读者很明确SIP 协议栈开发、VoIP 网关运维、运营商 IMS/SBC 测试岗位的从业者以及被 Wireshark 手动跟踪 UDP 流搞到崩溃的任何人。2. 从 tar.gz 到可执行文件编译安装与依赖检查2.1 三个依赖缺一个都编不过pcapsipdump 0.2 的源码包很小核心依赖只有两个libpcap 的开发头文件和 flex词法分析器。用 CentOS 系的 yum 或者 Debian 系的 apt 都能装上。我一般会在编译之前先跑一遍包管理器避免 configure 阶段报错再回头补装。在 CentOS 7 / Rocky Linux 8 上yum install -y libpcap libpcap-devel flex gcc在 Ubuntu / Debian 上把 yum 换成 aptapt-get install -y libpcap-dev flex gcc逻辑说明libpcap-devel 提供pcap.h头文件和libpcap.so链接库是抓包功能的底层依赖flex 用来生成词法解析器处理 SIP 消息的文本解析gcc 是编译器。缺了 libpcap-devel 会在编译时报找不到pcap.h缺 flex 会在 lex 阶段报yylex undeclared。这两个错误我都在不同机器上踩过属于纯环境问题装好重来就过了。参数说明-y参数指定包管理器自动确认安装交互环境下可以不加。生产服务器上如果没有外网源先把 rpm/deb 包拷到内网再装效果一样。另外注意如果机器上已经装了 Wireshark通常 libpcap 已经在但libpcap-dev/libpcap-devel不一定在这两个名字不一样别只装一半。2.2 解压编译三行命令跑完拿到 pcapsipdump-0.2.tar.gz 之后我习惯先扔到/usr/local/src底下跟其他源码包放在一起方便以后查找。cd /usr/local/src tar -xzf pcapsipdump-0.2.tar.gz cd pcapsipdump-0.2 make make install逻辑说明tar -xzf解压出源码目录make按 Makefile 编译出二进制make install把可执行文件装到系统路径默认是/usr/local/bin/pcapsipdump。整个过程不带 configure因为 0.2 版本的 Makefile 是写死的直接在源码根目录编译即可。参数说明如果make install没有写权限可以手动把编译出来的pcapsipdump二进制复制到自己的目录或者用 root 执行安装。装完可以跑pcapsipdump -v看版本号确认安装成功。部分 Linux 发行版的 libpcap 版本较新如果报pcap_createsrcstr之类符号找不到说明 0.2 的源码和新版 libpcap 有兼容性差异往下看避坑章节的处理办法。2.3 先跑通最小命令确认网卡能抓到包安装完成后不要急着上生产环境先用一个最小命令验证基本功能。在测试机器上找一块网卡跑几秒钟抓包看有没有输出文件生成mkdir -p /tmp/siptest cd /tmp/siptest pcapsipdump -i eth0 -t 10 sleep 3 kill %1 ls -la /tmp/siptest逻辑说明-i eth0指定监听 eth0 网卡-t 10意思是在抓到一个 SIP 报文后最多等 10 秒就封包写文件文件名的实际含义后面讲。后台执行 3 秒后杀掉进程此时如果测试网络里有 SIP 流量目录下会生成.pcap文件没流量则目录为空属于正常现象。这个最小命令的作用是把工具本身跑通排除编译问题。参数说明进程被 kill 时pcapsipdump 会主动把已缓冲的报文刷到磁盘所以不用担心丢数据。-i可以换成any表示监听所有网卡但多网卡机器上出来的 pcap 文件里 DLT 类型可能变为DLT_LINUX_SLL部分 Wireshark 版本解析 SIP 地址时不够直观所以生产场景我一般指定具体网卡。验证完把/tmp/siptest里的测试文件删掉进入下一步参数配置。3. 核心参数逐个拆-i / -c / -r / -t / -l / -p 怎么配才不抓瞎3.1 参数全景一张表看懂每个开关的作用pcapsipdump 0.2 的参数数量不多但每个都直接影响抓包结果。我按实际使用的频率排了一张表覆盖我日常 90% 的需求参数含义典型场景-i iface指定监听网卡网关出口、SBC 镜像口-r file从 pcap 文件回放抓取而非实地抓包事后分析历史 pcap-c同时保存非 SIP 报文RTP/RTCP 等需要恢复录音或抖动分析-t sec会话空闲多少秒后闭合并写文件控制单文件大小-l lines限制单个会话内最多存储的信令报文数防恶意轰炸或内存溢出-p关闭混杂模式只抓本机收发的包-s len设置快照长度只存报文头部注意-i和-r是互斥的一个表示从网卡实时抓一个表示从文件回放抓两个都写会报参数错误。这个表不是全部参数-h能看到完整列表但实际生产里后面四个参数一般用不上我在这里把用得上的先讲透。3.2 -c 参数为什么是录音恢复的关键遇到过很多同事在网关镜像口抓包死活提取不出可播放的音频文件。原因基本都是没加-c。pcapsipdump 默认只存储跟 SIP 信令直接相关的报文RTP 媒体流会被丢弃。加了-c之后工具会把属于同一会话的 UDP 流量整体归入对应的 pcap 文件这样每个文件里既有 INVITE/BYE 等信令也有音频 RTP 包后续用 Wireshark 的Telephony - VoIP Calls或RTP - Stream Analysis功能可以直接把音频导出成 .au 或 .wav。我一般在 SBC 或者媒体网关前面抓包时命令是这模样的pcapsipdump -i eth0 -c -t 30 /var/log/sip/out.pcap逻辑说明注意最后的位置参数out.pcappcapsipdump 会把它作为输出文件的「名称前缀」。实际生成的文件名是out_20240101120000_a1b2c3.pcap这样的结构。其中的时间戳是会话建立时间协调世界时后面的十六进制串是工具内部生成的会话标识不同的呼叫会落到不同的文件里。-t 30的意思是如果某个会话最后一条报文距今超过 30 秒就认为呼叫已经结束关闭这个文件所有后续同会话的新报文会重新开一个文件。这样设计是为了避免内存里挂太多半开会话实际生产中遇到长时间通话文件会等到挂断或超时后才最终生成。参数说明-c会把所有 UDP 流量都存下来文件体积会明显变大建议配合-s 160之类的快照长度来压规模。如果不做录音恢复只是查信令交互过程不开-c反而更轻量文件小、检索快。3.3 -r 回放的历史文件要注意什么-r参数用于从已存在的 pcap 文件里按会话切分。典型用途是现场先用 tcpdump 连续抓了几个小时的包之后再用 pcapsipdump 做事后切分优点是不影响在线抓包性能也能随手换参数重新切。pcapsipdump -r raw_all.pcap -c -t 15 /data/split/call.pcap逻辑说明-r raw_all.pcap读取原始 pcap 文件-c保留 RTP 流-t 15是回放时的超时阈值。回放速度很快一个 1 GB 的 pcap 一两分钟就能切完输出文件落在/data/split/目录下命名规律跟实时抓包一样。这里有个细节回放模式下的时间超时阈值-t指的是「按 pcap 时间戳计算的两个相近报文之间的间隔」而不是计算机墙钟时间所以 -t 15 在回放时代表前后报文时间戳差超过 15 秒就断开会话。参数说明如果你手里的 pcap 是在 NAT 后面抓的或者只有单方向的 SIP 流量比如只镜像了客户端一侧切出来的文件里会出现大量只有请求没有响应的半截会话此时可调大-t到 30 甚至 60减少误切。另一个注意点是-r读取大文件时占内存如果原始文件超过 5 GB建议用-t配合较长超时或者在源头上分段抓包。3.4 -l 参数遇到 SIP 洪水时保命的开关-l参数全称是 per-call line limit限制一个会话里最多记录多少条信令消息。正常一通电话的 INVITE/100/180/200/BYE 流程也就十几条消息但如果出现注册攻击或者扫描器的 OPTIONS 洪水同一个会话标识可能被塞进成千上万条报文内存和磁盘都被拖垮。我一般会定期巡检的网关上加-l 200pcapsipdump -i eth0 -c -l 200 -t 20 /var/log/sip/monitor.pcap逻辑说明-l 200表示单个会话文件内最多写入 200 条报文超过之后后续的报文会被丢弃但文件本身仍会被保留。这个参数能防止畸形流量把磁盘写满代价是极端情况下会丢一部分报文——对排障来说200 条足够还原完整交互了对证据保全类需求则不建议设太小的值。参数说明-l同时影响实时和回放模式。在回放模式下设置-l主要是为了防止某些异常会话在全部扫描完成前吃光内存。默认值如果没记错是 0不限生产环境务必显式设置别依赖默认值。4. 抓下来的包怎么用文件命名规则、RTP 提取与 Wireshark 联调4.1 读懂文件名里的时间戳和会话 IDpcapsipdump 生成的文件名格式非常固定业内常用写法类似prefix_YYYYMMDDhhmmss_hex.pcap。这个格式极其实用——在目录里ls -lt就能直接按时间排序看到每一路呼叫的开局时间排查某个时段的问题时可以直接定位。ls -lh /var/log/sip/ total 1.2G -rw-r--r-- 1 root root 342M Jan 4 10:23:45 monitor_20240104102345_3f9a2c.pcap -rw-r--r-- 1 root root 18M Jan 4 10:24:01 monitor_20240104102401_7b11cd.pcap -rw-r--r-- 1 root root 620M Jan 4 10:30:12 monitor_20240104103012_ab34df.pcap逻辑说明第一列是文件名前缀来自命令行传入的位置参数第二段是协调世界时时间戳UTC精确到秒第三段是十六进制会话 ID。有了这个命名规则在做定时任务时可以直接用find -name monitor_$(date %Y%m%d%H%M%S)*之类的通配符抓取指定时刻的文件。注意时间戳是 UTC比起本地时区差 8 小时的场景先确认你的服务器时区配置不然对照业务日志时容易搞错时间线。参数说明文件前缀不区分大小写但建议固定用小写前缀里不要带「通配符」或空格否则脚本解析时容易出错。文件权限默认是当前用户的 umask 值如果后续要让别的账号读取通过umask 022或者事后 chmod 统一处理。4.2 用 tshark 二次过滤把 SIP 状态码和时延直接拉到表里pcapsipdump 切出来的 pcap 文件已经按呼叫隔离但里面依旧同时有信令和媒体。如果你要快速看某一通电话的 SIP 状态码、INVITE 到 200 OK 的时延用 tshark 批量扫比一个个开 Wireshark 高效得多。我常用的组合是for f in /var/log/sip/monitor_*.pcap; do tshark -r $f -Y sip sip.MethodINVITE -T fields \ -e sip.call-id -e sip.status.code -e frame.time_delta_displayed \ -e sip.Media-Description 2/dev/null | head -5 done逻辑说明-Y是 Wireshark 显示过滤器的语法sip sip.MethodINVITE挑出 INVITE 事务-T fields按字段输出-e sip.call-id把呼叫标识带出来-e sip.status.code显示状态码。这条命令的价值在于当你有上百个切分好的文件时可以用它快速判断哪些文件里有失败的呼叫状态码非 200 或 180再针对性打开详情。参数说明frame.time_delta_displayed是相对时间戳能直接看出同一文件里 INVITE 和 200 OK 的间隔。不同 tshark 版本对 SIP 字段名的写法略有差异跑之前先执行tshark -G fields | grep -i sip确认字段名。如果 tshark 输出为空先检查文件里是否有sip报文——用capinfos $f看协议统计最直观。4.3 RTP 音频导出Wireshark 的 Telephony 菜单是最后的后悔药当你要证明某通电话的音频质量或者给业务部门提供录音证据时把 RTP 流导出来是最常见的做法。Wireshark 打开 pcapsipdump 切好的文件后走Telephony - VoIP Calls找到目标呼叫右键选中后点Play Streams或Export即可导出音频。这一步看似简单但有两个细节经常让人翻车。逻辑说明第一导出的音频文件默认是 8 kHz 的 PCM如果你的设备用的是 G.729 或 OpusWireshark 默认不带解码器需要在Analyze - Decode As里手动指定编码类型否则导出的文件是「嗡嗡」的噪音。第二只有开了-c参数抓的文件才有媒体流只存信令的文件在 Telephony 菜单里是空的。这个「后悔药」本质上依赖抓包开关配置所以我在第 3 章里特别强调-c。参数说明导出时建议选Play Streams旁边的保存按钮保存成.au格式再转.wav比 Wireshark 直接导出的.wav更稳定。音频文件命名可以用原始 pcap 文件的时间戳对应回溯源文件就方便了。5. 避坑指南让 pcapsipdump 白跑的 4 个常见问题5.1 抓包时丢 UDP 报文会话文件断成两半现象网络流量不大但按 -t 切出来的文件里频繁出现只有 INVITE 没有 BYE 的残会话用 Wireshark 打开提示 TCP 乱序或大量丢包尽管 SIP 是 UDP。原因pcapsipdump 默认使用 libpcap 的内存缓冲Linux 内核环形缓冲区net.core.rmem_max太小高突发流量下内核直接把包丢了。这正是这个工具最容易被误判为「有 bug」的场景——实际上包根本没到用户态。解决抓包前调大内核缓冲区或者在命令行里顺手设置sysctl -w net.core.rmem_max67108864 sysctl -w net.core.rmem_default67108864 pcapsipdump -i eth0 -c -t 20 /var/log/sip/call.pcap逻辑说明rmem_max是内核 socket 接收缓冲区上限默认值通常只有 212992 字节突发 RTP 流量很容易打爆。调大后 libpcap 可以缓存更多报文用户态来不及处理时不会立刻丢弃。事后丢包率可以用tshark -r 抓到的文件 -q -z io,stat,0看统计如果还丢就要考虑用 PF_RING 版本的 libpcap 或者把抓包点旁路到专用采集器。5.2 回放历史 pcap 时目录空空如也现象-r读一个确定含 SIP 的 pcap 文件命令跑完没有任何输出文件。原因回放模式下pcapsipdump 的「会话超时」判断依赖于 pcap 内部的时间戳如果原始 pcap 是在多个网卡镜像口抓的某些包的时间戳异常出现 1970 年或未来时间导致工具认为会话永远不结束一直在内存里挂着。解决先用capinfos raw.pcap | grep Capture start和capinfos raw.pcap | grep Capture end检查时间戳范围。如果发现异常时间戳用 editcap 修正后再回放editcap -E 0 raw.pcap raw_fixed.pcap pcapsipdump -r raw_fixed.pcap -c -t 15 /tmp/out/call.pcap逻辑说明editcap -E 0把第一层错误时间戳修正为 0之后再回放。这个坑在 0.2 版本的 pcapsipdump 里比较常见因为它对时间流逝的判定比较简单不处理异常时间戳。如果你没有 editcap退而求其次的做法是换用tcpdump -r raw.pcap -w fixed.pcap重写一遍 pcap有时可以修正封装头部的偏移信息。5.3 开了 -c但音频文件里只有前几秒现象录音导出后只有前几秒后面全是静音或直接结束。原因RTP 流在会话中途发生了 IP 地址或端口切换典型的如 NAT 超时重新协商或语音媒体被迁移到另一台媒体网关但 pcapsipdump 0.2 只追踪它认定的「原会话地址五元组」后续媒体包归到了新的流里被当成新会话开头或者直接丢弃。解决抓包时加上-k保留完整 UDP 流。我一般这样组合pcapsipdump -i eth0 -k -c -t 30 /var/log/sip/call.pcap逻辑说明-k是保留模式它在会话判断上放松限制把同一对 IP:端口之间的 UDP 包尽量归入同一文件避免媒体重协商导致文件被切段。这是案头常备技巧对付「同一通电话两边声音都在但文件里只有一半」的场景非常有效。代价是磁盘占用变大配合-t 30控制单文件闭合速度即可。注意不同编译版本的 pcapsipdump 对-k的行为略有差异有的版本需要-k和-c同时开启单独开-k等于没效果。建议在一台测试机上先抓一分钟验证一下文件内容里媒体是否连续。5.4 tshark 过滤不到 SIP 报文现象pcapsipdump 生成的 pcap 文件用tshark -r file.pcap打开报文数量正常但http sip过滤器结果为零。原因文件可能是在多网卡环境下用-i any抓的报文头部是 Linux cooked capture (SLL)Wireshark 默认以以太网类型解析却对内部 IP 协议类型识别不准还有一种可能是-s快照长度设得太小SIP 载荷被截断只剩二层头部。解决针对 SLL 头的问题用tshark -r file.pcap -Y sip仍然无效时改用-Y udp.port5060 || udp.port5061定位端口再手动跟进针对快照长度重抓时设置-s 512保证 SIP 消息体完整pcapsipdump -i eth0 -s 512 -c -t 20 /var/log/sip/call.pcap逻辑说明SIP 报文头加起来通常在 300600 字节之间-s 512在绝大多数场景下够用极端大的 SIP header如长 URI 或大号 Via 分支需要 1024 字节以上。如果你是为了搞录音RTP 载荷不用太多-s 512对媒体流影响不大因为音频帧大小本身就小。这个参数的坑在于默认值可能很小比如 68 字节只够二层和 IP 头SIP 消息被截得七零八落Wireshark 也就无法识别。6. 进阶玩法7×24 巡检脚本和定时清理策略把 pcapsipdump 养成一个固定服务比每次手动抓包省心得多。我现在常用的方式是用一个 shell 脚本做 7×24 小时循环抓包同时用-t让文件自动闭合配合find定时清理老文件。#!/bin/bash PCAP_DIR/var/log/sip STALE_DAYS7 # 保持抓包进程存活 if ! pgrep -f pcapsipdump -i eth0; then cd $PCAP_DIR nohup pcapsipdump -i eth0 -c -l 300 -t 60 -s 512 monitor.pcap /var/log/pcapsipdump_launch.log 21 fi # 清理 7 天前的 pcap find $PCAP_DIR -name monitor_*.pcap -mtime $STALE_DAYS -delete逻辑说明脚本每 5 分钟被 cron 调用一次先检查 pcapsipdump 是否还在跑不在了就重新拉起find把超过 7 天的文件删掉避免磁盘被历史包塞满。-t 60保证在一通电话结束后最多 1 分钟文件就关闭配合-l 300避免异常呼叫刷爆内存。启动参数里的-s 512兼顾信令完整性和磁盘占用。这套巡检方案部署在边缘网关上大半年了日常排查直接按时间戳打开对应 pcap基本不用临时上去抓包。参数说明nohup是让进程脱离终端重定向日志记录了启动失败信息比如网卡不存在、权限不足等。cron 配置里建议把脚本放到/usr/local/bin/sip_pcap_guard.sh并chmod x。如果想更精细可以加一层rsync把 pcap 每天归档到集中存储但不要把find的删除策略直接复制到归档服务器上——归档端保留周期要长得多按业务需求另定。最后说一个我自己的教训之前把-t设成了 5 秒结果一通持续 20 分钟的通话被切成了 4 个文件恢复录音时对不上后来改成 60 秒文件合并和检索就听话了。这个值没有标准答案取决于你最长通话的间隙和磁盘水位但 60 秒是我在多个项目里觉得最省心的默认值。希望帮到你。本文还有配套的精品资源点击获取
返回列表