蓝牙协议栈实战:从HCI命令到GATT服务,手把手教你用Wireshark抓包分析BLE通信
蓝牙协议栈实战:从HCI命令到GATT服务,手把手教你用Wireshark抓包分析BLE通信
在物联网设备爆炸式增长的今天,低功耗蓝牙(BLE)已成为智能穿戴、家居自动化等场景的核心技术。但当你开发的智能手环频繁断连,或自定义服务无法被手机识别时,仅靠SDK文档远远不够——你需要深入协议栈底层,像外科手术般精准定位问题。本文将带你使用Wireshark这把"手术刀",解剖BLE通信全过程。
1. 搭建BLE抓包环境
1.1 硬件准备
要捕获空中传输的BLE数据包,常规网卡无法胜任。推荐以下三种方案:
| 硬件方案 | 成本 | 适用场景 | 推荐型号 |
|---|---|---|---|
| 专用蓝牙嗅探器 | $$$ | 企业级协议分析 | Ellisys Bluetooth Explorer |
| 双模蓝牙适配器 | $$ | 开发调试 | Nordic nRF52840 Dongle |
| 手机抓包 | $ | 移动端问题排查 | Android HCI日志功能 |
以nRF52840 Dongle为例的配置步骤:
# 刷写嗅探固件 nrfjprog -f nrf52 --program sniffer.hex --chiperase # 启动Wireshark捕获 hciconfig hci0 reset wireshark -k -i /dev/hci01.2 Wireshark配置技巧
安装完成后需进行关键设置:
- 在
Edit > Preferences > Protocols > Bluetooth中启用BLE LL decoding - 添加蓝牙厂商ID定义文件(如
company_ids.txt) - 设置显示过滤器为
btle || bthci_acl
提示:遇到CRC校验错误时,尝试调整信道偏移量(Channel Map)
2. BLE连接建立过程解析
2.1 广播阶段抓包分析
观察智能手环的广播包,典型结构如下:
Frame 1234: 42 bytes on channel 37 Advertising Address: 00:11:22:33:44:55 (Random) Advertising Type: ADV_IND (0x00) Advertising Data: 01 02 01 06 // Flags: LE General Discoverable 09 09 48 65 // Complete Local Name: "HelloBand" 03 03 0F 18 // Service UUID: Battery Service广播包类型对比:
| 类型代码 | 含义 | 是否可连接 | 是否可扫描 |
|---|---|---|---|
| 0x00 | ADV_IND | 是 | 是 |
| 0x01 | ADV_DIRECT_IND | 是 | 否 |
| 0x02 | ADV_NONCONN_IND | 否 | 否 |
| 0x03 | ADV_SCAN_IND | 否 | 是 |
2.2 连接请求解密
当手机发起连接时,关键参数包括:
- Connection Interval:7.5ms到4s之间
- Slave Latency:允许跳过的连接事件数
- Supervision Timeout:超时断开阈值
典型连接请求包:
LL_CONNECT_REQ: Access Address: 0x8E89BED6 CRCInit: 0x55AACC WinSize: 2 (2.5ms) WinOffset: 0 Interval: 24 (30ms) Latency: 4 Timeout: 200 (2s) Channel Map: 0x1FFFFFFFFF Hop: 5 SCA: 3 (251ppm to 500ppm)3. HCI层命令与事件剖析
3.1 关键HCI命令结构
HCI命令采用统一格式:
+---------------+----------------+-------------------+-------------------+ | OGF (6 bits) | OCF (10 bits) | Parameter Length | Parameters... | +---------------+----------------+-------------------+-------------------+常见OGF分类:
- 0x01:链路控制(重置、断开等)
- 0x03:控制器基带(设置事件掩码)
- 0x08:BLE专用命令(广播/扫描设置)
示例:设置广播参数命令
# HCI_LE_Set_Advertising_Parameters (OGF=0x08, OCF=0x0006) command = [ 0x20, 0x06, 0x0F, # Header (OGF|OCF + length) 0xA0, 0x00, # Min interval = 100ms 0xB0, 0x00, # Max interval = 110ms 0x00, # Advertising type 0x00, # Own address type 0x00, # Peer address type 0x00,0x00,0x00,0x00,0x00,0x00, # Peer address 0x07, # Channel map 0x00 # Filter policy ]3.2 典型事件解析
设备连接成功后,控制器会返回LE Connection Complete事件:
Event Code: 0x3E (LE Meta Event) Subevent: 0x01 (LE Connection Complete) Status: 0x00 (Success) Handle: 0x0042 Role: Master Peer Address Type: Random (0x01) Peer Address: 00:11:22:33:44:55 Interval: 0x0018 (30ms) Latency: 0x0004 Timeout: 0x00C8 (2s)4. ATT/GATT协议实战分析
4.1 属性协议操作流程
ATT协议采用简单的请求-响应模型:
特征值读取流程:
Client -> Server: READ_REQUEST (Handle=0x0012) Server -> Client: READ_RESPONSE (Value=0x4B)通知与指示的区别:
- 通知(0x1B):无确认,可能丢失
- 指示(0x1D):需要客户端确认
心率服务抓包示例:
ATT: Handle Value Notification (Handle=0x0015) Value: 0x4E 0x00 # Heart Rate = 78bpm4.2 GATT服务发现过程
完整的服务发现包含三个步骤:
发现主要服务:
Client -> Server: READ_BY_GROUP_TYPE_REQ (UUID=0x2800) Server -> Client: READ_BY_GROUP_TYPE_RSP Handle Range: 0x0001-0x0005 UUID: 180D (Heart Rate Service)发现服务特性:
Client -> Server: READ_BY_TYPE_REQ (UUID=0x2803) Server -> Client: READ_BY_TYPE_RSP Handle: 0x0012 Properties: Notify (0x10) Value Handle: 0x0013 UUID: 2A37 (Heart Rate Measurement)配置通知:
Client -> Server: WRITE_REQ (Handle=0x0014) Value: 0x0100 # Enable notification
5. 高级调试技巧与异常排查
5.1 常见问题诊断表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 连接频繁断开 | Supervision Timeout太小 | 检查LL_CONNECT_REQ参数 |
| 数据传输卡顿 | Connection Interval过长 | 抓包分析实际间隔时间 |
| 服务发现失败 | 属性权限设置错误 | 检查ATT协议的READ_REQ响应 |
| 广播包不可见 | 广播信道被干扰 | 切换至37/38/39信道测试 |
5.2 性能优化建议
- 连接参数调优公式:
最优Interval = (吞吐量需求 × 8) / (MTU × 每个连接事件包数) - MTU协商技巧:
// 在Android开发中设置最大MTU BluetoothGatt.requestMtu(247); // 最大支持247字节
在完成一次完整的BLE通信分析后,建议保存过滤后的数据包:
tshark -r capture.pcapng -Y "btle || bthci_acl" -w ble_filtered.pcapng