
简介pcapsipdump 是一款基于 libpcap 开发的开源 SIP 嗅探工具主要面向 VoIP 运维、SIP 协议研发以及网络抓包分析人员用于解决 SIP/RTP 会话抓包与后续分类存储的问题。它能够监听指定网络接口实时捕获流量并自动识别 SIP/RTP 会话为每个会话生成独立且命名友好的 pcap 文件可直接被 tcpdump、Wireshark 等常见工具打开回放适用于注册失败、通话中断、语音质量异常等真实排障场景也可作为 VoIP 网络调优的参考。整个资源包为 gz 格式共 16 个文件大小仅 15KB可以称得上小巧完整其中 C/C 源文件实现核心抓包与会话映射Makefile 等构建脚本负责快速编译init、sysconfig、spec、debian、solaris 等文件提供了不同 Unix 环境的封装并配有说明文档、变更记录和许可证文件方便本地部署或二次开发。目前已有 298 人学习下载是快速了解开源抓包工具实现的不错选择。通过阅读源码读者可以学习到 libpcap 抓包循环、SIP/RTP 会话归类逻辑、跨平台打包思路等具体技术点对协议分析或工具开发极有参考价值。1. pcapsipdump 0.2SIP抓包老工具为什么现在还值得装pcapsipdump 0.2这个tar.gz压缩包初看像十几年前的老工具但它解决的是至今仍常被问的问题SIP信令在5060端口媒体RTP却在动态协商的高位端口tcpdump按端口抓要么漏要么抓成大杂烩。pcapsipdump专为SIP会话设计自动从INVITE、200 OK的SDP里解析媒体信息把同一通电话的信令和媒体切进独立pcap文件还带索引。适合VoIP运维、话机注册排障、通话质量分析的人。下面按我自己落地这个工具的经验从原理、编译、参数到避坑完整过一遍。2. 抓SIP建话为什么不能直接用tcpdump会话边界与媒体端口2.1 信令端口固定媒体端口动态协商按端口过滤必然漏很多同事排查通话问题第一反应是 tcpdump -i eth0 -n port 5060。这个命令能抓到INVITE和BYE但抓不到语音因为RTP端口是SIP消息的SDP里随机选的。我见过最典型的翻车现场抓了半小时pcap 20多MB打开一看全是5060信令和一堆重传RTP一个没有。用户反馈“我说了三分钟话你抓回来怎么只有握手”——因为媒体在高位端口压根没进过滤条件。如果为了抓RTP把高位端口范围加进过滤比如 udp portrange 10000-20000那结果更糟。同一时间网络上其他应用也在这个范围内P2P、视频流、游戏全被混进pcap。Wireshark打开后卡死分析效率为零。说到底tcpdump是“看到什么抓什么”理解不了SIP会话里哪个包属于哪通电话更不知道媒体的真实地址是SDP协商出来的。pcapsipdump的思路是让工具去“读”SIP。它跟踪每个从INVITE开始的会话解析SDP里的c行和m行拿到RTP的IP与端口之后只捕获这条会话相关的包。所以不管媒体协商到10080还是65530它都能精准命中。这才是VoIP抓包该有的样子。2.2 同一个Call-ID跨信令与媒体等多条数据流SIP通话不是一条连续的数据流而是信令UDP流和若干条RTP流交织在一起。从INVITE开始中间有100 Trying、180 Ringing、200 OK、ACK最后BYE。通话中还可能出现re-INVITE、UPDATE、INFO甚至换编码和换端口。tcpdump把这一切都写成一个大文件事后找一通电话得先用Wireshark按sip.Call-ID过滤再手动分清哪些包是信令、哪些是媒体。pcapsipdump把同一Call-ID范围内的所有包写入单独文件文件名带时间戳。这样找通话像翻相册用户说“10点20分那通电话有杂音”去抓包目录按文件名一翻就能定位。更重要的是re-INVITE后RTP端口变了tcpdump按旧端口过滤就会切掉后半段媒体pcapsipdump会跟随SDP更新继续把后续RTP写进同一会话文件保住整通电话的原始证据。另一个容易忽略的点是early media。很多呼叫流程里被叫在180 Ringing时就已经开始播放回铃音或彩铃这段早期媒体发生在200 OK之前。tcpdump如果只抓5060端口这段媒体就直接丢了。pcapsipdump因为从INVITE响应里就解析SDP所以从第一个180开始就能正确关联媒体不会出现“信令完整但媒体前几秒没了”的情况。2.3 与tcpdump、ngrep的对比各有各的活工具适合场景不适合场景tcpdump网络层诊断、确认丢包/重传/分片按SIP会话切片、多媒体口跟踪ngrep在线过滤SIP头字段快速确认某个头保存完整信令媒体、长时间录制pcapsipdump长期录制SIP/RTP、按会话回放非SIP协议、通用流量分析pcapsipdump的边界很清楚它只对SIP和RTP会话感兴趣其他流量基本忽略。如果你查的是TCP建链、TLS证书、MTU分片应该用tcpdump如果你只想在线看一眼某个Authorization头有没有带错ngrep更快。但要做通话级录制和事后回放pcapsipdump比前两者都顺手。我线上长期抓包时会同时跑两个进程pcapsipdump负责把每通电话录成独立pcaptcpdump只抓几个固定端口做网络层参照。比如怀疑公网丢包tcpdump能给出整体流量统计pcapsipdump能给出具体会话的完整包。两个文件一对比就能区分是网络丢包还是SIP业务异常。这个组合我用了很久比单靠一个工具排查快得多。3. 从pcapsipdump-0.2.tar.gz开始编译依赖、改错、装完验证3.1 解压并确认版本与目录结构我习惯把抓包工具源码放在 /opt/src而不是直接堆在root目录。解压命令mkdir -p /opt/src cd /opt/src tar zxvf pcapsipdump-0.2.tar.gz cd pcapsipdump-0.2 ls -latar zxvf含义是z 用gzip解压x 解包v 显示过程f 指定文件。解压后目录里一般有源码、Makefile和README。0.2这个版本代码量不大Makefile是裸写的没有autoconf生成的configure脚本所以不需要执行configure直接make。但正因如此依赖路径和编译参数得自己看一眼。先看README再翻Makefile。重点确认两件事一是安装前缀默认可能是/usr/local二是头文件路径是不是标准/usr/include。如果你的libpcap装在/usr/local/libMakefile里没有指定 -I 和 -L后面编译就会因为找不到头文件或库而失败。提前看能省不少时间。3.2 依赖检查libpcap-dev是硬前提pcapsipdump的抓包核心是libpcap所以编译前必须装开发包。Debian/Ubuntu上包名是libpcap-devRHEL/CentOS上是libpcap-devel。光有运行库libpcap.so.1不够必须有pcap.h头文件。# Debian/Ubuntu apt-get install -y build-essential libpcap-dev # RHEL/CentOS yum install -y gcc make libpcap-devel装完可以验证pcap-config --version || echo libpcap-devel not found ls /usr/include/pcap.h /dev/null 21 echo header ok || echo header missing这里有个常见误区如果你只 yum install libpcap装的是动态库文件没有pcap.h和链接用的libpcap.so链接文件。编译时gcc会报找不到头文件或-lpcap失败。所以我一般装完devel包后会顺手跑一下pcap-config --libs确认编译参数能拿到。pcap-config不存在多半是devel没装好别急着改Makefile先补包。3.3 make与常见编译错误处理依赖齐了直接makecd /opt/src/pcapsipdump-0.2 make顺利的话当前目录会生成pcapsipdump二进制。看到错误也别慌常见就三类一是pcap.h: No such file or directory说明头文件路径不对或没装devel。解决确认pcap.h位置如果确实装在了/usr/local/include在Makefile的CFLAGS里加-I/usr/local/include。二是undefined reference to pcap_*说明库路径或库名不对检查LDFLAGS里-lpcap是否在并确认有libpcap.so链接文件。三是较新的GCC对源码里的字符串写法会报warning比如format not a string literal这类警告不影响生成二进制可以忽略。编译通过后先验证文件类型file pcapsipdump输出应为ELF可执行文件。接着安装make install正常会复制到/usr/local/bin。如果只想先试用也可以不安装直接在源码目录运行./pcapsipdump。我在前期调试时都这么干避免一个小工具污染系统。3.4 静态编译与动态链接的选型如果要把pcapsipdump带到其他机器排查我建议静态编译。0.2默认是动态链接libpcap生成的二进制拷到别的机器上可能因为缺libpcap.so.1跑不起来。改成静态编译make clean make CFLAGS-static -O2 LDFLAGS-static -lpcap -lpthread file pcapsipdump | grep statically注意静态编译需要libpcap静态库libpcap.adevel包一般自带。如果报找不到libpcap.aRHEL系可以额外装libpcap-static。静态版本体积大一些但好处明显拷到同架构的Linux机器上直接能跑不怕现场缺运行库。我应急U盘里就放了一个静态编译版到客户现场解压即用。3.5 装完最少要跑通的验证动作装完别急着扔进生产先在测试网卡上跑一下./pcapsipdump 21 | head -20如果程序正常会打印用法或版本信息。如果提示error while loading shared libraries说明动态库缺退回静态编译或补齐libpcap运行库。确认可执行后再用-daemon方式或nohup后台跑。我一般还会做一个最简单的冒烟测试在环回口跑一个10秒抓包再配合socat或本地SIP软交换产生一个INVITE看输出目录是否生成pcap。只有这一步过了才敢说编译环境没问题。到这一步pcapsipdump-0.2.tar.gz才刚刚算装好了。4. 上手抓包pcapsipdump的常用参数与最小可用命令4.1 最小抓包命令按会话切片保存到指定目录装好后的最小可用命令mkdir -p /var/spool/sipdump pcapsipdump -i eth0 -d /var/spool/sipdump -m 100M -t 600这个命令的含义-i eth0指定抓包网卡-d指定pcap输出目录-m 100M限制单个会话pcap最大100MB-t 600表示会话空闲600秒后自动关闭文件。跑起来后用话机发起一通呼叫挂断后去目录查看应该能看到新的pcap文件。-m和-t是我特别强调的两个参数。没有-m一通挂在电话会议上的通话会一直写RTP文件越来越大没有-t很多BYE丢失的悬挂会话会一直占着文件句柄。加了这两个参数后长期挂在SBC旁边才不会出问题。注意-m到上限后是滚动生成新文件不是覆盖旧文件所以磁盘空间仍然要按总量核算。4.2 关键参数详解网卡、输出目录、超时、并发下面是我常用的参数表实际编译时可能因宏配置略有差异但0.2版本主流程基本一致参数作用我一般怎么设-i eth0抓包网卡抓业务网卡别选管理口-d /var/spool/sipdumppcap输出目录单独挂一个大分区-m 100M单个会话pcap大小上限100M或500M看平均通话时长-t 600会话空闲超时秒数600防止悬挂会话占用FD-c 10000最大并发会话数按峰值呼叫量估算-p /var/run/pcapsipdump.pidpid文件用脚本管理时方便stop-v版本/详细信息排错时用-c并发上限是保护项。当大量陌生电话打进来时每个新Call-ID都要建文件和索引文件句柄消耗很快。如果ulimit -n默认1024而并发通话一多进程就会报Too many open files。所以我启动前会先ulimit -n 65535再把-c调到一个合理值不是越大越好而是要与FD数匹配。-d的输出目录建议用独立分区。抓包文件是持续写入的如果和系统日志挤在同一个分区一次长时间抓包就能把根分区撑满导致系统卡死。我一般用单独的/data/sipdump挂载点并配logrotate定期处理。4.3 输出目录里的pcap、索引和当前会话清单抓包目录里通常有三种东西pcap文件、与pcap同名的索引文件以及记录当前活动会话的状态文件。索引文件是pcapsipdump的增量价值它存了每个包在pcap里的偏移和时间戳用于快速定位。文件名后缀可能因版本而异常见的是.idx或.index关键是pcap和索引要同名、同目录。千万不要手动删索引。虽然删了还能用Wireshark硬读pcap但按时间跳转和自动化定位能力会丢。如果索引坏了把同名的pcap留作原始证据重新生成索引或让程序重建。我处理过几次索引损坏都是因为进程被kill -9杀掉索引没来得及落盘。所以正常停进程要用SIGTERM别随手kill -9。4.4 按Call-ID定位从一堆文件里捞一通电话用户报障通常给的是大概时间不是文件名。找一通电话最快的方法是先用ls按时间排序ls -lt /var/spool/sipdump找到可疑时间段的pcap后用sngrep读取并看呼叫流程sngrep -r /var/spool/sipdump/2024-06-01-10-20-00.pcap如果有多个pcap可能包含通话先用tshark提取Call-IDtshark -r /var/spool/sipdump/2024-06-01-10-20-00.pcap -Y sip -T fields -e sip.Call-ID 2/dev/null | sort | uniq这样能确认哪几个文件属于同一通电话。实际上一通异常电话的完整信令可能跨两个文件比如re-INVITE后tag改变pcapsipdump会按规则拆分。只看一个文件容易误判所以我会汇总Call-ID后再分析。4.5 抓包过滤加BPF表达式时最容易坑到自己pcapsipdump支持在启动命令里追加BPF表达式类似tcpdump的写法。这个功能很有用但也最容易把媒体抓丢。比如想只看某个IPpcapsipdump -i eth0 -d /var/spool/sipdump -m 100M host 192.168.1.10这样信令和媒体都会被限定到该IP没问题。但如果你写成udp port 5060那媒体包全部不会进入会话匹配就算抓下来也只有信令。我见过有人为了降低流量这么干结果所有pcap里都没有RTP回放全是静音。用BPF时记住过滤条件只能缩窄主机和网段不要把端口限制在5060上。另一个相关坑是抓包网卡没开混杂模式。pcapsipdump基于libpcap默认会尝试打开混杂模式但在虚拟化环境下如果交换机端口没配置镜像或者云主机安全组只放行本机地址那它就只能抓到自己收发的包。确认流量路径比调参数更重要否则抓包进程跑多久都是白跑。5. 避坑与排查pcapsipdump用不起来的五个常见现场5.1 抓了半天没有pcap文件生成现象pcapsipdump进程活着话机呼叫也正常但输出目录一直为空。原因最常见是SIP信令不走默认的5060端口或者抓包网卡不在流量路径上。如果SIP用的是5061TLS或自定义端口pcapsipdump默认监听的是UDP 5060自然识别不到。另一个原因流量在eth1上你抓的是eth0。解决先用tcpdump确认流量确实到了抓包网卡tcpdump -i eth0 -n udp port 5060 -c 10如果能看到包再看pcapsipdump启动命令里有没有加BPF限制。如果确实是非标端口要确认你用的pcapsipdump版本是否支持自定义SIP端口或者用iptables把非标端口流量转向/镜像到默认端口。很多临时排障我就是直接在接入交换机做RSPAN镜像把流量引到抓包口比改应用省事。5.2 一通电话被拆成了多个pcap文件现象一个通话的完整信令分散在好几个pcap里每个文件只有一部分。原因SIP会话的Call-ID相同但tag不同比如通话中发生re-INVITE后某些话机或B2BUA会生成新的From/To tag。pcapsipdump如果按Call-ID加tag作为会话主键tag一变就会认为新会话于是开新文件。另一个常见原因是媒体协商走了不同传输路径比如信令直达、媒体过代理导致媒体不被识别。解决先确认呼叫路径里有没有B2BUA比如SBC或网关。跨B2BUA抓包时前后两段是不同的Call-ID这不算bug是业务模型决定的。遇到re-INVITE引起拆分看编译或运行时有没有“仅按Call-ID匹配”的选项有就打开。实在不行事后用mergecap把同一通电话的几个文件合并mergecap -F pcap -w /tmp/call.pcap 2024-06-01-10-20-00.pcap 2024-06-01-10-20-15.pcap合并后再按时间排序基本能还原完整会话。注意不要乱合并只合并确认属于同一Call-ID的文件。5.3 单通RTP只抓到一个方向现象pcap里有双向SIP信令但RTP只有A到B或者只有B到A回放时只有一路声音。原因最常见是RTP流量走了不同路径。比如A在局域网B在公网NAT后面媒体经过RTP代理信令却直连。抓包点只覆盖了其中一路。还有一种可能是交换机镜像口只做了单向镜像RSPAN配置没带双向。解决抓包点要尽量放在SBC、网关或核心交换机的镜像口这样才能同时看到双向媒体。如果只能抓单端就不要期待拿到双向RTP。另外检查SDP里的c地址与实际RTP源地址是否一致。NAT场景下SDP里写的是内网地址实际媒体来自公网地址pcapsipdump可能因为地址不匹配而没把RTP归入会话。这种情况可以在网络出口抓包或者在终端上关闭SIP的NAT变换功能后再试。5.4 长时间运行后文件句柄耗尽现象进程没退出但新呼叫不再产生文件日志或shell里报Too many open files。原因没设-t超时大量BYE丢失的悬挂会话一直占着FD-c并发上限设置得太高实际把进程FD用满系统默认ulimit -n是1024一个VoIP网关上的流量很容易击穿这个值。解决启动脚本里加ulimit -n 65535再给pcapsipdump加上-t 600。日常用下面命令监控FD数lsof -p $(pgrep pcapsipdump) 2/dev/null | wc -l如果这个数只涨不降说明有会话没被超时回收。我遇到过一次单通异常电话引发的悬挂会话占了两千多个FD新呼叫全被拒绝最后只能在维护窗口开启自动重启。重启会丢正在进行的会话文件所以要放在业务低谷做。更好的做法是写个看门狗FD数超过阈值就告警并重启。5.5 索引文件损坏与时间戳漂移现象pcap能打开但用索引做时间定位时跳转不对或者显示的时间与实际通话时间差几分钟。原因索引文件在进程被SIGKILL后没有落盘导致索引不完整。时间戳漂移多半是网卡开启了TSO、GRO或RCO网卡在硬件层对包做了聚合或批量提交抓包时间戳会偏离真实时间。对信令顺序分析影响不大但算呼叫时延会得出错误结论。解决索引损坏时如果能找到对应版本的reindex工具重新生成不行就删掉索引损耗的是自动定位能力不损耗包数据。时间戳漂移问题用ethtool关掉offloadethtool -K eth0 tso off gso off gro off关掉后重新抓包时间戳就准了。注意这个命令在部分虚拟网卡上不支持会报Operation not supported那就要从宿主机层面调整或放弃高精度时间测量。5.6 大流量下的内核丢包抓包进程自己成了瓶颈现象pcapsipdump持续跑着但pcap里的包数远小于交换机镜像实际流量信令和媒体都有缺失。原因libpcap抓包在万兆或大量小包场景下单进程可能跟不上中断速率。内核socket接收缓冲区满了以后直接丢包libpcap层面看不到任何错误。这个问题在抓SIP大流量时很容易出现尤其是几百路并发通话时。解决一方面调大内核ring buffercat /proc/net/core/rmem_max sysctl -w net.core.rmem_max134217728另一方面把pcapsipdump进程绑定到独立CPU或者用多队列网卡分别抓不同VLAN降低单卡压力。再不行减少BPF无关流量进入抓包路径。总之要认识到pcapsipdump是业务层录制不是底层探针大流量下丢包不能只怪工具。6. 进阶技巧把pcapsipdump接到自动化和sngrep验证里6.1 用Shell脚本监听目录并及时归档pcapsipdump本身不清理文件我会配一个归档脚本#!/bin/bash DUMP_DIR/var/spool/sipdump DATE_DIR$(date %Y%m%d) mkdir -p $DUMP_DIR/archive/$DATE_DIR find $DUMP_DIR -maxdepth 1 -name *.pcap -mmin 30 -exec mv {} $DUMP_DIR/archive/$DATE_DIR/ \; find $DUMP_DIR/archive -type f -mtime 30 -delete脚本逻辑先建当天目录把超过30分钟不再写入的pcap移入归档再删30天前的文件。30分钟这个值大于会话空闲超时确保文件已经写完。移动正在写的文件会导致内容截断所以如果之前没设-t这里可能踩坑。6.2 用sngrep验证一通电话的SIP时序归档后不分析等于没抓。我用sngrep看单个pcap里的信令时序sngrep -r /var/spool/sipdump/archive/20240601/2024-06-01-10-20-00.pcap只看INVITE、180、200、ACK、BYE的先后顺序就能快速判断问题方向。只有INVITE没有响应是路由或认证问题出现大量重传是网络丢包看到486 Busy是被积极拒绝。sngrep比Wireshark启动快适合每天巡检几百个文件。6.3 检查抓包完整性按Call-ID做跨文件汇总最后分享一个验证方法。我曾在一次排障中只打开了一个pcap发现丢了一半语音后来才意识到后半段写在另一个文件里。从那以后我统一用Call-ID做跨文件汇总for f in /var/spool/sipdump/archive/20240601/*.pcap; do tshark -r $f -Y sip -T fields -e sip.Call-ID 2/dev/null done | sort | uniq -c | sort -rn如果一个Call-ID的包数异常少比如只有INVITE没有BYE就单独挑出来深查。这个习惯帮我少踩了很多“误判丢包”的坑。希望帮到你。本文还有配套的精品资源点击获取