做 BLE 开发这几年,抓包工具就是我的另一双眼睛。不管是调试连接参数、看广播包格式、排查断连原因,还是确认手机和从机之间到底聊了什么,没有一套顺手的抓包环境,基本等于盲人摸象。在众多方案里,PC 端 Wireshark 配合 nRF52832/nRF52840 Sniffer Dongle 算是性价比最高、用得最多的一套组合,但说实话,它的环境配置并不像装个 QQ 那么无脑。我印象最深的一次,光把 dongle 固件烧进去、让 Wireshark 认出来,就折腾了一整个下午,最后发现是驱动和插件版本不对付。这篇文章就把我踩过的坑、试出来的解决办法,以及日常抓包分析的一些小习惯,一次性整理出来,给正在被这套环境折磨的朋友一个参考。
1. 环境搭建的整体思路与组件盘点
1.1 这套抓包方案由哪几部分组成
很多人第一次接触 BLE 抓包,容易以为“买个 dongle 插上电脑就能抓”,真上手才发现,要正常跑起来,背后其实是四层东西在协作:硬件 dongle、板载固件、PC 端驱动、上位机软件 Wireshark 及其插件。哪一层出问题,表现都是“抓不到包”或者“设备不识别”,但排查路径完全不同。
具体来说,硬件是 nRF52832 或 nRF52840 核心的 USB dongle(最常见的是 Nordic 官方的 nRF52840 Dongle,也就是 PCA10059,还有第三方做的 52832 版本)。固件方面,官方提供的是 nRF Sniffer for BLE 的 hex 文件,需要烧录进 dongle 后,它才能把空中的 2.4G BLE 数据包抓下来并通过 USB 转成逻辑帧送给 PC。PC 端需要有对应的串口驱动,比如 dongle 上用的 J-Link OB 芯片或者直接 USB CDC 枚举出来的 COM 口。最后,Wireshark 里要装 Nordic 提供的 nRF Sniffer 插件,插件以 extcap 的方式工作,把串口数据解析成 Wireshark 能识别的 pcap 格式。
这四层里,最容易出问题的就是固件和插件版本不匹配。我见过太多人把最新版 Wireshark 和旧版 nRF Sniffer 插件搭在一起,结果 extcap 接口在 Wireshark 里根本不显示。所以搭建之前,最好先把“固件版本 + 插件版本 + Wireshark 版本”这个三角关系理顺,后面能少走很多弯路。
1.2 为什么推荐 nRF52 系列而不是其他抓包器
市面上 BLE 抓包硬件其实不少,有国产的、有 TI 的 CC2540 方案的、也有高端一点的 Ellisys 或 Frontline 协议分析仪。但 nRF52 系列 dongle 能被大家广泛使用,我认为核心优势有三个:
第一是价格友好。官方 dongle 或者其他基于 nRF52840 的 USB 棒子,几十块到一百多块就能搞定,对比动辄上万的专业协议分析仪,学习成本和试错成本都很低。
第二是抓包能力够用。nRF52840 支持 BLE 5.0,能抓 1M、2M PHY,也支持 Coded PHY(125k/500k),对于绝大多数 BLE 开发调试场景——广播、扫描、连接、配对、GATT 读写——已经完全够用。nRF52832 虽然只支持 BLE 4.x 的 1M PHY,但抓个基本连接、看看广播包也绰绰有余。
第三是软件生态成熟。Nordic 出了配套的 nRF Connect for Desktop,里面直接集成了 Programmer 和 Sniffer 相关的工具,最方便的是它能把 dongle 刷成 Wireshark 可识别的工作模式。再加上 Wireshark 本身对 BLE 协议解析的支持已经很完善,两者配合,基本等于拿一台“民用协议分析仪”。
不过我要提前打个预防针:这套方案本质上是“单信道抓包”,也就是一次只能抓到 dongle 所在信道的空中数据。BLE 连接会跳频,所以你抓到的包并不完整。这是硬件方案的通病,不是配置问题。理解这一点,后面抓连接过程的时候就不会一头雾水了。
2. 驱动与设备识别问题:从“插上没反应”到“稳定出包”
2.1 dongle 插上后毫无反应,先别急着怪硬件
我先说一个最常见也最让人崩溃的场景:dongle 插上电脑,设备管理器里啥也没多,或者多了一个带黄色感叹号的未知设备。这时候大概率不是硬件坏了,而是固件状态不对,或者驱动没对上。
nRF52840 Dongle 出厂时默认跑的是 bootloader,首次插上电脑,在设备管理器里会看到一个叫 “OpenBootloader” 或者类似的 USB 设备。这个状态下,你是没法直接用它抓包的,必须先把 Sniffer 固件烧进去。如果你是在设备管理器里看到一个未知设备,可以先右键属性看一下硬件 ID,如果 VID 是 0x1915(Nordic 的 USB Vendor ID),那基本就可以确认是 Nordic 设备,只是驱动和固件的问题。
另一个常见情况是:之前用这个 dongle 刷过其他固件,比如跑过 Zephyr 的 BLE 示例或者当普通串口用过,再插回来发现 Wireshark 不认。这就需要用 nRF Connect for Desktop 里的 Programmer 工具重新烧回 Sniffer 固件。我自己的习惯是,专门拿一个 dongle 只当 Sniffer 用,不拿它刷乱七八糟的例程,免得每次换固件都要重新折腾一遍驱动识别。
2.2 串口驱动选不对,Wireshark 永远看不到接口
如果设备管理器里已经能看到一个 COM 口了,但 Wireshark 的接口列表里就是没有 nRF Sniffer 相关的入口,这时候问题多半出在驱动类型上。
nRF52840 Dongle 官方固件在烧录成功后,会以 USB CDC ACM 的方式枚举出一个串口。Windows 10/11 系统一般会自动装一个 “USB 串行设备” 的驱动,但某些精简版系统或者装了其他串口工具的电脑,可能会被占掉或者装错。我的经验是:如果 COM 口能正常识别,但 Wireshark 里就是不出接口,先去设备管理器里看看这个 COM 口是不是被识别成了 “通信端口”,右键属性 → 驱动程序详细信息,看驱动文件是不是 usbser.sys。如果是别的什么第三方驱动,尤其是某些 USB 转串口芯片的万能驱动,会干扰 extcap 的正常调用。
另外要提一个很多人忽略的点:nRF Connect for Desktop 自带的 J-Link 驱动有时候会和 dongle 的 USB CDC 串口冲突,导致设备反复枚举。解决方法是去设备管理器里,把那个“J-Link CDC UART Port”禁用一个,只保留一个 COM 口给 Wireshark 用,不然 extcap 会随机选到一个不对的串口,结果就是抓包界面起得来,但一包数据都没有。
2.3 设备管理器操作速查:一步步排查驱动状态
这里我直接给一个排查顺序,照着走基本能把“插上没反应”这类问题解决掉:
- 插上 dongle,打开设备管理器,看在“端口 (COM 和 LPT)”里有没有出现 COM 口。如果出现了,说明 USB 枚举和串口驱动都正常,问题在 Wireshark 插件层。
- 如果出现在“其他设备”或者“通用串行总线设备”里,右键更新驱动,手动指定驱动路径到 C:\Windows\System32\drivers 下的 usbser.sys,或者直接卸载设备后重新插拔,让系统重新枚举。
- 如果连设备都没有,换个 USB 口,最好是直连主机后置口,别用前置面板或者 USB Hub。我遇到过因为 USB Hub 供电不稳导致 dongle 反复掉线的问题,后来插主机后面就再没犯过。
- 确认无误后,打开 nRF Connect for Desktop 的 Programmer,看能否识别到设备。如果 Programmer 能读到设备信息,基本说明硬件链路没问题。
最后一步也是我强烈建议做的:烧录完固件后,拔插一次 dongle,让设备重新枚举。因为固件切换不会自动触发 USB 重枚举,有时候你以为没烧成功,其实就是没拔插。
3. 固件烧录与 Wireshark 插件版本匹配:最常见的坑都在这
3.1 烧录工具选哪个:nrfutil 命令行还是图形化 Programmer
烧录 Sniffer 固件有两种主流方式:用 Nordic 官方的 nrfutil 命令行工具,或者用 nRF Connect for Desktop 里的 Programmer 图形界面。对新手来说,我推荐用图形化 Programmer,因为可以看到烧录进度和结果,也减少输错命令的风险。
但如果你用的是第三方 nRF52832 dongle,尤其是那种不带 USB bootloader 的版本,可能没法直接通过 USB 烧录。这时候需要用到 SWD 调试接口,也就是拿一个 J-Link、DAP-Link 之类的调试器,配合 nrfutil 或者 Keil、IAR 烧录。nRF52832 的 dongle 一般会引出 SWD 的 4 个引脚(SWCLK、SWDIO、GND、VDD),用杜邦线连上调试器就行。注意 nRF52832 烧录时,如果芯片有保护位,可能需要先用 nrfjprog --recover 解锁,不然会报错。
如果你用的是 nrfutil 命令行方式,核心命令是:
nrfutil dfu usb-serial -pkg sniffer_ble_3.2.0.zip -p COM5这个命令适用于 dongle 里已经有 DFU bootloader 的情况。它会通过串口把 zip 包里的固件烧进去,烧完自动运行。注意这里 -pkg 参数要求的是 zip 包而不是 hex 文件,很多新手卡在这一步,不知道去哪里找 zip 包。其实 Nordic 官网下载的 nRF Sniffer for BLE 安装包里,除了 hex 文件,还带了一个 zip 格式的 DFU 包,专门用来给 bootloader 升级用的。
3.2 Wireshark 版本和 nRF Sniffer 插件版本的匹配关系
版本匹配这件事,我放在最后说,但它是所有坑里最坑的一个。nRF Sniffer 插件的 extcap 接口依赖 Wireshark 的 extcap 框架,而 Wireshark 不同版本之间对 extcap 的接口规范有过变化,导致旧版插件往往无法在新版 Wireshark 里正常加载。
以我实际测试的情况,给出一个保守的搭配表:
| Wireshark 版本 | nRF Sniffer 插件版本 | 实测结果 |
|---|---|---|
| 4.0.x / 4.2.x | 3.2.0 | 正常 |
| 3.6.x | 3.1.0 / 3.2.0 | 正常 |
| 3.4.x | 3.1.0 | 正常 |
| 3.2.x 及更早 | 2.x / 3.0 | 需确认具体版本 |
这个表不是绝对的,因为 Nordic 在新版插件里也修复了不少旧 Wireshark 的兼容问题,但如果你用的组合特别新或特别旧,建议优先按表里的组合试。插件的安装路径在 Windows 上一般是 C:\Program Files\Wireshark\extcap,安装完插件后一定要完全退出 Wireshark 再重开,不是关闭窗口,而是确认进程管理器里没有 Wireshark 在跑,否则 extcap 不会重新加载。
还有一个细节:有些用户装插件时会把整个文件夹放错位置,导致 Wireshark 的接口列表里多了个灰色的 “nRF Sniffer for BLE” 但怎么点都报错。这种情况直接去 extcap 目录看看有没有 nrf_sniffer_ble.py 文件,或者对应的 exe 文件。插件没放全、依赖的 Python 环境不对,都会导致这种“看得到用不了”的症状。
3.3 烧录完成后,Wireshark 里怎么确认环境就绪
烧完固件、装好插件、重开 Wireshark 之后,正确的检查步骤是这样的:
在 Wireshark 首页的接口列表里,应该能看到一个叫 “nRF Sniffer for BLE” 的接口,点旁边的齿轮图标可以设置信道、包过滤等参数。双击接口进入抓包界面后,在显示过滤器里输入btle,应该能看到一堆广播包或者数据包在滚动。如果界面上方显示 “No packets captured” 但设备明明在发广播,多半是信道没选对,或者 dongle 固件没跑起来。
另外,抓包界面有一个专门的 “Nordic BLE Sniffer” 工具栏,里面可以选 Advertising 信道(37/38/39)或者 Follow 一个连接。如果这个工具栏没出现,可能是在视图 → 界面工具栏里被隐藏了,勾选出来就行。Wireshark 4.x 版本默认不显示所有工具栏,这个细节能卡住不少人。
我建议烧完固件后,先用手机开一个 BLE 调试助手,随便发点广播数据,再回到 Wireshark 里看能不能抓到手机发出的广告包。能抓到,说明整条链路已经通了;抓不到,优先检查信道选择,手机广播默认在 37/38/39 三个信道上轮流发,你如果固定在一个信道上,有概率漏掉。
4. 抓包过程疑难杂症与数据分析技巧
4.1 为什么抓不到广播包,或者抓到的包断断续续
这个问题我把原因分成三类,大家可以对照自查:
第一类是硬件问题。dongle 天线周围有金属遮挡、USB 线过长导致供电不足、或者电脑 USB 口本身供电不稳,都会让 dongle 灵敏度下降。我试过用一个延长线把 dongle 放到离被测设备更近的位置,抓包成功率明显提升。另外,如果同时插了多个 USB 3.0 设备,2.4G 频段的干扰会非常大,因为 USB 3.0 的时钟谐波正好落在 2.4GHz 附近,这个干扰是实打实的。
第二类是信道问题。BLE 广播数据在 37、38、39 三个信道上轮发,连接数据则在 0 到 36 号数据信道上跳频。Sniffer dongle 单次只能监听一个信道,所以如果 dongle 停在 37 信道,手机在 38 信道发广播,你就抓不到。解决办法是:抓广播时,把 Sniffer 设置成 “All Advertising Channels” 模式,它会在这三个信道间快速切换;抓连接时,要用 “Follow” 模式锁定一个连接,让 dongle 模拟从机跟着主机跳频。
第三类是软件层面的过滤。Wireshark 默认的显示过滤器可能会过滤掉你不关注的数据,比如你只输出了btle过滤器,但有些广播包是带 CRC 错误的,在 Wireshark 里会被标成坏包并默认不显示。这时候需要在显示过滤器里加上!btle.advertising_header.crc_bad,把坏包也显示出来,方便排查信号干扰问题。
4.2 连接包抓不全?这是单信道抓包的物理限制
很多人在抓连接过程的时候会发现一个现象:广播连接请求(CONNECT_IND)抓到了,但连接建立后的数据包断断续续,隔几个事件才冒出来一个。这不是配置问题,而是 BLE 连接本身的跳频机制决定的。
BLE 连接建立后,主从双方会按照一个伪随机序列在 37 个数据信道间跳频,每次连接事件换一个信道。你的 Sniffer dongle 只有一个射频前端,同一时间只能守在一个信道上,所以不可能把每个连接事件都抓到。官方的 Sniffer 固件在 Follow 模式下,会通过监听 CONNECT_IND 里的 Channel Map 和 Hop Increment 等信息,计算出下一次连接事件在哪个信道上,然后提前跳过去等包。但因为时序同步有误差,或者设备修改了连接参数,经常会出现“跟上了一个事件,丢了下一个”的情况。
应对办法也比较实用:
- 尽量让 dongle 靠近从机端,因为从机是在 CONNECT_IND 之后才切换信道,信号相对容易跟上;
- 把抓包时长拉长,多抓几个连接事件,截取关键帧分析;
- 结合从机端的日志(比如用 RTT 或者串口打印)来互补,Sniffer 拿射频层数据,日志拿协议栈状态,两边对照,能拼出完整图景。
另外要说一点,nRF Sniffer for BLE 的 Follow 功能并不是百分百可靠,尤其在连接参数更新(Connection Parameter Update)之后,它需要重新同步。实际工作中,如果遇到 Follow 跟不上,我一般会退回“守某一两个常用信道”的方式,虽然拿不到完整连接数据,但至少能看到广播、扫描请求这些低频类型。
4.3 解密配对后的数据包:LTK 从哪里来、怎么填
抓到了连接数据,但如果设备之间做了配对加密,你会发现 Wireshark 里的 ATT/GATT 数据全部是加密后的密文,根本看不懂。这时候需要把配对过程产生的 LTK(Long Term Key)喂给 Wireshark,它才能解密后面的数据。
获取 LTK 的方式有几种:如果你是做嵌入式端的开发,最常见的办法是从协议栈里把 LTK 打印出来。比如用 Zephyr 的bt_conn_info或者 Nordic SDK 里的pm_peer_data_load接口,在配对完成后把 LTK 以十六进制形式打出来,然后填进 Wireshark。如果是手机和从机配对,就得从手机端想办法,iOS/Android 一般拿不到,所以实际工作中更多是在从机端抓。
在 Wireshark 里填 LTK 的位置是:编辑 → 首选项 → Protocols → BLE,然后找到 “Decryption keys” 部分,添加一条记录,Key 类型选 LTK,值填 32 位十六进制数。填完之后 Wireshark 会自动用这个 LTK 解密后续的加密包。注意一点:需要配合配对过程中产生的 SKD(Session Key Diversifier)和 IV,Wireshark 才能正确派生会话密钥。但 nRF Sniffer 插件会自动从空中抓到这些参数,你只需要填 LTK 就够了。
实测下来,最容易出错的坑是 LTK 填反了端。BLE 配对后,主从两端各自持有一份相同的 LTK 用于加密,但安全分发时还有 EDIV 和 Rand 来区分哪一端。Wireshark 里填 LTK 时默认按“本地设备”处理,如果你是从从机端抓包,但把主机端的 LTK 填进去了,解密会失败。我一般建议:从设备协议栈里拿到 LTK 后,先看一下它是哪一端的,填到 Wireshark 后立刻发一个 Read Request 测试,能解出来就对了,解不出来换另一端试试。
4.4 双 dongle 协作抓包:把单信道变“伪双信道”
前面说过单信道抓包有物理限制,那有没有办法提升覆盖率呢?有,而且成本不高。如果你手头有两个 nRF52 dongle,可以同时插在电脑上,分别打开两个 Wireshark 实例,一个 dongle 设为在新连接事件中优先跟随主机,另一个跟随从机视角。虽然不可能做到全覆盖,但两个 dongle 同时守在不同信道,能显著提高抓到连接事件的比例。
这个方法在分析连接参数更新、断连原因、多连接并发时特别好用。比如排查“设备连接后 5 秒必断”问题,单 dongle 抓到的包可能刚好错过了断开那一刻的信道,双 dongle 至少多一倍的覆盖率。
操作上有个小技巧:两个 Wireshark 实例分别用不同的显示过滤器,一个只看 HCI 事件和控制 PDU,另一个只看 ATT/GATT,这样可以减少视觉干扰,也方便对照时间戳。另外 Wireshark 支持把抓包结果导出为 CSV 或者 pcap,两个实例抓完后可以用 mergecap 合并成一个文件,再统一分析。
4.5 常用过滤器和显示技巧:别在密密麻麻的包里迷失
最后分享几个我日常高频使用的过滤器和界面设置,能明显提高分析效率。
- 只看广播包:
btle.advertising_address存在,或者用btle.type == 0(ADV_IND 等广播类型)。 - 只看某个设备的包:
btle.advertising_address == 12:34:56:78:9a:bc或者btle.master_address/btle.slave_address。设备地址是蓝牙地址,注意是小端格式显示,Wireshark 会直接解析好,不用手工翻转。 - 只看连接相关的包:
btle.type == 5(CONNECT_IND 类型),配合btle.ll_control_opcode可以看连接参数更新、LL_VERSION_IND 等控制 PDU。 - 只看 ATT 读写操作:
att.opcode存在,再配合att.handle过滤某个具体句柄的读写。 - 快速定位抓包起点:可以用
frame.time_relative > X这种时间过滤,但更推荐直接在 Wireshark 的 IO Graph 里,按 btle 包类型做一个简单统计,看整个抓包周期里的流量分布,能快速找到异常点。
显示方面,我建议在首选项里把 BLE 协议的时间显示改成 “Seconds since beginning of capture”,配合相对时间分析连接间隔、扫描间隔这些时序参数会非常直观。另外,Wireshark 的颜色规则里可以自定义一下:把 CONNECT_IND 标成醒目的颜色,把 MIC 错误或者 CRC 错误的包标成红色,一打开就知道哪里出了问题。
5. 常见问题速查表与避坑心得
5.1 配置问题速查表
把前面散落在各个章节的问题汇总成一张表,方便遇到问题时按图索骥。
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| 插上 dongle 设备管理器无任何反应 | USB 枚举失败、dongle 处于 bootloader 状态 | 换 USB 口、重新插拔、用 Programmer 烧录固件 |
| 设备管理器显示未知设备或黄叹号 | 驱动未正确安装 | 右键更新驱动,指定 usbser.sys 或重装 Nordic USB 驱动 |
| Wireshark 接口列表没有 nRF Sniffer 入口 | 插件没装对、extcap 目录不对、Wireshark 未完全重启 | 检查 extcap 目录,重装插件,确认进程完全退出后重开 |
| 能看到接口但双击没数据 | 固件没跑起来、信道没选对、串口被占用 | 重烧固件,切换广播信道,关闭其他占用串口的软件 |
| 抓到的包全是坏包或 CRC 错误 | 信号干扰、距离太远、USB 3.0 干扰 | 靠近设备、换 USB 口、排除 2.4G 干扰源 |
| 连接数据抓不全 | 单信道抓包限制 | 使用 Follow 模式、双 dongle 协作、结合设备端日志 |
| 配对后的数据全是密文 | 缺少 LTK 解密 | 从协议栈获取 LTK,填入 Wireshark BLE 协议解密配置 |
| Wireshark 打开后卡住或崩溃 | 插件版本与 Wireshark 版本不兼容 | 按版本匹配表更换插件版本或 Wireshark 版本 |
5.2 我个人的几条经验心得
最后说几条难以归类的个人心得,都是实战中逐渐养成的习惯。
第一,养成抓包前先确认环境的习惯,不要等抓了半天发现是 dongle 固件掉了。我现在每次开始正式抓包前,会先在 Wireshark 里看一眼有没有持续滚动的时间戳,再用手机发一个广播包确认链路,整个检查不超过 30 秒,但能省下后面一小时的排查时间。
第二,多利用 nRF Connect for Desktop 里的 Programmer 工具,不要只把它当成烧录工具。它能直接查看 dongle 的固件版本、芯片信息,还能在设备出问题时一键恢复。我常用的流程是:烧录 → 验证固件版本 → 拔插 → Wireshark 抓包,每一步都有明确反馈,出问题能立刻定位。
第三,分析连接问题时,不要把 Sniffer 当成唯一依据。单信道抓包天然有缺陷,有时候抓到的是不完整的数据,容易得出错误结论。比如一次排查从机断连问题,Sniffer 显示对端主动发起了 DISCONNECT,但实际是因为我们的从机长时间没回包,主机超时断开。只看 Sniffer 数据很容易被误导,一对照从机端日志才发现真相。所以我的习惯是:射频层数据 + 协议栈日志 + 应用层日志,三份资料一起看,才能还原完整现场。
第四,固件版本记得随手记录。nRF Sniffer 固件更新比较频繁,有时候你从官网下载的安装包和 Wireshark 插件的版本对不上,导致 extcap 报错。我每次下载安装包后,会在解压目录里放一个 README,记录版本号、安装日期、配套的 Wireshark 版本。过几个月再出问题,翻一下这个文件就能快速定位是不是升级导致的不兼容。
5.3 环境搭建完成后的验证清单
最后给一个我每次搭好环境都会快速跑一遍的验证清单,等同于“开机自检”:
- 设备管理器里能看到一个正常的 COM 口;
- nRF Connect for Desktop 的 Programmer 能识别到 dongle;
- Wireshark 接口列表里显示 nRF Sniffer for BLE;
- 同一办公室里另一台手机发 BLE 广播,Wireshark 能刷出 btle 包且无 CRC 错误;
- 与自己的开发板建立连接,Wireshark 能抓到 CONNECT_IND 以及至少几个数据信道上的包。
这五条全部通过,说明这套环境已经处于“健康可用”状态。后面再遇到奇葩问题,至少可以排除环境因素,把精力集中在协议本身的分析上。
说实话,Wireshark + nRF52 dongle 这套环境,虽然配置过程有点磨人,但用顺手之后,它的性价比和实用性真的没话说。尤其当你通过抓包解决了一个隐蔽的断连原因,或者定位到一个手机上频繁发起连接参数更新的问题时,那种“原来如此”的感觉,就是所有折腾最好的回报。希望这篇文章能帮大家少走一些弯路,早点进入真正有意思的协议分析阶段。