Google 致力于为黑人社区推动种族平等。查看具体行动

线程边界路由器 - 双向 IPv6 连接和基于 DNS 的服务发现

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

1. 简介

699d673d05a55535.png

什么是线程边界路由器?

Thread 是一种基于 IP 的低功耗无线网格网络协议,可实现从设备到设备的安全通信,以及设备到云的通信。线程网络可以适应拓扑变化,以避免单点故障。

线程边界路由器将线程网络连接到其他基于 IP 的网络,如 Wi-Fi 或以太网。线程网络需要边界路由器才能连接到其他网络。线程边界路由器至少支持以下功能:

  • 线程与 Wi-Fi/以太网之间的双向 IP 连接。
  • 通过 mDNS(采用 WLAN/以太网链路)和 SRP(采用线程网络)实现双向服务发现。
  • 线程式基础架构,通过基于 IP 的链接合并线程分区。
  • 通过外部线程调试(例如手机)对线程设备进行身份验证,并将其加入线程网络。

Google 发布的 OpenThread Border Router (OTBR) 是线程边界路由器的开源实现。

构建内容

在此 Codelab 中,您将设置线程边界路由器,并通过边界路由器将手机连接到线程端点设备。

学习内容

  • 如何设置 OTBR
  • 如何使用 OTBR 构建线程网络
  • 如何构建具有 SRP 功能的 OpenThread CLI 设备
  • 如何向 SRP 注册服务
  • 如何发现和访问线程端点设备。

所需条件

  • Raspberry Pi 3/4 设备和至少 8 GB 功能的 SD 卡。
  • 2 个北欧半导体 nRF52840 开发板。
  • 未启用路由器的 IPv6 路由器通告防护的 WLAN AP。
  • 一部搭载 iOS 14 或以上版本的 Android 手机,或搭载 Android 8.1 或以上版本的 Android 手机。

2. 设置 OTBR

设置 Raspberry Pi

只需按照 raspberrypi.org 上的说明操作,即可通过 rpi-imager 工具轻松设置全新的 Raspberry Pi 设备,而不必在该工具中使用最新的 Raspberry Pi 操作系统,请下载 2021-05-07-raspios-buster-armhf-lite)。要完成此 Codelab 中的手机步骤,您需要将 Raspberry Pi 连接到 WLAN AP。请按照指南设置无线连接。使用 SSH 登录 Raspberry Pi 非常方便,请点击此处查看相关说明。

获取 OTBR 代码

登录 Raspberry Pi 并从 GitHub 克隆 ot-br-posix

$ git clone https://github.com/openthread/ot-br-posix.git --depth 1

构建和安装 OTBR

OTBR 具有两个引导和设置线程边界路由器的脚本:

$ cd ot-br-posix
$ ./script/bootstrap
$ INFRA_IF_NAME=wlan0 ./script/setup

OTBR 适用于通过 INFRA_IF_NAME 指定的线程接口和基础架构网络接口(如 Wi-Fi/以太网)。线程接口由 OTBR 本身创建,默认命名为 wpan0,如果未明确指定 INFRA_IF_NAME,则基础架构接口的默认值为 wlan0。如果您的 Raspberry Pi 是通过以太网线缆连接的,请指定以太网接口名称(例如 eth0):

$ INFRA_IF_NAME=eth0 ./script/setup

检查 OTBR 是否已成功安装:

$ sudo service otbr-agent status
● otbr-agent.service - Border Router Agent
   Loaded: loaded (/lib/systemd/system/otbr-agent.service; enabled; vendor preset: enabled)
   Active: activating (auto-restart) (Result: exit-code) since Mon 2021-03-01 05:43:38 GMT; 2s ago
  Process: 2444 ExecStart=/usr/sbin/otbr-agent $OTBR_AGENT_OPTS (code=exited, status=2)
 Main PID: 2444 (code=exited, status=2)

otbr-agent 服务应处于非活动状态,因为它需要运行 RCP 芯片。

重新启动 Raspberry Pi 以使更改生效。

构建并刷写 RCP 固件

OTBR 支持采用 Radio Co-Processor (RCP) 模式的 15.4 无线电芯片。在此模式下,OpenThread 堆栈在主机端运行,并通过 IEEE802.15.4 收发器传输/接收帧。

关注步骤 4使用 nRF52840 开发板和 OpenThread 构建线程网络Codelab要编译并刷写 nRF52840 RCP 设备,请执行以下操作:

$ script/build nrf52840 USB_trans

启动动态密码并验证状态

将 nRF52840 开发板连接到 Raspberry Pi 并启动 otbr-agent 服务:

$ sudo service otbr-agent restart

验证 otbr-agent 服务是否处于活跃状态:

$ sudo service otbr-agent status
● otbr-agent.service - Border Router Agent
   Loaded: loaded (/lib/systemd/system/otbr-agent.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2021-03-01 05:46:26 GMT; 2s ago
 Main PID: 2997 (otbr-agent)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/otbr-agent.service
           └─2997 /usr/sbin/otbr-agent -I wpan0 -B wlan0 spinel+hdlc+uart:///dev/ttyACM0

Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Stop publishing service
Mar 01 05:46:26 raspberrypi otbr-agent[2997]: [adproxy] Stopped
Mar 01 05:46:26 raspberrypi otbr-agent[2997]: PSKc is not initialized
Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Check if PSKc is initialized: OK
Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Initialize OpenThread Border Router Agent: OK
Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Border router agent started.
Mar 01 05:46:26 raspberrypi otbr-agent[2997]: [INFO]-CORE----: Notifier: StateChanged (0x00038200) [NetData PanId NetName ExtPanId]
Mar 01 05:46:26 raspberrypi otbr-agent[2997]: [INFO]-PLAT----: Host netif is down

3.构建线程网络

ot-ctl 命令可用于控制 otbr-agent 服务。ot-ctl 接受所有 OpenThread CLI 命令。如需了解详情,请参阅 OpenThread CLI 指南

使用 OTBR 构建线程网络:

$ sudo ot-ctl dataset init new
Done
$ sudo ot-ctl dataset commit active
Done
$ sudo ot-ctl ifconfig up
Done
$ sudo ot-ctl thread start
Done

等待几秒钟,我们应该能够看到 OTBR 充当线程 leader,并且线程网络数据中存在 off-mesh-routable (OMR) 前缀:

$ sudo ot-ctl state
leader
Done
$ sudo ot-ctl netdata show
Prefixes:
Prefixes:
fd76:a5d1:fcb0:1707::/64 paos med 4000
Routes:
fd49:7770:7fc5:0::/64 s med 4000
Services:
44970 5d c000 s 4000
44970 01 9a04b000000e10 s 4000
Done
$ sudo ot-ctl ipaddr      
fda8:5ce9:df1e:6620:0:ff:fe00:fc11
fda8:5ce9:df1e:6620:0:0:0:fc38
fda8:5ce9:df1e:6620:0:ff:fe00:fc10
fd76:a5d1:fcb0:1707:f3c7:d88c:efd1:24a9
fda8:5ce9:df1e:6620:0:ff:fe00:fc00
fda8:5ce9:df1e:6620:0:ff:fe00:4000
fda8:5ce9:df1e:6620:3593:acfc:10db:1a8d
fe80:0:0:0:a6:301c:3e9f:2f5b
Done

4.设置 SRP 客户端最终设备

构建并刷写 OT CLI

请按照使用 nRF52840 开发板和 OpenThread 创建线程网络 Codelab 的第 5 步,构建并刷写 nRF52840 CLI 终端设备。

但是,CLI 节点需要启用 OT_SRP_CLIENTOT_ECDSA 功能,而不需要启用 OT_COMMISSIONEROT_JOINER

因此,完整的构建调用应如下所示:

$ script/build nrf52840 USB_trans -DOT_SRP_CLIENT=ON -DOT_ECDSA=ON

加入 OTBR 网络

如需加入由 otbr-agent 服务创建的线程网络,我们需要从 OTBR 设备获取活动的操作数据集。让我们返回到 otbr-agent 命令行,并获取活动数据集:

$ sudo ot-ctl dataset active -x
0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

返回 SRP 客户端节点屏幕会话并设置有效数据集:

> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

然后,启动线程界面:

> ifconfig up
Done
> thread start
Done

等待几秒钟,并验证是否成功加入线程网络:

> state
child
Done
> netdata show
Prefixes:
fd76:a5d1:fcb0:1707::/64 paos med 4000
Routes:
fd49:7770:7fc5:0::/64 s med 4000
Services:
44970 5d c000 s 4000
44970 01 9a04b000000e10 s 4000
Done
> ipaddr
fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927
fda8:5ce9:df1e:6620:0:ff:fe00:4001
fda8:5ce9:df1e:6620:ed74:123:cc5d:74ba
fe80:0:0:0:d4a9:39a0:abce:b02e
Done

确保网络数据与 OTBR 上印出的网络数据一致。我们现在可以对 OTBR 的 OMR 地址进行 ping 操作:

> ping fd76:a5d1:fcb0:1707:f3c7:d88c:efd1:24a9
Done
> 16 bytes from fd76:a5d1:fcb0:1707:f3c7:d88c:efd1:24a9: icmp_seq=1 hlim=64 time=49ms

5. 在最终用户设备上发布服务

mDNS 已广泛用于链路本地发布 DNS-SD 服务。但多播消息会占用过多带宽,会快速耗尽低功耗设备的电池电量。线程使用单播 SRP 协议向边界路由器注册其服务,并依赖边界路由器在 Wi-Fi 或以太网链路上通告服务。

我们可以使用 srp client 命令注册服务。

转到 SRP 客户端节点屏幕会话并自动启动 SRP 客户端:

> srp client autostart enable
Done

设置将通过 Wi-Fi/以太网链接通告的主机名:

> srp client host name ot-host
Done

对于连接到 Wi-Fi/以太网链路的设备,需要访问线程设备的最终用途 OMR 地址:

> srp client host address fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927
Done

最后,注册虚构的 _ipps._tcp 服务:

> srp client service add ot-service _ipps._tcp 12345
Done

等待几秒钟,我们应该会看到已注册的服务:

> srp client service
instance:"ot-service", name:"_ipps._tcp", state:Registered, port:12345, priority:0, weight:0
Done

我们已完成所有设置工作,并且应该已通过 Wi-Fi/以太网链接通告 _ipps._tcp 服务。现在就来发现并访问最终设备吧!

6.发现服务

使用手机发现服务

54a136a8940897cc.png

我们使用服务浏览器应用通过 Android 手机发现 mDNS 服务,我们还为 iOS 移动设备提供了等效的应用。打开应用,服务 _ipps._tcp 应该应该会显示。

通过 Linux 主机发现服务

如果要从其他 Linux 主机发现该服务,可以使用 avahi-browse 命令。

安装 avahi-daemonavahi-utils

$ sudo apt-get install -y avahi-daemon avahi-utils

解析服务:

$ sudo service avahi-daemon start # Ensure the avahi daemon is started.
$ avahi-browse -r _ipps._tcp
+ wlan0 IPv6 ot-service                                    Secure Internet Printer local
= wlan0 IPv6 ot-service                                    Secure Internet Printer local
   hostname = [ot-host.local]
   address = [fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927]
   port = [12345]
   txt = []
...

通过 macOS 主机发现该服务

您可以在 macOS 上使用 dns-sd 解析该服务:

$ dns-sd -Z _ipps._tcp local.
Browsing for _ipps._tcp.local.
DATE: ---Sun 14 Mar 2021---
21:31:42.125  ...STARTING...

; To direct clients to browse a different domain, substitute that domain in place of '@'
lb._dns-sd._udp                                 PTR     @

; In the list of services below, the SRV records will typically reference dot-local Multicast DNS names.
; When transferring this zone file data to your unicast DNS server, you'll need to replace those dot-local
; names with the correct fully-qualified (unicast) domain name of the target host offering the service.

_ipps._tcp                                      PTR     ot-service._ipps._tcp
ot-service._ipps._tcp                           SRV     0 0 12345 ot-host.local. ; Replace with unicast FQDN of target host
ot-service._ipps._tcp                           TXT     ""
...

7. 对最终设备执行 Ping 操作

通过手机 Ping

以 Pixel 手机为例,我们可以在 Service Browser 应用中的服务实例的详情页面中找出之前注册的服务“ot-service”的 OMR 地址。

bb992962e68d250b.png 888daa1df1e1a9bf.png

我们现在可以使用其他网络分析器应用对 OMR 地址执行 ping 操作。

遗憾的是,Android 版本的网络分析器应用不支持针对 ping 实用程序的 mDNS 查询,我们无法直接对主机名 ot-host.local 执行 ping 操作(我们可以使用 iOS 版本的应用来对主机名执行 ping 操作)。

从 Linux/macOS 主机执行 ping 操作

线程边界路由器发送 ICMPv6 路由器通告 (RA),以通告 Wi-Fi/以太网链路中的前缀(通过前缀信息选项)和路由(通过路由信息选项)。

准备 Linux 主机

请确保在主机上启用 RA 和 RIO:

  1. 如果未启用 IP 转发,则 net.ipv6.conf.wlan0.accept_ra 应至少为 1;否则,应设置为 2
  2. net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen 不得小于 64

对于大多数发行版,accept_ra 默认为 1。但是,其他网络守护程序可能会替换此选项(例如,Raspberry Pi 上的 dhcpcd 会覆盖 accept_ra0)。您可以使用以下命令检查 accept_ra 值:

$ sudo sysctl -n net.ipv6.conf.wlan0.accept_ra
0

将值设置为:1(如果已启用 IP 转发,则设置为 2):

$ sudo sysctl -w net.ipv6.conf.wlan0.accept_ra=1
Net.ipv6.conf.wlan0.accept_ra = 1

大多数 Linux 发行版中的 accept_ra_rt_info_max_plen 选项均默认为 0,并可通过以下命令将其设置为 64

$ sudo sysctl -w net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen=64
net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen = 64

重新启动主机后,更改将会丢失。例如,将以下命令附加到 /etc/sysctl.conf 以永久启用 RIO:

$ net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen = 64

现在可能无法更改这些配置,因为 OTBR 一直在发送 RA 消息,而两封未经请求的 RA 消息之间的时间间隔可能为几百秒。一种方法是断开连接并重新连接到 WLAN AP,以发送路由器请求消息,以便 OTBR 响应应求 RA。另一种方法是重新启动边界路由器的边界路由功能:

$ sudo ot-ctl br disable
Done
$ sudo ot-ctl br enable
Done

如果您尝试重新连接 Wi-Fi 或重启以太网接口,请确保未使用 dhcpcd 管理您的 Wi-Fi/以太网 IPv6 网络。由于每次重启接口时,dhcpcd 都会替换 accept_ra 选项,因此您的 accept_ra 配置将丢失。将以下代码行附加到 dhcpcd 配置文件(例如 /etc/dhcpcd.conf)中,以显式停用 dhcpcd 中的 IPv6:

noipv6
noipv6rs

您需要重新启动,更改才会生效。

准备 macOS 主机

默认情况下,这两个 accept_ra* 选项都会启用,但您需要将系统升级到至少 macOS Big Sur。

Ping 主机名或 IPv6 地址

现在,我们可以使用命令 ping -6 对主机名 ot-host.local ping (ping6 for macOS):

$ ping -6 ot-host.local.
PING ot-host.local.(fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927)) 56 data bytes
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=1 ttl=63 time=170 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=2 ttl=63 time=64.2 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=3 ttl=63 time=22.8 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=4 ttl=63 time=37.7 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=5 ttl=63 time=28.7 ms
...

在 Linux 主机上,此命令可能会失败,并显示 "Name or service not known" 错误。这是因为 ping 命令无法通过 mDNS 查询解析 ot-host.local. 名称。打开 /etc/nsswitch.conf 并将 mdns6_minimal 添加到以 hosts 开头的行中:

hosts:          files mdns4_minimal mdns6_minimal dns

当然,您可以随时直接对 IPv6 地址进行 ping 操作:

$ ping -6 fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927
PING fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927(fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927) 56 data bytes
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=1 ttl=63 time=32.9 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=2 ttl=63 time=27.8 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=3 ttl=63 time=29.9 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=4 ttl=63 time=73.5 ms
64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=5 ttl=63 time=26.4 ms
...

8. 取消发布设备 服务

如需移除从 SRP 客户端节点注册的地址和服务,请执行以下操作:

> srp client host remove
Done

您现在应该无法发现 _ipps._tcp 服务。

9. 恭喜

恭喜!您已成功将 OTBR 设置为线程边界路由器,以便为线程端点设备提供双向 IP 连接和服务发现。

接下来做什么?

查看下列 Codelab…

参考文档