☰
pcapsipdump:按SIP Call-ID拆分pcap,一个通话一个文件
2026/10/12 4:59:00 网站建设 项目流程

简介:pcapsipdump 是一款基于 libpcap 开发的开源 SIP 嗅探工具,能够监听指定网络接口,自动识别 SIP 信令与 RTP 媒体流,并将每个会话单独保存为命名友好的 pcap 文件,结果可直接用 tcpdump、Wireshark 打开分析。该工具主要面向 VoIP 运维、网络排障和协议分析人员,也可用于学习 SIP 会话建立与媒体协商的全过程。压缩包内共有 16 个文件,以 C/C++ 源码与头文件为核心,配合 Makefile 编译脚本、init 服务管理脚本、spec 打包配置以及 README、ChangeLog 等文档,包体仅 15KB。阅读源码可以理解按会话拆分抓包、呼叫表维护、文件命名规则等关键实现,同时附带的平台适配文件有助于在 Red Hat、Debian、Solaris 等环境中完成编译部署,阅读文档也能快速掌握用法和扩展思路。开发者可据此梳理抓包流程,并根据实际需求新增过滤规则或输出格式。该资源已有 298 人学习,适合想深入 libpcap 抓包原理或开发自定义 VoIP 监测工具的开发者。

1. 拆 SIP 会话的 pcap sip dump:一个通话一个文件,省掉你半夜扒包的命

一个语音网关同时跑着几十路通话,客户投诉其中一路声音断续。tcpdump 把整个接口的包全录下来了,但你想单独看这一路的 RTP 流,却发现要么在 Wireshark 里按时间硬切,把前后其他路的包也剪进来;要么靠 IP 和端口手筛,IP 头一 NAT,端口一对不上,全白干。pcapsipdump 这类按 SIP call-id 自动拆包的 pcap sip dump 工具,解决的就是这个尴尬:一个通话一个 pcap 文件,每个文件里只有这一路的 SIP 信令和 RTP 媒体包,拿到手直接用 Wireshark 打开看 RTP 统计,不用自己写脚本从几十万包里捞那几万个媒体包。它适合语音运维、VoIP 开发、抓包分析这几类人,尤其是懒得为每个现场写 Python 解析器的人。

2. 安装与编译:老工具的 configure 三连与新系统的三个坑

pcapsipdump 是那种很纯粹的老牌 C 程序,整个项目就一个核心二进制,依赖极轻,但越轻的东西在现在的新系统上反而越容易在编译阶段翻车。这一章先把依赖、参数确认、编译排错走通,后面抓包才稳。

2.1 依赖确认:libpcap 是唯一硬依赖,但版本有讲究

pcapsipdump 抓包用的不是自己实现的收包逻辑,而是直接基于 libpcap 的 pcap_open_live 和 pcap_loop,所以系统里必须装 libpcap 的开发头文件。Debian/Ubuntu 系是libpcap-dev,CentOS/RHEL 系是libpcap-devel。

这里有一个新系统容易踩的版本问题:比较新的发行版带的 libpcap 是 1.9.x 甚至 1.10.x,而 pcapsipdump 0.2 是较早的代码,对 libpcap 的 API 调用还是老一套。多数情况是兼容的,但如果编译时出现pcap_createsrcstr、pcap_open这类符号找不到的报错,基本可以判定是 libpcap 头文件路径没被 configure 找到,而不是代码本身的问题。

安装依赖的命令,Debian/Ubuntu 系:

sudo apt-get install -y build-essential libpcap-dev

CentOS/RHEL 系:

sudo yum install -y gcc make libpcap-devel

逻辑说明:第一段命令把编译工具链和 libpcap 开发头文件一起装上;第二段是红帽系对应的包名,注意libpcap-dev和libpcap-devel只差一个后缀,但缺了哪一个在编译阶段都会直接报找不到pcap.h。参数说明:如果你用的是 RHEL 9 这类默认启用 dnf 的系统,把yum换成dnf即可,包名不变。

2.2 configure 三连与两个典型编译错误

源码包解开之后是标准的 autotools 工程,当前目录下执行三板斧:

tar zxf pcapsipdump-0.2.tar.gz cd pcapsipdump-0.2 ./configure make

逻辑说明:configure会检查 libpcap 头文件和链接库的位置,同时确认当前平台是否支持pcap_setdirection这类可选 API;make编译出名为pcapsipdump的二进制。参数说明:整个包没有复杂的 configure 开关,默认生成的二进制就在./pcapsipdump,不需要make install也能直接跑,这点对只想在服务器上临时用一下的场景很友好。

编译期最常见的报错有两类。第一类是找不到pcap.h:

fatal error: pcap/pcap.h: No such file or directory

原因几乎都是只装了运行时库libpcap0.8或libpcap,没装带头文件的-dev/-devel包,补齐上面的依赖命令重跑即可。第二类是链接阶段报undefined reference to pcap_*,这通常不是缺库,而是 libpcap 的库文件路径没在默认链接目录里。我一般会先find /usr -name "libpcap.so*"确认库在哪个目录,如果库存在只是路径偏,就在 configure 前加环境变量:

CPPFLAGS=-I/usr/include LDFLAGS=-L/usr/lib ./configure

逻辑说明:这行命令把头文件路径和库搜索路径显式指给编译器,绕过 configure 默认搜索路径的盲区。参数说明:CPPFLAGS影响预处理阶段的头文件查找,LDFLAGS影响链接阶段的.so查找,如果 libpcap 在/usr/local下,把两个路径相应替换。别上来就改源码,先查路径,这是我被这个问题折腾过两次之后学到的习惯。

2.3 权限与快速验证:非 root 抓包全是玄学问题

编译完先别急着上生产接口,用 loopback 接口做一个 10 秒的快速验证。pcapsipdump 底层走的是 raw socket 收包,普通用户在很多发行版上没权限,抓到的包数量恒为 0。所以验证命令最好直接带sudo:

sudo ./pcapsipdump -i lo -w /tmp/siptest -T 5 -v -L

逻辑说明:-i lo指定 loopback 接口,-w指定输出目录,-T 5表示每个通话的拆包文件上限为 5 分钟,-v会把 SIP 信令明文也落盘成文本文件,-L让工具把状态写到系统日志。参数说明:这个组合不是为了抓真实流量,而是确认二进制能正常启动、能打开接口、能创建输出目录。跑几秒后sudo pkill pcapsipdump,然后看/tmp/siptest下有没有生成带时间戳的文件。

验证的另一个点是输出目录权限。pcapsipdump 拿到-w目录后,如果目录不存在不会自动创建,而是直接放弃写入并打印错误信息。所以脚本里要先mkdir -p,这也是后面所有自动化脚本里我固定的第一行命令。

3. 参数拆解:从“能跑”到“按我的通话粒度拆包”

pcapsipdump 的参数不算多,但每个参数的语义和 tcpdump 不太一样,容易按惯性理解错。比如-T不是抓包总时长,而是单个通话文件的最大时长;-m不是内存限制,而是媒体停多久后主动关闭文件。这一章把参数按“必会和选调”拆开讲,参数表放前面,后面展开场景。

3.1 必会参数:-i、-r、-w、-v

先看这张参数表,后面对照场景解释:

参数作用典型值
-i指定抓包接口eth0、any
-r从已有 pcap 文件回放拆包mixed.pcap
-w输出目录/var/tmp/calls
-v把每个通话的 SIP 明文写入同名的.sip文件无
-T单个通话拆包文件的最大时长(分钟)15
-H让 Wireshark 正常识别时间戳无
-m媒体流停止多久后关闭当前文件(秒)60

-i最常用的值是any,意思是对所有接口收包。这个值在语音网关和软交换排障时特别好用,因为很多时候你根本不确认媒体流走了哪块网卡。但注意any模式下抓到的包没有具体接口信息,如果服务器上有多块网卡且需要按网卡区分流量来源,还是老老实实指定物理接口。

-r把磁盘上已有的 pcap 文件作为输入,工具只做离线拆包,不碰网卡。这个参数是这套工具里我最常用的:现场先 tcpdump 录一个混合包拿回来,夜里再慢慢拆,完全不占在线资源。-w指定输出目录,配合-r就是一条离线生产线。

-v在拆出来.pcap的同时,额外生成一个同名.sip文本文件,里面是这一路通话的 SIP 信令原文。比如呼叫 ID 是abc123,会生成abc123.pcap和abc123.sip。我之前排查一个注册失败问题,就是靠这个文本文件直接 grep 401 和 403 的分布在几分钟内锁定了是认证密码错,而不是媒体问题。

使用姿势上,我习惯的“标配启动命令”长这样:

sudo ./pcapsipdump -i eth0 -w /var/tmp/calls -T 15 -H -v -L

逻辑说明:-i eth0指定从业务网卡收包,-w指定拆包输出目录,-T 15限制每个通话 pcap 最多 15 分钟,-H输出兼容时间戳的文件头,-v同步落文本信令,-L把工具自身运行状态写 syslog,方便出问题时留痕。参数说明:-T 15不是抓包时长而是单通话上限,这个数字按你业务里最长通话的预期来,设太短会把长通话硬切成几个文件,设太长文件会很大。

3.2 拆分行为参数:-T、-H、-m 的语义与配合

-T的语义值得再强调一次,它是“单个通话文件的时间上限”。工具从 INVITE 开始计时,到-T分钟如果这个通话还在继续,会滚动写到下一个文件,但 call-id 不变,靠 Wireshark 打开时你会发现是同一路 RTP 被切成了两段。实际排障时这个副作用不大,因为你按时间看还是连续的一段流,只是文件数量多一个。

-H全称是 “Wireshark compatibility” 之类的作用,它的作用是保证生成文件的 pcap 头里的时间戳格式能被 Wireshark 直接识别。没有-H时,部分环境生成的 pcap 头时间戳是微秒精度,新版 Wireshark 在某些场景会提示时间偏移。加了-H之后基本没遇到过时间轴错乱,所以我的脚本里-H永远是常驻参数。

-m是媒体停止多久后关闭文件的超时参数,单位秒。这个参数解决的是“通话已经结束,但因为 keepalive 包一直没停,文件一直被占着”的问题。比如有些 SIP 终端挂了电话还会继续发 OPTIONS 保活,如果没有-m,这个通话的 pcap 文件会被一直写下去,直到被-T切段。设成-m 60表示媒体流停 60 秒没新包就把当前文件关闭,后续再来的 keepalive 就不再往这个文件里写了。

选参数的思路按场景来:如果你只关心信令完整性,-T设 30 甚至 60 分钟都没关系,信令包本来就不大;如果你要拿 RTP 流做丢包率分析,文件越纯粹越好,-T 15加-m 60的组合会让每个文件里只有完整通话,很少掺尾巴。监控长时间在线的设备时,-m尤其关键,这是我被一个设备“通话结束但文件一直变大”坑过一次之后才彻底搞懂的。

3.3 调试辅助:-L 与前台日志的取舍

-L参数把运行状态写进系统日志,适合放到后台跑的场景。不带-L时工具在前台打印一行行摘要,每抓到一个新通话会打一条记录。我实际用的守则是:短时间现场抓包用前台模式,Ctrl+C 直接停;线上长期抓包用nohup配合-L,日志走 syslog,不占用终端。

nohup sudo ./pcapsipdump -i eth0 -w /var/tmp/calls -T 15 -H -v -m 60 -L >/dev/null 2>&1 &

逻辑说明:这条命令把 pcapsipdump 放到后台运行,-m 60避免 keepalive 把文件拖到天荒地老,-L把状态写进系统日志,nohup保证 SSH 断开后进程不跟着挂。参数说明:>/dev/null 2>&1丢弃前台输出,因为有了-L已经不需要前台打印了;如果要停掉后台的抓包,用sudo pkill pcapsipdump,不要用 killall,后者权限要求更高。

4. 抓包实战:从混合流量里把三通并发通话拆成独立文件

上一章把参数讲完,这一章直接跑一个完整流程:模拟某办公室的三通并发通话,其中一路有视频,媒体端口各不相同,先用 tcpdump 录一段混合包,再用 pcapsipdump 拆开验证。整个过程在临时环境里跑,重点看拆包结果和文件组织方式。

4.1 第一步:先录一段混合流量

模拟环境里,三路 SIP 终端之间互拨,其中一路带视频协商,RTP 端口从 40000 到 40004 不等。现场录制时我一般先用 tcpdump 定点抓一会儿:

sudo tcpdump -i eth0 -s 0 -w /tmp/capture_mix.pcap -Z root port 5060 or portrange 40000-40004

逻辑说明:-s 0表示抓整个包不截断,保证 SDP 里的媒体信息是完整的;-Z root让 tcpdump 抓包时切换到 root 权限并读取抓包逻辑;port 5060 or portrange 40000-40004把 SIP 信令和这一段动态端口的 RTP 都收进来。参数说明:抓包时长建议覆盖完至少一路完整通话,比如 60 秒左右,包量不用太大,主要是演示拆包逻辑。

这段混合 pcap 里既有 INVITE、200 OK、BYE 等信令,也有三路的语音/视频 RTP 包,混在一起大概一万多个包。直接拿 Wireshark 打开也能看,但三路媒体流在时间轴上叠着,定位某一路的问题很费眼。

4.2 第二步:用 pcapsipdump 离线拆包

拿到混合包后,用-r模式离线拆包,这是不占用在线资源最理想的方式:

sudo ./pcapsipdump -r /tmp/capture_mix.pcap -w /tmp/split_output -T 15 -H -v -m 60

逻辑说明:-r让工具进入回放模式,逐个读包并按 call-id 聚合,每个新的 call-id 自动新建文件;-w指定输出目录,同一个 call-id 的 SIP 和 RTP 包会持续写入同一个文件,直到 BYE 或超时关闭。参数说明:-H和-v与在线模式完全一致,-T 15在本例中不会被触发,因为每路通话都很短;-m 60保证收到 BYE 后 60 秒内如果还有媒体包,也合并进同一个会话文件。

输出目录里的内容大致长这样:

/tmp/split_output/ ├── call_001_a3f9.pcap ├── call_001_a3f9.sip ├── call_002_4e11.pcap ├── call_002_4e11.sip ├── call_003_b708.pcap └── call_003_b708.sip

逻辑说明:.pcap文件是这一路完整通话的 SIP+RTP 包,.sip文件是这一路的信令文本,方便直接 grep 消息码和头域。参数说明:文件名前缀是工具按 call-id 的前几位生成的,不保证全局唯一,如果有两个对话的 call-id 前缀相同,工具会追加区分标识。这个现象很少见,但如果遇到,不要慌,打开.sip文件对比 call-id 全值即可区分。

用capinfos快速确认每个文件的包数量和时间跨度:

for f in /tmp/split_output/*.pcap; do echo "== $f" capinfos "$f" | grep -E "Number of packets|First packet time|Last packet time" done

逻辑说明:这个循环对每个 pcap 文件执行capinfos,只提取包数量和时间范围三个字段。如果你看到每个文件只有几百个包而不是混在一起的上千个包,说明按会话拆分成功。参数说明:grep -E里三个模式分别对应包计数、起始和结束时间,如果某个文件缺了Last packet time,说明文件可能被-m强制截断,属于正常现象。

4.3 第三步:打开拆包结果验证媒体完整性

这是我最看重的验证环节。拆包完成后,我会直接对比混合包和拆分包的“会话完整性”:

tshark -r /tmp/split_output/call_001_a3f9.pcap -Y "rtp" | wc -l tshark -r /tmp/capture_mix.pcap -Y "rtp" | wc -l

逻辑说明:第一条命令统计拆包文件里的 RTP 包数量,如果媒体包基本保留,说明拆分过程没有丢 RTP;第二条统计混合包里总的 RTP 包数,两者大致相等或略少(少了的是其他通路的媒体),就说明拆分没有损伤数据。参数说明:-Y "rtp"的显示过滤语法在 Wireshark 新版本里等价于rtp协议族,老版本tshark可能不支持-Y,改用-R "rtp"效果相同。

这个验证不能省。我在某次排障时遇到过拆出来的 pcap 只有信令没有媒体的情况,原因是抓包点设备和 SIP 信令不在同一跳,RTP 走过别的路径。如果直接拿拆包文件看 RTP 统计,就会误判媒体根本没有到网关,实际只是没抓到而已。

5. 避坑排查:五条血泪经验,覆盖 0 字节、乱文件名和拆错通话

pcapsipdump 用起来的坑集中在几个特定的“翻车”场景,多数不是工具本身的问题,而是和抓包环境、参数误用纠缠在一起。这五条是我自己或帮别人排查过的真实现场记录,按现象、原因、解决三步写清楚。

5.1 抓了半天,输出目录里全是 0 字节文件

现象:启动命令后,输出目录里确实生成了文件,但每个文件大小为 0,或者压根没有新文件生成。

原因:最常见的是非 root 启动导致收不到包,其次是-w指向的目录不存在,工具直接静默退出创建流程。还有一种情况是接口选错,比如业务流量走了eth1,但-i指定的eth0上干干净净。

解决:先确认权限,直接用sudo启动;再用tcpdump -i eth0 -c 10先验证这个接口上有包在跑,确认接口有流量后再启动 pcapsipdump。输出目录必须提前mkdir -p,或者脚本里先执行创建命令。我自己的习惯是把目录创建、权限赋值写到启动脚本前两行,避免每次手动补。

5.2 同一路通话被拆成了两个文件

现象:和同一通话对象连续打了两次电话,第二次的包没有并到第一次的文件里,而是生成了新文件。

原因:这不是工具随机乱拆,而是两次呼叫的 call-id 本身不同。很多 SIP 终端会在一次通话的多次 INVITE 重传中改变 Call-ID 的大小写格式,pcapsipdump 对 call-id 是大小写敏感的;另外,某些设备在 update 或 re-INVITE 时会生成新的 Call-ID。两段 RTP 流对应的不是同一个 call-id 时,工具自然当成新通话处理。

解决:先用.sip文件里的 Call-ID 头域确认两次的 call-id 是否一致。如果确实是同一通通话但 call-id 变了,目前版本没有自动合并开关,只能靠人工按时间范围把两个 pcap 拼接。实践中更常见的是大小写不一致,旧版本工具严格比对字符串,小写化处理后就能正常聚合,我建议先用文本对比确认是不是大小写问题再考虑拼接方案。

5.3 Wireshark 打开拆包文件时间轴乱跳

现象:用 Wireshark 打开拆出的 pcap,时间轴不连续,RTP 流的间隔明显异常,但用 tcpdump 抓的原始文件没问题。

原因:pcap 文件头的时间戳格式兼容性问题。pcapsipdump 在写入文件头时,有些环境下写的时基是微秒精度,Wireshark 按默认的纳秒精度解析,导致时间轴错位。这个问题在老版本 libpcap 上更容易出现。

解决:启动参数加-H,让工具以兼容模式写入文件头;如果已经生成了文件,用capinfos -E可以查看文件实际精度,再用editcap -T转换精度。现在我的所有启动脚本里默认带上-H,基本没再遇到过时间轴乱跳。

5.4 call-id 里的特殊字符导致文件名乱码

现象:输出目录里出现%、/等字符开头的文件或子目录,文件系统报错,或者文件打不开。

原因:部分 UA 生成的 Call-ID 里包含@、:、/甚至空格。pcapsipdump 直接用 call-id 的一部分拼文件名,这些字符在文件系统里有特殊含义。比如包含/的时候,工具会认为自己要写到子目录里,而子目录根本不存在,于是写入失败。

解决:在-w目录里看到乱码文件时,先用.sip文件里的完整 call-id 对照确认哪些文件被异常命名。旧版本常量里没有自动清洗逻辑,最省事的做法是在批量拆包后执行一个统一重命名脚本,把所有文件名里的危险字符替换成下划线。这个坑出现概率不高,一旦出现就是批量问题,所以我的处理脚本里固定先跑一遍清理。

5.5 拆包后媒体丢了一部分,统计丢包率虚高

现象:拿拆出来的 pcap 文件做 RTP 丢包率分析,发现丢包率异常高,但原始混合包数据看起来一切正常。

原因:这是我在一个视频通话排查里遇到的:视频通话有多路 RTP 流,但 pcapsipdump 按 call-id 聚合文件时,把音频和视频按同一会话范围写入,而视频流如果有独立的 RTCP 间隔策略,超时后工具提前关闭文件,后到的视频包就“丢”了,实际上是没写进当前文件。这种丢包是工具层面的时间窗口问题,不是网络丢包。

解决:分析丢包率时不要把其中一个 pcap 文件的媒体包数当成全量,先确认该通话实际有几路 RTP 流,再看文件时间范围是否完整覆盖。如果需要精确的媒体质量分析,优先用-m 120拉大关闭窗口,或者直接回到原始 pcap 包按端口做 RTP 统计。从那以后我只要做丢包率分析,都会先把拆包文件的时间跨度打出来看一眼,确认文件确实是完整的通话范围才下结论。

6. 进阶技巧:批量拆完后,用 5 行脚本把异常通话挑出来

拆包文件一多,一个个用 Wireshark 打开看效率太低。我的固定操作是:拆包结束后先跑一个 bash 循环,把每个 pcap 的 RTP 包数、时间跨度、丢包率指标批量拉出来,数值异常的直接列入排查清单,最后再针对那一路打开 Wireshark 细看。

for f in /tmp/split_output/*.pcap; do cnt=$(tshark -r "$f" -Y "rtp" 2>/dev/null | wc -l) pkt=$(capinfos "$f" 2>/dev/null | awk -F: '/Number of packets/{gsub(/ /,"",$2);print $2}') echo "$f RTP=$cnt PKT=$pkt" done | awk '$2 ~ /RTP=0/ {print "NO RTP: " $1}'

逻辑说明:循环体里对每个拆包文件分别统计 RTP 包数和总包数,最后一行的awk把 RTP 包数为 0 的文件单独拎出来打印。这类文件通常意味着只有信令没有媒体,优先级最高,最先排查。参数说明:tshark -Y "rtp"如果碰到损坏的文件会报错,2>/dev/null把报错吞掉不影响循环;awk -F: '/Number of packets/'里的字段分隔符是冒号,因为capinfos的输出格式是Number of packets: 1234。

做完这层筛选,我还会对 RTP 包数最多的几个峰值文件再做一次时延分布检查,用tshark的-T fields把 RTP 时间戳导出来看有没有乱序跳跃。一般到这步,问题基本都能定位到具体某一路通话。

某次客户投诉会议系统“声音时断时续”,我远程跑不了抓包,现场同事按我脚本录了一段混合包,我回公司后拆完,靠上面这个循环在五分钟内挑出那一路 RTP 包数量异常的 pcap,再结合.sip文件里的 SDP 和重传记录,确认是对端网关的 RTP 端口在通话中途被防火墙改写了端口映射,导致后半段媒体走了错路。从那以后,我每次拆完包都强制走一遍这个批量筛选流程,确认没有异常文件才继续做深度分析,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询