iOS Central 与 BlueZ Peripheral 由于授权不足而断开连接

iOS Central with BlueZ Peripheral disconnect due to insufficient auth

在我们的系统中,我们有一个使用 BlueZ 5.50 的 BLE 外围设备(在本例中,运行 在 RPi4 上)。

我们有一个 iOS 应用程序作为中央连接到此外围设备。

这个连接可以在btmon中看到,一切正常:

> HCI Event: LE Meta Event (0x3e) plen 31                                                                                                                                                                             #189 [hci0] 1157.975252
      LE Enhanced Connection Complete (0x0a)
        Status: Success (0x00)
        Handle: 1
        Role: Slave (0x01)
        Peer address type: Random (0x01)
        Peer address: 51:A3:4E:3C:B5:D6 (Resolvable)
        Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable)
        Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable)
        Connection interval: 30.00 msec (0x0018)
        Connection latency: 0 (0x0000)
        Supervision timeout: 720 msec (0x0048)
        Master clock accuracy: 0x01
@ MGMT Event: Device Connected (0x000b) plen 13                                                                                                                                                                   {0x0003} [hci0] 1157.975343
        LE Address: 51:A3:4E:3C:B5:D6 (Resolvable)
        Flags: 0x00000000
        Data length: 0
@ MGMT Event: Device Connected (0x000b) plen 13                                                                                                                                                                   {0x0002} [hci0] 1157.975343
        LE Address: 51:A3:4E:3C:B5:D6 (Resolvable)
        Flags: 0x00000000
        Data length: 0
@ MGMT Event: Device Connected (0x000b) plen 13                                                                                                                                                                   {0x0001} [hci0] 1157.975343
        LE Address: 51:A3:4E:3C:B5:D6 (Resolvable)
        Flags: 0x00000000
        Data length: 0
< HCI Command: LE Read Remote Used Features (0x08|0x0016) plen 2                                                                                                                                                      #190 [hci0] 1157.975611
        Handle: 1
> HCI Event: Command Status (0x0f) plen 4                                                                                                                                                                             #191 [hci0] 1157.976191
      LE Read Remote Used Features (0x08|0x0016) ncmd 1
        Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 12                                                                                                                                                                             #192 [hci0] 1158.060347
      LE Read Remote Used Features (0x04)
        Status: Success (0x00)
        Handle: 1
        Features: 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00
          LE Encryption
          Connection Parameter Request Procedure
          Extended Reject Indication
          Slave-initiated Features Exchange
          LE Ping
          LE Data Packet Length Extension
          LL Privacy
          Extended Scanner Filter Policies

我们遇到的问题是几分钟后断开连接。更深入地看,btmon 日志记录显示以下内容,并且不断循环直到最终断开连接:

< ACL Data TX: Handle 1 flags 0x00 dlen 7                                                                                                                                                                             #301 [hci0] 1159.739498
      ATT: Read Request (0x0a) len 2
        Handle: 0x0016
> ACL Data RX: Handle 1 flags 0x02 dlen 9                                                                                                                                                                             #302 [hci0] 1159.799046
      ATT: Error Response (0x01) len 4
        Read Request (0x0a)
        Handle: 0x0016
        Error: Insufficient Authentication (0x05)
> HCI Event: Number of Completed Packets (0x13) plen 5                                                                                                                                                                #303 [hci0] 1159.799227
        Num handles: 1
        Handle: 1
        Count: 1
< ACL Data TX: Handle 1 flags 0x00 dlen 6                                                                                                                                                                             #304 [hci0] 1159.799388
      SMP: Security Request (0x0b) len 1
        Authentication requirement: Bonding, No MITM, Legacy, No Keypresses (0x01)
> ACL Data RX: Handle 1 flags 0x02 dlen 11                                                                                                                                                                            #305 [hci0] 1159.859132
      SMP: Pairing Request (0x01) len 6
        IO capability: KeyboardDisplay (0x04)
        OOB data: Authentication data not present (0x00)
        Authentication requirement: Bonding, No MITM, Legacy, No Keypresses (0x01)
        Max encryption key size: 16
        Initiator key distribution: EncKey IdKey (0x03)
        Responder key distribution: EncKey IdKey (0x03)
@ MGMT Event: Authentication Failed (0x0011) plen 8                                                                                                                                                               {0x0003} [hci0] 1159.859286
        LE Address: 51:A3:4E:3C:B5:D6 (Resolvable)
        Status: Authentication Failed (0x05)
@ MGMT Event: Authentication Failed (0x0011) plen 8                                                                                                                                                               {0x0002} [hci0] 1159.859286
        LE Address: 51:A3:4E:3C:B5:D6 (Resolvable)
        Status: Authentication Failed (0x05)
@ MGMT Event: Authentication Failed (0x0011) plen 8                                                                                                                                                               {0x0001} [hci0] 1159.859286
        LE Address: 51:A3:4E:3C:B5:D6 (Resolvable)
        Status: Authentication Failed (0x05)
> HCI Event: Number of Completed Packets (0x13) plen 5                                                                                                                                                                #306 [hci0] 1159.859215
        Num handles: 1
        Handle: 1
        Count: 1
< ACL Data TX: Handle 1 flags 0x00 dlen 6                                                                                                                                                                             #307 [hci0] 1159.859348
      SMP: Pairing Failed (0x05) len 1
        Reason: Pairing not supported (0x05)
> HCI Event: Number of Completed Packets (0x13) plen 5                                                                                                                                                                #308 [hci0] 1159.919220
        Num handles: 1
        Handle: 1
        Count: 1
> ACL Data RX: Handle 1 flags 0x02 dlen 11                                                                                                                                                                            #309 [hci0] 1160.999201
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0001-0x0005
        Attribute type: Device Name (0x2a00)
< ACL Data TX: Handle 1 flags 0x00 dlen 19                                                                                                                                                                            #310 [hci0] 1160.999678
      ATT: Read By Type Response (0x09) len 14
        Attribute data length: 13
        Attribute data list: 1 entry
        Handle: 0x0003
        Value: 6d6174742d7562756e7475

查看此日志记录,似乎 BlueZ 端(外围设备)正在尝试从 iOS 端(中央)读取某些内容。

如果我们通过 bluetoothctl 检查 iOS 设备上的服务列表,我们会看到该设备公开了 21 项服务:

[iPhone]# info DC:08:0F:5B:8D:82
Device DC:08:0F:5B:8D:82 (public)
Name: iPhone
Alias: iPhone
Class: 0x007a020c
Icon: phone
Paired: yes
Trusted: no
Blocked: no
Connected: yes
LegacyPairing: no
UUID: Vendor specific (00000000-deca-fade-deca-deafdecacafe)
UUID: Service Discovery Serve.. (00001000-0000-1000-8000-00805f9b34fb)
UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: Advanced Audio Distribu.. (0000110d-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
UUID: NAP (00001116-0000-1000-8000-00805f9b34fb)
UUID: Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb)
UUID: Phonebook Access Server (0000112f-0000-1000-8000-00805f9b34fb)
UUID: Message Access Server (00001132-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: Current Time Service (00001805-0000-1000-8000-00805f9b34fb)
UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb)
UUID: Battery Service (0000180f-0000-1000-8000-00805f9b34fb)
UUID: Vendor specific (02030302-1d19-415f-86f2-22a2106a0a77)
UUID: Vendor specific (7905f431-b5ce-4e99-a40f-4b1e122d00d0)
UUID: Vendor specific (89d3502b-0f36-433a-8ef4-c502ad55f8dc)
UUID: Vendor specific (9fa480e0-4967-4542-9390-d343dc5d04ae)
UUID: Vendor specific (d0611e78-bbb4-4591-a5f8-487910ae4366)

这个问题似乎是 this Stack Overflow question 的症结所在,他们已经发布了一个在没有电池配置文件的情况下编译 BlueZ 的解决方法。

应用该解决方法,即重新编译 BlueZ:

builtin_modules += battery
builtin_sources += profiles/battery/battery.c

Makefiles.plugin 中删除使上述错误消失,并且不再断开连接。

这令人困惑,因为根据规范,电池服务没有安全要求:

"This service defines no security requirements for these characteristics."

所以,有人知道是什么原因造成的吗? 有没有办法阻止 BlueZ 尝试以这种方式阅读? 有谁知道避免重新编译 BlueZ 的解决方法?

也许这是一个需要在非发起方禁用 GATT 客户端的情况 - 就像 BlueZ 邮件列表中的 this post 一样,发帖人似乎已经深入研究了同样的问题但没有回应。

在电池 GATT 特性移入 DBUS org.bluez.Battery1 interface 后,此问题开始出现在 Bluez v5.48 中。当 Pi 和 iOS 设备连接时,Pi 会尝试读取 iOS 电池特性。然后触发配对请求,因为 Apple 已保护此特性免受未配对读取,或者 Bluez 中的某些内容错误地确定此特性受到保护。我找到了两种不同的方法来解决这个问题而无需重新编译 Bluez。

  1. 简易解决方案:防止 Bluez 电池插件在启动时加载。您将需要修改位于以下路径的蓝牙服务文件: /lib/systemd/system/bluetooth.service 。在此文件中,转到以“ExecStart”开头的行,并确保该行具有“ExecStart=/usr/lib/bluetooth/bluetoothd -P battery”(没有引号)。这个-P选项prevents any listed plugins from loading.

  2. 自定义解决方案:编写您自己的自动接受配对请求的自定义代理。我使用了 Bluez simple-agent example 并对其进行了修改,以便 RequestPinCode 函数始终成功返回,而不是请求输入。这种方法的缺点是这仍然要求 iOS 用户配对。不过,如果您想通过完全配对的蓝牙连接获得可靠性和加密访问权限,这可能是一个积极的结果。