资讯动态

pcapsipdump:按Call-ID拆分SIP会话与RTP媒体流的命令行工具

发布时间:2026/10/7 4:17:30 来源:尧图企业网站定制
简介这是一款面向VoIP网络调试、安全分析与运维人员的开源SIP嗅探工具基于libpcap库实现监听指定网卡后能将每个SIP/RTP会话自动拆分并保存为独立命名的pcap文件后续可用tcpdump、Wireshark等工具逐会话回放与问题排查。压缩包共16个文件以C源文件和头文件为主配套Makefile构建脚本、init启动脚本、spec打包配置、README与LICENSE文档以及面向Debian、RedHat、Solaris等系统的平台适配文件整包仅15KB体量轻巧、目录结构清晰。已有298人学习下载。借助该资源读者可以深入理解SIP会话表维护、RTP流识别与pcap文件写入等关键实现同时多平台配置样例与变更日志也有助于在真实环境中快速编译部署或以此为模板二次开发定制抓包分析工具能有效节省自行设计基础框架的时间。1. 先搞清楚 pcapsipdump 是什么一个能把 SIP 会话从 pcap 里按呼叫拆开的命令行工具做 VoIP 抓包的人都会遇到这种场景网关或 SBC 上跑了一天 tcpdump攒下几百 MB 的 pcap想定位某个号码的通话为什么掉线。用 Wireshark 打开过滤器能筛出sip和rtp但你得自己记住 Call-ID还要手工把同一个通话的信令和媒体流关联起来几万个包翻下来眼睛都花。pcapsipdump 就是干这个的它用 libpcap 读取 pcap 文件或直接监听网卡再用 libosip2 解析 SIP 协议最后按 Call-ID 把同一通电话的 SIP 信令和 RTP 媒体流拆到独立的 pcap 文件里一条命令能处理一天的抓包。适合运营商 IMS 测试、VoIP 网关排障、SIP 协议开发的人。本文从编译、参数、踩坑到脚本化处理把这个小工具讲透。2. 下载编译从 tar.gz 到可执行文件依赖比想象中更挑版本2.1 依赖安装libpcap-dev 和 libosip2-dev 是硬前提pcapsipdump 源码很小整个工程就是几个.c文件外加一个 Makefile但它依赖两个库libpcap 负责抓包和读包libosip2 负责 SIP 协议解析。这两个缺一个Makefile 直接编译不过所以装依赖是第一关。在 Debian/Ubuntu 上我一般这样装sudo apt-get install libpcap-dev libosip2-dev build-essential注意包名Ubuntu 18.04 和 20.04 上libosip2-dev都有但 Debian 老版本可能叫libosip2-4-dev。装完别急着编译先确认头文件在不在ls /usr/include/osip2/osip.h如果这步提示 No such file or directory后面编译必然报错。CentOS/RHEL 的包名不同sudo yum install libpcap-devel osip-devel这里有一个坑有的系统里你可能已经装了从源码编译的 libosip2和系统包管理的头文件混在一起编译时会出现重复定义或者版本冲突。我踩过一次头文件是 4.x链接库是 3.x结果编译过了运行起来直接段错误根本没法定位问题。所以建议只用系统包管理器装不要自己源码装 osip2除非你要给这个老工具打补丁。2.2 编译配置Makefile 里的 CFLAGS 和 LDFLAGS 别有玄学解压源码tar -zxvf pcapsipdump-0.2.tar.gz cd pcapsipdump-0.2 make运气好的话一条make就出二进制。但大多数情况下你会遇到找不到头文件的问题因为默认的 Makefile 里的路径是十几年前 Linux 发行版的结构。我一般这样改make CFLAGS-I/usr/include/osip2 -I/usr/include LDFLAGS-losip2 -lpcapCFLAGS里的-I/usr/include/osip2让编译器找到osip.h-I/usr/include补一下 libpcap 的头文件路径。LDFLAGS里的-losip2是链接 osip 库-lpcap是链接 pcap 库。如果提示找不到pcap.h先检查ls /usr/include/pcap.h。编译完成后运行./pcapsipdump -h看到 Usage 输出就说明成功了。然后把二进制放到/usr/local/binsudo cp pcapsipdump /usr/local/bin/这个工具这么多年没大更新但在很多老网元、测试仪表上仍然非常能打。需要注意的是如果系统 libpcap 版本比较新源码里用到的pcap_lookupdev可能被标记废弃只会有 warning不影响最终生成。2.3 版本兼容性老工具遇上新系统时经常出现的三个编译错这个工具最烦人的地方就是版本兼容。我在 Ubuntu 20.04 上编译时就碰到了libosip24.x 带来的几个编译错误。第一个是implicit declaration of function osip_message_to_str原因是新版改了函数签名多了输出长度参数。解决方法是找到源码里调用osip_message_to_str的地方改成新签名char *buf; size_t length; osip_message_to_str(msg, buf, length);第二个错误是osip_list_iterator相关新版把 list API 改成了osip_list_iterator_t结构体。如果你不想深究可以直接在 Makefile 里加-DHAVE_CONFIG_H有时候能把一些兼容分支激活。但更多时候需要打开源文件逐个替换血泪经验是先grep -n osip_ *.c看一下到底用了哪些 API再和/usr/include/osip2/下实际头文件对比。第三个错误是链接阶段报一堆undefined reference这通常是 CFLAGS 和 LDFLAGS 顺序问题。GNU ld 对静态库有顺序要求放在-l前面的目标文件引用了后面的库才能被解析。所以如果你自己写了.o文件确保它们出现在所有-l之前。遇到这些编译问题不要慌。这个源码总共就几千行错误信息直接指向具体文件和函数按新 API 改一下就是十几分钟的事。改完之后编译出来的工具在现网跑起来非常稳。3. 命令行用法读取 pcap 按 Call-ID 切片一条命令拆出几十个会话3.1 基本命令与输出文件命名规则先看最常见的一种用法从 pcap 文件里读取 SIP 会话写到一个目录。mkdir -p /tmp/sipout pcapsipdump -r /var/log/sip_capture.pcap -w /tmp/sipout-r指定读取的 pcap 文件-w指定输出目录。执行完之后/tmp/sipout下会出现一堆以 Call-ID 命名的.pcap文件。命名规则是把 SIP 消息里的 Call-ID 字段中的/、、空格等特殊字符替换成_再加上.pcap后缀。比如 Call-ID 是a1b2c3192.168.1.1输出文件就是a1b2c3_192.168.1.1.pcap。如果遇到重复的 Call-ID比如设备重新注册后复用后面会追加数字区分比如a1b2c3.pcap和a1b2c3-1.pcap。每个文件里就是这个 Call-ID 对应的所有 SIP 信令以及相关联的 RTP 媒体包。要验证拆得对不对用 tshark 看一个文件tshark -r /tmp/sipout/a1b2c3_192.168.1.1.pcap | head -5输出里如果同时出现sip和rtp两种协议说明信令和媒体关联成功了。如果只有sip那就是没抓全 RTP后面第 5 章会讲。3.2 关键参数-r、-w、-n、-f、-v 各管什么事pcapsipdump的-h输出很短但有几个参数需要理解透。下面是 0.2 版本中常见参数的作用参数作用说明-i eth0实时监听网卡用于镜像口抓包不能和-r同时用-r file.pcap读取抓包文件离线分析用的最多-w /path/dir指定输出目录不指定时默认写当前目录-n不导出 RTP 媒体流只保留 SIP 信令文件小很多-f udp port 5060pcap 过滤表达式在入口处过滤能加快处理速度-v打印更多日志调试时能看到每个会话的 Call-ID注意-f的过滤语法和 tcpdump 完全一样因为底层就是 libpcap。如果你知道 SIP 在 5060 端口可以用-f udp port 5060。但这里有个陷阱RTP 的端口是 SIP 协商出来的往往不在 5060 段。如果你加了-f udp port 5060RTP 包在入口处就被丢掉了拆出来的文件里只有信令媒体流全丢。所以如果你希望拿到完整通话不建议对来源 pcap 加-f端口过滤除非你确定 RTP 也落在固定端口范围。-n参数非常实用。有时候我们只关心信令流程不关心语音内容加-n后输出文件只有默认的三分之一到四分之一大小分析起来快得多而且不会被媒体流干扰。3.3 完整示例提取某个时间段内所有 INVITE 通话假设你有一整天的抓包all_day.pcap只想看上午 9:00-9:05 之间发生的通话。pcapsipdump 没有按时间切片的参数但可以先用 tshark 按时间范围过滤再丢给 pcapsipdump。第一步用 tshark 按时间过滤出 SIP 信令生成一个小 pcaptshark -r all_day.pcap -Y frame.time \2024-01-15 09:00:00\ frame.time \2024-01-15 09:05:00\ -w morning_sip.pcap第二步对这个筛选后的文件运行 pcapsipdumpmkdir -p morning_sessions pcapsipdump -r morning_sip.pcap -w morning_sessions -n这里加-n是因为第一步只筛出了 SIP 信令RTP 已经被丢掉了再加一次媒体流也拿不回来。这样拆出来的文件每个都是一个独立呼叫的信令过程。如果你想连媒体一起拿就不能用 tshark 做时间过滤得先把全天 pcap 全量拆再对每个会话文件做时间过滤。我一般在排障时先信令后媒体两轮操作效率最高。3.4 实时抓包镜像口监听与 pcap 过滤器的坑pcapsipdump 也能实时监听网卡特别适合在网关镜像口上边抓边拆pcapsipdump -i eth0 -w /var/spool/sipdump/默认情况下它会持续抓包每识别出一个新 Call-ID 就建一个新文件。镜像口流量大的时候输出目录最好放在独立硬盘或 SSD 上否则磁盘 IO 会成为瓶颈造成丢包。另外实时模式下如果只关心 INVITE 通话不关心 REGISTER 和 OPTIONS可以用-f限制pcapsipdump -i eth0 -w /var/spool/sipdump/ -f udp port 5060但正如上面所说这个过滤会把 RTP 也滤掉所以一般我只在只查注册失败问题时才这么用。正常的排障流程建议不要加-f让工具把 SIP 和 RTP 全拆出来之后再按需求挑选。4. 实战进阶SIP 与 RTP 关联导出把通话语音捞出来4.1 pcapsipdump 的 RTP 关联原理从 SDP 到五元组pcapsipdump 为什么能把 RTP 和 SIP 关联起来关键在于 SIP 消息里携带的 SDP。INVITE 请求和 200 OK 响应里都包含了c行媒体连接地址和m行媒体类型和端口比如cIN IP4 192.168.1.10 maudio 40000 RTP/AVP 8 0工具解析这些字段后会在内存里建立一个表Call-ID 对应的媒体 IP、端口、RTP payload 类型。后续抓到的 RTP 包只要五元组中的 IP 和端口跟这个表匹配就归到这个 Call-ID 的会话文件里去。这个机制有个隐含的边界如果 SIP 信令经过了代理服务器SDP 里写的地址是终端私网地址而抓包点在代理外侧RTP 包的实际源地址跟 SDP 里的地址不一致关联就会失败。碰到这种情况pcapsipdump 无能为力只能靠 Wireshark 手动关联或者把抓包点放到 SDP 指定地址所在的链路上。4.2 导出信令用 -n 只取 SIP避免媒体干扰排查大部分业务问题时信令时序比媒体内容更重要。比如看 REGISTER 流程有没有收到 401、INVITE 有没有被 486 拒绝这些用-n拆出来的文件就够了。pcapsipdump -r call.pcap -w only_signal -n加了-n之后输出文件里只剩下 SIP 消息没有 RTP 包。文件体积小用 tshark 打开也更快。我在做批量分析时习惯默认加-n只有在需要回放语音或者分析编解码时才重新不带-n拆一遍。4.3 还原通话音频rtpplay 回放与 Wireshark RTP Streams要听通话内容得先确认 RTP 的 payload 类型。常见的 G.711A 是 8G.711U 是 0。你可以在拆出来的文件里用 tshark 看tshark -r /tmp/sipout/a1b2c3.pcap -Y rtp -T fields -e rtp.payload_type | head拿到 payload 类型后用rtpplay回放到一个 UDP 端口再交给 SIP 话机或分析软件。rtpplay是rtptools包里的命令需要额外安装sudo apt-get install rtptools rtpplay -t 20 /tmp/sipout/a1b2c3.pcap 127.0.0.1/25000-t 20表示每包间隔 20ms这是 G.711 的典型打包时长。如果你只是想可视化看波形直接在 Wireshark 里打开拆好的 pcap走Telephony - RTP - Streams就能看到流和听音频。这个工具已经把每个通话的媒体流单独放好了省掉你自己过滤 RTP 的时间。4.4 用 mergecap 合并与会话统计快速评估一批通话质量拆出来的文件多了以后如何快速判断哪些通话有异常我习惯把一批会话文件合并成一个 pcap然后用 tshark 做 SIP 统计mergecap -w /tmp/merged.pcap /tmp/sipout/*.pcap tshark -r /tmp/merged.pcap -q -z sip,stat这条命令会输出 SIP 方法、状态码的分布。如果出现大量 486、603说明被叫侧忙或拒接如果出现 200 OK 但后面没有 ACK可能是终端异常挂死。结合 pcapsipdump 按通话拆出来的文件能快速定位到具体 Call-ID再深挖那个文件的信令时序。这个流程我基本每天都在用。5. 避坑与常见问题排查为什么拆出来的文件是空的、乱码、不完整5.1 现象跑了命令输出目录却一个文件都没有原因输入 pcap 里根本没有明文 SIP 包。常见几种抓包加密了SIP 跑在 TLS 上5061 端口或者干脆抓的是别的协议。解决方法是先用 tshark 验证tshark -r input.pcap -Y sip | head如果没有任何输出说明没有明文 SIP。另外检查你的-f过滤器比如-f tcp会把 UDP 的 SIP 全滤掉。还有一种情况pcap 文件本身用到了 nanosecond 时间戳格式旧版 pcapsipdump 不识别会在读取时直接退出。解决方法是先用editcap -F pcap转成标准微秒格式。5.2 现象同一个 Call-ID 被拆成了好几个文件原因pcapsipdump 用精确字符串匹配 Call-ID如果 SIP 消息里 Call-ID 的格式有细微差异比如有的带有的不带或者大小写不一致就会被当成不同会话。另一个常见场景是终端重启后复用 Call-ID工具会给第二个文件加-1后缀。解决先看这几个文件里分别有哪些方法。用 tshark 逐个列出tshark -r a1b2c3.pcap -Y sip -T fields -e sip.Call-ID -e sip.method如果只是大小写差异可以手动用 mergecap 合并再处理。但如果真的是终端 bug 导致不同片段建议按时间线用 Wireshark 重新分析不要强行合并。5.3 现象RTP 流没导出来只有几个 SIP 信令包原因第一你加了-n参数那必然没有 RTP。第二SDP 包在抓包里丢了工具没有拿到媒体端口和 IPRTP 关联失败。第三抓包点和媒体路径不一致比如信令走了一个网段媒体走了另一个网段RTP 包根本没进这个 pcap。解决先确认命令里没有-n。然后看 INVITE 和 200 OK 里的 SDP 是否完整。可以这样查tshark -r session.pcap -Y sip sip.msg_type 2 -T fields -e sip.SDP.c -e sip.SDP.m如果sip.SDP.c为空那说明 SDP 没抓到。这种情况只能重新抓包没有后悔药。另外如果抓包点看到 RTP 包但工具没关联检查 SDP 里的地址是否和 RTP 包里的 IP 一致不一致就需要修改抓包点。5.4 现象编译时报错找不到 osip.h原因libosip2 头文件不在默认搜索路径或者根本没装。解决先确认头文件位置find /usr/include -name osip.h然后按第 2 章的方法在编译时指定-I/usr/include/osip2。如果还报错检查 libosip2 版本。新版 5.x 已经把 osip 解析改成线程安全接口方法签名变化很大建议直接用发行版自带的旧包比如 Ubuntu 18.04 的libosip2-dev和这个工具配合最好。5.5 现象输出目录不存在或权限错误导致进程退出原因-w指定的目录没有预先创建或者运行用户没有写权限。pcapsipdump 不会自动创建目录遇到错误会直接退出不会像 daemon 一样偷偷跑。解决先mkdir -p然后给足权限mkdir -p /var/spool/sipdump sudo chown nobody:nogroup /var/spool/sipdump如果用 systemd 服务跑注意临时目录的读写权限也是常见翻车点最好把输出目录单独建好并在 service 文件里明确User和Group。5.6 现象拆出来的 pcap 时间戳跟原始包不一致原因pcapsipdump 在写输出文件时会对部分 pcap 记录做时间戳归一化有些版本会丢纳秒精度。如果原始抓包用的是 nanosecond 精度拆出来的文件就变成微秒了。解决对时间要求不高的场景无所谓但如果你要做延迟分析建议用editcap -T seconds或者mergecap处理一下。另外工具在实时抓包模式下写入文件时会有几毫秒的缓冲跨文件边界的那一两个包可能会出现时间偏移做精度分析时记得避开会话的开头和结尾几个包。6. 进阶技巧批量处理一整天的 pcap以及实时抓包时的文件轮转6.1 用 shell 脚本批量处理成百上千个 pcap如果你有一堆按小时切割的 pcap比如gw_20240115_00.pcap到gw_20240115_23.pcap不要一个个手敲命令。写个循环一跑就行#!/bin/bash INPUT_DIR/var/log/sipcaps OUTPUT_BASE/data/sip_sessions for f in $INPUT_DIR/*.pcap; do session_dir$OUTPUT_BASE/$(basename $f .pcap) mkdir -p $session_dir pcapsipdump -r $f -w $session_dir -n done脚本里把每个小时文件的输出放到独立子目录避免不同小时相同 Call-ID 互相覆盖。加上-n是因为批量分析主要看信令流程媒体流可以先不取。如果确定要保留 RTP去掉-n但提前查看磁盘空间。6.2 验证拆出来的会话文件是否完整批量跑完之后我一般会快速数一下文件数排查异常for d in $OUTPUT_BASE/*/; do echo $d: $(ls $d | wc -l) files done如果某个目录的文件数特别多大概率是那个时段有大量 REGISTER 或 OPTIONS 心跳每个独立 Call-ID 都会生成一个文件。这时候可以用 tshark 聚合tshark -r 某小时目录下的文件 -Y sip -T fields -e sip.Call-ID | sort | uniq -c看看有没有高频重复的 Call-ID把心跳消息过滤掉再跑 pcapsipdump。6.3 实时大流量下的一个规避丢包的习惯实时抓包时流量大和输出文件多会让磁盘 IO 飙升直接影响 pcapsipdump 的处理速度。我现在的习惯是镜像口流量超过 200Mbps 时不用 pcapsipdump 直接写文件而是先用tcpdump抓成原始 pcap再离线批量拆。虽然多一道工序但能保证原始包不丢。另外我在每次处理重要排障时都强制先跑一遍-n模式拆信令确认 Call-ID 和时间线没问题再重新抓包拿媒体流。这个习惯帮我少翻了无数次车希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑