☰
nRF Sniffer实战:从抓包到解密,彻底搞懂BLE调试
2026/9/28 17:01:51 网站建设 项目流程

写这篇东西之前,先说说我自己的一个经历。做BLE开发那段时间,最头疼的不是代码逻辑,而是“空中在发生什么”完全是盲区。设备偶发断连、配对失败、数据丢包,你只能靠log猜。后来被同行推荐了Nordic nRF Sniffer,第一次在Wireshark里看到实时的链路层报文时,那种“原来是这么回事”的豁然开朗,真的让我觉得之前浪费了太多时间。这篇博文就围绕nRF Sniffer这套方案,把环境搭建、快速抓包、加密报文解密、以及LESC配对调试的实战经验一次讲透,适合正在做BLE协议栈调试、固件开发、或者刚入门想理解蓝牙协议底层的朋友。我会把那些文档里不会写、只有实际踩坑才能拿到的细节一并放进来,尽量让你拿到就能直接上手。

1. nRF Sniffer凭什么成为BLE调试标配

我先花点篇幅讲清楚一个问题:为什么BLE调试强烈建议抓包,而不是全靠打log。

BLE的通信链路分物理层、链路层、L2CAP、ATT/GATT等好几个层次。固件里的log只能看到本机协议栈做了什么,但空中的报文顺序、重传、跳频行为、连接事件里的时序,你根本看不到。很多时候两端设备的状态都是正常的,问题出在中间链路层的交互细节上——这种情况下,唯一的办法就是把空中报文抓出来,一帧一帧看。

市面上的抓包方案大致有三类。

一类是商业协议分析仪,比如Ellisys、Teledyne LeCroy的产品,功能确实强大,能同时抓BLE、Wi-Fi、Zigbee,还带图形化的时序分析。但价格一般人接受不了,动辄几万起步,对个人开发者或者小团队来说不现实。

还有一类是TI的CC2540 USB Dongle方案。它的经典程度不用多说,很多老工程师手里都有,但问题是软件年代久远,对新设备和Wireshark版本的兼容性越来越差。如果你只是偶尔抓一次包,够用;要是频繁调试,维护成本会有点高。

剩下就是我推荐的主流方案:Nordic nRF Sniffer。它最大的优势是硬件成本极低——一块nRF52840 Dongle,几十块钱,配对到Wireshark里就能用。官方持续维护Wireshark插件和固件,对BLE协议栈的支持很完整,而且能直接利用Wireshark庞大的过滤器和解码器生态。对绝大多数BLE开发场景来说,这套方案是性价比最高的,没有之一。

1.1 新旧两代固件怎么选

这里要插一句,很多人在用nRF Sniffer时会被固件版本搞晕。市面上的资料里常见到两代固件:

  • 经典版nRF Sniffer for BLE:工作方式是抓取单一信道的数据,抓包前需要手动指定信道。它轻量、稳定,但有个明显的痛点——BLE的跳频机制导致你很难持续跟住某个连接事件,抓包时经常丢一半内容。
  • 新版nRF Sniffer for Bluetooth LE:从v3.x开始,官方重新设计了方案。固件利用nRF52840的多协议硬件能力,可以并行监听所有37个数据信道,配合Wireshark插件能自动跟随连接事件。不管是广播、连接建立、还是后续的加密交互,都能更完整地抓到。

我的建议很明确:新项目直接用新版固件。只有当你手里还留着老款nRF52832 Dongle、且不想再买硬件的时候,才去考虑经典版。经典版单信道切换的方式在现代BLE调试里效率太低。

1.2 这套方案适合谁

如果你是做BLE外设固件的、做手机端蓝牙交互的、或者刚入门想彻底理解配对和数据交互过程的,用nRF Sniffer做空中报文抓取,能让你少走不少弯路。对于协议栈本身的开发调试,它同样适用——你可以直观看到协议栈发出的每一帧,判断是上层的策略问题还是底层的时序问题。

2. 从零搭环境:Dongle烧录、驱动、Wireshark插件

我一开始以为买回来插上就能用,结果卡在了环境上差不多一个小时,所以把搭建过程完整写在这里,省得大家再踩一遍。

2.1 硬件选择建议

  • 如果你还在观望,直接买nRF52840 Dongle,外形像U盘,内置天线,官方有配套的UF2 Bootloader,烧录非常简单。价格在电商平台上也就几十块钱,非常亲民。
  • 如果你手头有nRF52840 DK开发板,也可以把Sniffer固件烧进去当抓包器用。但DK板的体积大,USB供电加上天线位置不确定,实际抓包时不如Dongle灵巧。
  • 有一种情况要注意:nRF52832 DK也能刷Sniffer固件,但新版固件对nRF52832的支持不如52840完整,尤其新固件的全信道监听能力在52832上会打折扣。如果打算长期做BLE开发,建议还是备一块52840。

另外强烈建议备一根USB延长线,对于抓包的信号质量影响很大。Dongle直接插在电脑USB口上,机身离天线太近,再加上电脑主板的电磁干扰,会导致抓包时丢包率异常高。延长线把Dongle拉出来20~30厘米,信号干净很多。这个是实测有效的小细节,很多人忽略了。

2.2 烧录固件

新版的Sniffer固件通过nRF Connect for Desktop来管理,整体流程分几步。

  1. 从Nordic官网安装nRF Connect for Desktop(Windows / macOS / Linux都有)。
  2. 打开左侧的Programmer应用,把nRF52840 Dongle插入USB口。Dongle的UF2 Bootloader会让它在系统里识别为一个U盘设备,Programmer也能看到这颗芯片。
  3. 去Nordic官网下载nRF Sniffer for Bluetooth LE软件包,里面除了固件文件,还包含Wireshark插件和文档。解压后会看到类似nrf_sniffer_for_bluetooth_le_vX.X.X_master_en.bin这样的固件文件。
  4. 固件文件有命名上的区别,常见的有_master_、_slave_两个角色版本。简单来说,master版本可以监听Master发起的连接事件,slave版本则更适合跟随从设备。日常调试用_master_版本即可,两个版本可以通过Wireshark插件里下拉菜单切换,但固件烧录时二选一。
  5. 在Programmer中把下载好的固件烧录进去,等待烧录完成。之后Dongle会重新枚举为一个串口设备,这个串口就是Wireshark插件用来通信的通道。

2.3 Wireshark插件安装

新版nRF Sniffer的Wireshark插件以extcap扩展的形式工作。下载的软件包里有对应的插件目录,里面能找到nrf_sniffer_ble.py以及相关配置文件。把整个插件目录里的文件复制到Wireshark的extcap目录(Windows下一般在C:\Program Files\Wireshark\extcap),然后重启Wireshark即可。

如果你发现接口列表里没有出现nRF Sniffer,大部分情况是插件放错位置或者Wireshark版本过旧。另外Windows系统下,需要确认插上Dongle后系统能识别到COM口;如果设备管理器中看不到串口,多半是驱动问题,重装Nordic USB驱动或者换一个USB口试试。

桌面系统建议直接用最新版的Wireshark,4.x版本对BLE协议解码的支持已经相当完善。装完插件、插入Dongle,打开Wireshark就应该能看见类似nRF Sniffer的接口。

3. 5分钟快速抓包流程:一步步照着做

环境弄好之后,抓包本身其实很快。我按实际操作顺序写一个完整流程,你打开电脑对着走一遍就能跑通。

3.1 打开接口、扫描设备

打开Wireshark,在主界面接口列表里双击nRF Sniffer接口,进去之后会自动开始扫描设备。界面上方会多出一个nRF Sniffer控制工具栏,里面会列出当前扫描到的蓝牙设备,包含设备地址、名称、信号强度、广播类型等信息。

如果你的目标设备没有立即出现,确认它确实在广播。用手机或者nRF Connect桌面端的扫描功能对比一下,看看设备是否处于可广播状态。新固件的扫描能力很强,几乎瞬间就能看到周围所有在广播的设备。

3.2 选中目标、开始抓包

在设备列表中找到目标设备,点击选中,然后点工具栏的Follow按钮,让Sniffer跟踪这个设备的跳频序列。这一步很关键——如果不点Follow,Sniffer只会停留在广播信道上,抓不到连接期间的数据包。

选好设备后,点Start开始抓包。这时候Wireshark主窗口会开始滚动显示捕获的报文,链路层、L2CAP、ATT等层次的报文都会被解析。如果目标是未连接的设备,你在上面做连接操作,Wireshark里就能看到从广播到连接请求、连接更新、配对请求的一整套流程。

3.3 这对你意味着什么

以排查“设备连不上”为例:你在手机上点连接,如果Wireshark里能看到手机发出的CONNECT_IND报文、但没看到外设回任何链路层包,说明外设压根没收到,问题在射频或广播配置;如果能看到外设回包,但是连接后立刻断开,那就要继续看LL_TERMINATE_IND报文里的错误码,错误码会直接告诉你断开原因。这就是抓包相比打log最大的优势——你能看到两端交互的全过程,而不是只能看到其中一端。

3.4 常用过滤器

抓包过程中报文很杂,善用过滤器能快速定位关键内容。下面是我常用的几个过滤器表达式,直接复制到Wireshark的过滤器栏即可:

  • btle—— 只看BLE链路层报文
  • btatt—— 只看ATT层,适合看属性读写
  • btsmp—— 只看配对/安全相关的SMP报文
  • btl2cap—— 只看L2CAP层
  • btle.length == 0—— 筛选空包,排查CRC错误或丢包问题

调试外设时,我一般先开btatt查看业务数据是否正常;涉及配对就用btsmp聚焦安全流程;需要看底层异常再回到btle里慢慢查。

4. 解密密钥从哪来:BLE加密机制的通俗拆解

抓包抓到加密报文之后,最让人抓狂的就是数据被加密了,Wireshark只显示一堆十六进制密文,完全看不出业务内容。这个环节需要理解BLE加密的基本机制,不然你连要填什么参数都搞不清楚。

4.1 链路层加密到底加密了什么

BLE链路层加密使用AES-CCM算法,它对LL层之上的所有数据包进行加密和完整性校验。抓包软件在解密之前,看到的是加密后的Payload,也就是L2CAP、ATT这些上层协议的内容全部被隐藏了。加密发生在连接建立之后,一旦双方完成加密链路建立,后续所有数据包都走加密通道。

整个过程可以做一个生活类比:配对相当于双方约定一把钥匙,加密相当于把门锁上。抓包工具能透过窗户看见屋子里有人在锁门,但看不见锁门之后屋子里发生了什么。要看清屋里的情况,手里必须有那把钥匙。

4.2 LL层的加密握手过程

蓝牙连接建立后,如果双方决定加密,主设备会发起一系列链路层控制报文:

  • 主设备发送LL_ENC_REQ,里面包含随机数Rand、EDIV、以及第一部分SKD(Session Key Diversifier)和IV。值得注意的是,这些参数在加密建立之前是以明文形式在空口传输的,所以nRF Sniffer能直接抓到。
  • 从设备回复LL_ENC_RSP,携带属于自己的SKD和IV部分。
  • 双方用LTK和拼合后的SKD经过特定派生算法计算出Session Key,后续所有数据包的AES-CCM加解密都使用这个Session Key加上IV来运算。

所以从抓包的角度看,SKD和IV都是现成的,在LL_ENC_REQ和LL_ENC_RSP报文里就能找到。真正需要额外提供的只有LTK或STK这一样东西。整个流程里,随机数和派生参数相当于“公开的盐”,LTK才是真正的“钥匙”。

4.3 LTK和STK来源不同,文化和调试方式也不同

传统Legacy配对(BLE 4.0/4.1时代)和LESC配对(BLE 4.2+)最大的区别在于密钥的协商方式。

  • Legacy配对:如果设备支持Passkey Entry,那个6位数字的PIN码在配对过程中是明文传输的,Sniffer能直接看到。拿到PIN之后,配合固定算法就能推导出STK(Session Temporary Key),因此第三方在Legacy Passkey场景下有机会通过抓包离线推演出会话密钥。但也别高兴太早,实际推导过程依然繁琐,而且Just Works模式产量低。
  • LESC配对:使用ECDH P-256椭圆曲线公钥协商。公钥交换在空中是明文传输的,但私钥永远留在设备内部,即使抓包工具拿到了双方公钥、认证确认值、DHKey检查包,也无法在合理时间内离线还原LTK。换句话说,LESC天然抵抗抓包监听,这也是它成为新设备标配的原因。

在开发者调试场景下,我们不需要去“破解”——直接让自己手头的设备把LTK打印出来就行了。这是最干净、最省时间的思路。

4.4 Wireshark解密配置方法

知道LTK之后,配置解密非常简单:

  1. 打开Wireshark菜单:编辑 → 首选项 → Protocols → Bluetooth。
  2. 勾选Enable Bluetooth link layer decryption。
  3. 点击Edit按钮,在弹出的密钥管理对话框中添加一条记录。
  4. 记录类型选择LTK,填入16字节(32个hex字符)的LTK值。如果是传统配对,还需要把抓到的Rand和EDIV一并填进去;LESC配对下Rand和EDIV可以留空,因为新协商的LTK不依赖这两个参数。
  5. 保存设置后,回到抓包列表,加密的报文就会自动解密,L2CAP和ATT层的内容可以正常解析。

这里有个细节:Wireshark的解密是按设备地址关联的,如果你的设备使用了随机地址(RPA),每次连接地址都可能变化。需要在密钥记录里指定正确的设备地址,否则即使LTK填对了,Wireshark也不知道“该用哪把钥匙开哪扇门”。有关联到自己设备时,建议先把设备的地址固定下来,或者用btle.advertising_address和btle.master_address之类的字段过滤确认。

5. LESC配对调试的实战技巧:密钥获取与状态机排查

标题里特别提到LESC配对调试,确实,现在越来越多的设备强制LESC,调试时“配对能成功但数据不通”和“明明配对上却不加密”这两类问题,最常见。下面从实战角度给几个技巧,都是从实际项目里摸出来的。

5.1 技巧一:让固件把LTK主动打出来

解密的核心条件就是LTK。对开发者来说,最直接的方法是在固件日志里把LTK打印出来。

在nRF5 SDK中,配对完成后主机会收到BLE_GAP_EVT_AUTH_STATUS事件。在这个事件处理函数里调用sd_ble_gap_sec_info_get(),可以拿到连接的安全信息,里面就包含了LTK和Master ID。拿到之后用日志打印成十六进制字符串,一共32个字符,直接复制到Wireshark里即可:

static void on_auth_status(ble_evt_t const *p_ble_evt) { uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; ble_gap_enc_info_t enc_info = {0}; ble_gap_irk_t id_info = {0}; ret_code_t err_code = sd_ble_gap_sec_info_get(conn_handle, &enc_info, &id_info); if (err_code == NRF_SUCCESS) { NRF_LOG_INFO("LTK:"); NRF_LOG_HEXDUMP_INFO(enc_info.ltk, sizeof(enc_info.ltk)); } }

函数名和字段名在不同SDK版本里略有差异,比如有的版本需要传ble_gap_enc_key_t结构体,但思路是一致的:在配对完成事件里取安全信息,打印LTK。

如果是nRF Connect SDK(Zephyr),方法类似但更简单:开启CONFIG_BT_SMP_DEBUG=y之后,协议栈的SMP模块在分发密钥时会通过调试日志打印出LTK和其他key信息。准备好连接事件回调pairing_complete,确认配对成功后去日志里找密钥即可。

5.2 技巧二:抓包状态机定位配对失败原因

LESC配对在空中表现为一整套SMP报文序列,正常流程如下:

Pairing Request→Pairing Response→Public Key Exchange→Authentication Confirm→Authentication Confirm(主从两端各发一个)→DHKey Check(两端各发一个)→Encryption

在Wireshark里切换到btsmp过滤器,就能像看剧本一样看到整个配对流程。排查问题非常有效:

  • 如果在Pairing Request/Response阶段就终止,往往是双方的IO Capability或安全参数协商不来,比如一端要求MITM但另一端不支持。
  • 如果在Authentication Confirm之后出现Pairing Failed,通常是Passkey输入不一致。此时重点检查两端的Passkey交互逻辑。
  • 如果卡在DHKey Check失败,这个技术含量就高了,说明双方各自计算出的DHKey不一致。常见原因包括:公钥字节序处理错误、私钥按大端/小端解析错、或者在协议栈的Key Derivation逻辑里用了陈旧的安全参数。
  • 如果你看到Encryption之后又出现LL_TERMINATE_IND,大概率是上层因为加密不满足要求主动断开,常见于外设要求“必须加密才允许GATT操作”但主机迟迟没有发起加密。

5.3 技巧三:先看清IO Capability和MITM

很多人在调试时遇到“设备主动发起配对但手机上没有弹出验证码”或“明明配好了但外设不记得”这类问题。根源往往是IO Capability没配好。

BLE的配对策略取决于两端设备的IO Capability。比如:

  • Both端都是NoInputNoOutput,就用Just Works配对,没有确认码。
  • 一端是DisplayOnly一端是KeyboardOnly,会触发Passkey Entry,一端显示6位数字,另一端输入。

如果你在抓包里看到的配对模式和你预期不符,先回去查IO Capability。另外,MITM标志直接决定配对是否使用加密保护认证;如果两端都设为MITM=0,即使IO Capability支持,也可能退化为Just Works。

调试时还有个常见需求:不想让设备被重新配对太多次。在抓包里留意Bonding标志位,如果双方不交换Bonding请求,配对完成后不会存储Long Term Key,下次连接会重新配对。由于抓包时经常反复连接,建议调试阶段保持Bonding开启,方便快速定位配对相关逻辑。

5.4 技巧四:抓包期间固定地址、关掉隐私

这一点非常影响抓包体验。如果外设启用了LL Privacy(随机地址周期变化),并且处于bonded模式下,每过一段时间地址就会变。在Wireshark里,设备的地址一变,过滤器匹配就会乱,密钥关联也可能失效。

调试配对流程时,我一般会先把固件里的GAP_LL_PRIVACY相关宏关掉,或者强制使用静态随机地址。等调通了再开隐私功能。否则你会在“明明抓到数据却对不上号”上浪费大量时间。

5.5 技巧五:多次配对时注意密钥对应关系

Wireshark支持同时保存多组解密密钥,但如果你同一个设备反复配对,会产生多个LTK。填密钥时务必注意对应关系。一个高效的做法是:开始一次新的抓包和配对时,先把旧的解密密钥记录清掉,只保留当前这条连接的LTK。等定位完问题,再把常用连接的密钥加回来。

6. 实测避坑记录:从识别不到设备到解密失败

最后整理一批我在实际使用中遇到的坑,每个都是真金白银换来的经验,按出现频率排序。

6.1 Dongle插上电脑没反应

先看设备管理器里有没有串口。如果没有任何反应,多半是驱动问题。nRF52840 Dongle使用UF2 Bootloader,第一次插入时会像一个U盘,烧录SNIFFER固件后会重新枚举为SWD调试接口和CDC串口。此时在Windows下可能需要安装Nordic的USB驱动,或者换一个USB口重新插拔。

如果是一直识别为U盘不变成串口,说明固件没烧对或者烧录过程被中断,重新走一遍Programmer烧录流程。

6.2 Wireshark里找不到nRF Sniffer接口

基本都是插件没装到位。确认extcap插件文件复制到了正确目录,并且Wireshark版本和插件兼容。我遇到过一次把插件解压到了用户目录的AppData里,结果Wireshark只扫描Program Files底下的extcap,导致接口列表一直为空。后来重新复制到Wireshark安装目录下就正常了。

还有一个容易忽略的点:新版Sniffer固件需要配合nrf_sniffer_ble.py脚本,而这个脚本依赖Python3。如果你的电脑没有装Python,或者装了但环境变量不对,插件会启动失败。Wireshark自带了Python运行时,但某些情况下还是需要系统Python环境。报错的检查方法很简单:在cmd里手动执行一下extcap目录下的python脚本,看是否报错。

6.3 抓包时丢包严重,连接事件不完整

插着USB延长线后,大多数丢包问题会缓解。还有一个原因是同时开启的抓包会话太多,或者电脑性能不足。Wireshark在处理高密度广播包时CPU占用很高,建议在抓包时用过滤器先把不需要的数据挡掉。比如只抓某个设备地址的包:

btle.advertising_address == 12:34:56:78:9a:bc

另外注意:Dongle要插在独立的USB口上,尽量别用USB Hub。USB Hub的供电质量不稳定,会导致RF性能下降。

6.4 Follow了设备,但抓不到连接包

这种情况大概率是设备的连接参数里有固定的跳频模式,而Sniffer没有正确同步。新版固件对此做了很多优化,但如果你用的固件是经典版,需要手动选择信道。还有一点:如果设备是从机角色发起连接(比如用手机模拟外设),你需要烧录_slave_角色的Sniffer固件才能更好地跟随。建议遇到这种情况时,master/slave两个版本都试一下。

6.5 填了解密密钥,报文还是密文

排查步骤按顺序来:

  1. 确认Wireshark里启用了Bluetooth解密开关。
  2. 确认LTK填对了。长度一定是32个hex字符,不能有空格,大小写无所谓。
  3. 确认密钥关联的设备地址正确。如果你的设备用RPA随机地址,需要填静态地址和身份解析密钥,或者固定地址。
  4. 确认加密链路对应的是哪条连接。Wireshark里可能有多个蓝牙连接并存,密钥要填在对应连接上。
  5. 如果是传统配对,确认EDIV和Rand也填了。LESC则不用。

还有个坑:如果Wireshark版本过低,即使密钥填对,也可能无法准确解密带EDIV的链路。这时候升级Wireshark版本基本就能解决。

6.6 抓包时Dongle发热、抓一段时间就无响应

这是真实的物理问题。nRF52840在监听全部信道时满载运行,发热比较厉害。连续抓包超过一两个小时,偶发无响应。我的处理方案是:抓包时用延长线让Dongle处于通风环境,并且长时间抓包的场景下,每隔一段时间重启一下抓包会话。如果项目需要7x24小时持续抓包,建议准备两个Dongle轮换。

6.7 识别了设备但RSSI一直是0

这个问题通常不是Sniffer的问题,而是有些Sniffer固件版本不解析RSSI字段而已。你只需要确认设备列表中能看到目标设备并Follow成功,RSSI除非做距离测试,否则可以忽略。

最后再说几句

nRF Sniffer这套组合拳,基本覆盖了我日常BLE调试90%以上的场景:从广播参数检查、连接事件时序分析,到配对流程状态机、加密数据包解密。比起动辄数万的商用分析仪,一块几十块的Dongle加免费软件就能达到这个效果,性价比高到了一个不可思议的地步。

需要提醒的是,抓包解密这个能力只能用在合法的开发调试场景中,比如自己手头的设备、或者明确获得授权测试的项目。用它去窥探不属于自己的通信内容,性质就完全不同了,这条红线希望大家心里有数。

最后分享一个小技巧:遇到难缠的蓝牙问题,先抓包、再动手改代码。抓包能帮你把“猜”变成“看”,把排查时间从几天压缩到几小时。别像我一开始那样闷头打log,等一个偶然的灵感才定位问题——直接看数据,比什么都快。

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

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

立即咨询