Bluetooth PAN Setup

缘起

由于我有部分设备没有 RJ45 接口,我也不想买扩展坞或交换机,于是准备在无线上下个功夫,可惜清华的无线网络过于拉跨,除了巨大的延迟与延迟方差,还有认证和下线等问题,实在难受。

我日常会将我的键盘和鼠标「ssh」 到别的机器上(类似于要聚餐了我 ssh 过去吃饭),所以对延迟非常敏感。如下图,我用左边的上古机器(上古机器的键盘真的舒服啊)ssh 到右边的平板(没有 RJ45 接口)聊 Telegram。

这时我注意到了我的机器上基本都有蓝牙。由于我的内网机器都是 Linux 机器,所以自由度还是很大的,于是开始了解相关概念。

Fugoes 以前弄过 ethernet over bluetooth,具体内容如下

1
2
3
4
5
6
7
# for server:
sudo ip link add br-blue type bridge
sudo ip link set br-blue up
sudo bt-network -s nap br-blue

# for client:
sudo bt-network -c <server's MAC address> nap

在现在的我看来,这个教程已经很精髓了,足够囊括所需,但对于小白来说太不友好了,所以我这篇博文意在扩充以上的命令,给出一些先决条件和准备。

PAN (Personal Area Network)

PAN 和 LAN、WAN 等概念是一系列的,它更注重个人身边区域设备的连接情况,这个情况下用蓝牙是非常不错的选择。

为了构建 PAN,蓝牙实现了一种协议 BNEP,能够搭建一个二层隧道。在此基础上,由于程序的实现,我们使用一个 bridge 来连接这些隧道,构建一个完整的二层。

在目前的实现(bt-network)中,这个 bridge 是实现在服务端的;由于蓝牙的限制,一个服务端只能连接 7 个客户端,也就是说整个 PAN 内最多只能有 8 台设备。经典的网络拓扑是这样的

1
2
3
4
5
6
7
8
server:       bnep0--bridge--bnep2
server: / | \
server: / bnep1 \
/ | |
/ | |
client0: bnep0 | |
client1: bnep0 |
client2: bnep0

当然我们可以做一些更加高级的组网方式,绕开蓝牙的数量限制,比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server:       bnep0--bridge--bnep2
server: / | \
server: / bnep1 \
/ | |
/ | |
client0: bnep0 | |
client1: bnep0 |
client2: bnep0
client2: |
client2: bridge
client2: |
client2: bnep1
|
|
|
client8: bnep0

不过确实一般人没有这么多蓝牙设备,按下不表。

配对——预处理

为了建立 BNEP 隧道,我们需要先配对两个设备,一般而言两边设备都会走以下流程

1
2
3
4
5
6
7
# start bluetoothd daemon
systemctl start bluetooth
bluetoothctl
[bluetoothctl] power on
[bluetoothctl] pairable on
[bluetoothctl] discoverable on
[bluetoothctl] scan on

之后便是配对,只需一方发起,不过需要双方确认

1
[bluetoothctl] pair <MAC of peer device>

这里的 MAC 地址需要根据自己的设备情况填入。在 pair 成功后,即可进行以下组网操作。

组网

服务端

按照程序的一贯特点,bridge 是需要我们手动启动的,所以我有如下脚本。

1
2
3
ip l add pan0 type bridge
ip l set pan0 up
ip a a 10.0.111.1/24 dev pan0

之后分别在两个控制台中启用两个服务

1
2
bt-agent
bt-network -s nap pan0

客户端

1
2
bluetoothctl
[bluetoothctl] connect <MAC of server device>

由于 connect 后如果没有服务与活动,该连接会自动断开,所以我们需要在链接刚好启动的时候,在另一窗口运行以下命令

1
bt-network -c <MAC of server device> nap

如果命令成功,我们就可以 ip l 看到一个新的设备啦

1
2
3
4
5
$ ip a show dev bnep0
229: bnep0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether 28:3a:4d:7e:ec:0e brd ff:ff:ff:ff:ff:ff
inet6 fe80::2a3a:4dff:fe7e:ec0e/64 scope link
valid_lft forever preferred_lft forever

这时我们就可以配上地址并测试联通性了

1
2
ip a a 10.0.111.2/24 dev bnep0
ping -c1 10.0.111.1

一些日志

服务端

连接成功后会有以下日志

  • bt-agent
    1
    2
    3
    4
    $ bt-agent
    Agent registered
    Default agent requested
    Device: client (MAC) for UUID xxxxxx
  • bt-network
    1
    2
    $ bt-network -s nap pan0
    NAP server registered

客户端

1
2
$ bt-network -c <server MAC> nap
Network service is connected

延迟

1
2
3
4
5
6
7
8
9
10
$ ping -c4 10.0.111.1
PING 10.0.111.1 (10.0.111.1) 56(84) bytes of data.
64 bytes from 10.0.111.1: icmp_seq=1 ttl=64 time=28.6 ms
64 bytes from 10.0.111.1: icmp_seq=2 ttl=64 time=22.9 ms
64 bytes from 10.0.111.1: icmp_seq=3 ttl=64 time=22.8 ms
64 bytes from 10.0.111.1: icmp_seq=4 ttl=64 time=34.7 ms

--- 10.0.111.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 22.836/27.244/34.665/4.871 ms

带宽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[server] $ iperf -s
[client] $ iperf -c 10.0.111.1 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.111.1, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[ 3] local 10.0.111.2 port 51094 connected with 10.0.111.1 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0- 2.0 sec 640 KBytes 2.62 Mbits/sec
[ 3] 2.0- 4.0 sec 512 KBytes 2.10 Mbits/sec
[ 3] 4.0- 6.0 sec 768 KBytes 3.15 Mbits/sec
[ 3] 6.0- 8.0 sec 785 KBytes 3.22 Mbits/sec
[ 3] 8.0-10.0 sec 829 KBytes 3.39 Mbits/sec
[ 3] 0.0-10.3 sec 3.45 MBytes 2.82 Mbits/sec

问题与解决

bluetoothctl waiting to connect to bluetoothd

要么没开 bluetooth.service(这是Arch Linux有的,别的发行版请自行寻找等价服务),要么就是蓝牙设备还没有转换过来(常见与Dell的一些蓝牙和Wifi在一张板子上的),这时候需要 hid2hci 这个命令。

bt-network -c Network service is not supported by this device

这时候你还未连接已经配对好的设备,所以说 Network service 不支持啦。这时候需要在 bluetoothctl 中 connect 服务端,并在连接还未断开时运行命令

bt-network -c segmentation fault (core dumped)

服务端没有启动 bt-agent

闲话

  • 网上的教程都巨大古老了,然后最坑人的是,bluez 这群人非常折腾,许多工具都在版本迭代中没有了,弄得到处碰壁
  • 蓝牙栈确实没有什么很好的工具,要不是真的想折腾与利用,建议不要折腾。尤其是,组了蓝牙网络以后,其可能并不好纳入已有的网络(比如地址段)。对我来说,我是搭建 overlay network 作为内网的,所以下层越丰富越好
  • 目前我的内网里有Ethernet,有Wifi,也有蓝牙;有x86,也有arm;有教育网,也有移动网,真是包罗万象了。最后附上一张我内网的拓扑图吧(由于是 full mesh 内网,其拓扑会时常变动,这只是一个截面)。