Roteador de borda do Thread: conectividade IPv6 bidirecional e descoberta de serviços baseada em DNS

1. Introdução

699d673d05a55535.png

O que é um roteador de borda do Thread?

O Thread é um protocolo de rede mesh sem fio de baixo consumo e baseado em IP que permite comunicações seguras entre dispositivos e entre nuvens. As redes Thread podem se adaptar às mudanças de topologia para evitar um ponto único de falha.

O roteador de borda do Thread conecta uma rede Thread a outras redes baseadas em IP, como Wi-Fi ou Ethernet. Uma rede Thread requer um roteador de borda para se conectar a outras redes. Um roteador de borda do Thread oferece suporte mínimo às seguintes funções:

  • Conectividade de IP bidirecional entre as redes Thread e Wi-Fi/Ethernet.
  • Descoberta de serviços bidirecionais via mDNS (em link Wi-Fi/Ethernet) e SRP (na rede Thread).
  • Thread sobre infraestrutura que mescla partições de Thread sobre links baseados em IP.
  • Comissionamento externo de Thread (por exemplo, um smartphone) para autenticar e conectar um dispositivo Thread a uma rede Thread.

O roteador de borda do OpenThread (OTBR, na sigla em inglês) lançado pelo Google é uma implementação de código aberto do roteador de borda do Thread.

O que você vai criar

Neste codelab, você vai configurar um roteador de borda do Thread e conectar seu smartphone a um dispositivo final do Thread usando esse roteador.

O que você vai aprender

  • Como configurar o OTBR
  • Como formar uma rede Thread com OTBR
  • Como criar um dispositivo da CLI OpenThread com o recurso SRP
  • Como registrar um serviço no SRP
  • Como descobrir e alcançar um dispositivo final Thread.

O que é necessário

  • Um dispositivo Raspberry Pi 3/4 e um cartão SD com capacidade de pelo menos 8 GB.
  • 2 placas de desenvolvimento Nordic Semiconductor nRF52840.
  • Um AP Wi-Fi sem o Anúncio do roteador IPv6 ativado no roteador.
  • Um smartphone iOS com pelo menos o iOS 14 ou o Android 8.1 ou mais recente.

2. Configurar OTBR

Configurar o Raspberry Pi

É simples configurar um novo dispositivo Raspberry Pi com a ferramenta rpi-imager seguindo as instruções em raspberrypi.org (em vez de usar o SO Raspberry Pi mais recente na ferramenta, faça o download de 2021-05-07-raspios-buster-armhf-lite por conta própria). Para concluir as etapas para smartphones neste codelab, você precisa conectar o Raspberry Pi a um AP Wi-Fi. Siga este guia para configurar a conectividade sem fio. É conveniente fazer login no Raspberry Pi com SSH. Veja as instruções aqui.

Receber código OTBR

Faça login no Raspberry Pi e clone o ot-br-posix do GitHub:

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

Criar e instalar o OTBR

O OTBR tem dois scripts que inicializam e configuram o roteador de borda do Thread:

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

O OTBR funciona em uma interface Thread e em interface de rede de infraestrutura (por exemplo, Wi-Fi/Ethernet), que é especificada com INFRA_IF_NAME. A interface Thread é criada pelo próprio OTBR e nomeada wpan0 por padrão. A interface da infraestrutura tem um valor padrão de wlan0 se INFRA_IF_NAME não for explicitamente especificado. Se o Raspberry Pi estiver conectado por um cabo Ethernet, especifique o nome da interface Ethernet (por exemplo, eth0):

$ INFRA_IF_NAME=eth0 ./script/setup

Verifique se o OTBR foi instalado com sucesso:

$ 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)

Espera-se que o serviço otbr-agent não esteja ativo, porque ele exige um ícone RCP para ser executado.

Reinicie o Raspberry Pi para que as mudanças entrem em vigor.

Criar e atualizar o firmware do RCP

O OTBR oferece suporte a um chip de rádio 15.4 no modo coprocessador de rádio (RCP, na sigla em inglês). Nesse modo, a pilha do OpenThread é executada no lado do host e transmite/recebe frames pelo transceptor IEEE802.15.4.

Siga a etapa 4 do codelab Criar uma rede Thread com placas nRF52840 e OpenThread para criar e atualizar um dispositivo RCP nRF52840:

$ script/build nrf52840 USB_trans

Iniciar OTBR e verificar status

Conecte a placa nRF52840 ao seu Raspberry Pi e inicie o serviço otbr-agent:

$ sudo service otbr-agent restart

Verifique se o serviço otbr-agent está ativo:

$ 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. Formar uma rede Thread

Há um comando ot-ctl que pode ser usado para controlar o serviço otbr-agent. ot-ctl aceita todos os comandos da CLI do OpenThread. Consulte o Guia da CLI do OpenThread para mais detalhes.

Formar uma rede Thread com 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

Aguarde alguns segundos e observe que o OTBR está agindo como uma linha de execução leader e que há um prefixo off-mesh-routable (OMR) nos dados da rede Thread:

$ 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. Configurar dispositivo final do cliente SRP

Criar e atualizar a CLI OT

Siga a etapa 5 do codelab Criar uma rede Thread com placas nRF52840 e OpenThread para criar e atualizar um dispositivo final da CLI nRF52840.

Mas, em vez de ter OT_COMMISSIONER e OT_JOINER ativados, o nó da CLI requer os recursos OT_SRP_CLIENT e OT_ECDSA.

A invocação completa do build ficará assim:

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

Conectar-se à rede OTBR

Para mesclar a rede Thread criada pelo serviço otbr-agent, precisamos receber o conjunto de dados operacional ativo do dispositivo OTBR. Volte para a linha de comando otbr-agent e acesse o conjunto de dados ativo:

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

Retorne à sessão da tela do nó do cliente SRP e defina o conjunto de dados ativo:

> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

Em seguida, inicie a interface Thread:

> ifconfig up
Done
> thread start
Done

Aguarde alguns segundos e verifique se a entrada na rede Thread foi concluída:

> 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

Verifique se os dados de rede correspondem aos dados impressos no OTBR. Agora podemos dar um ping no endereço OMR do OTBR:

> 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. Publicar o Serviço no Dispositivo Final

O mDNS tem sido amplamente usado para publicar o serviço DNS-SD em link-local. Mas as mensagens multicast consomem muita largura de banda e acabam com a bateria para dispositivos de baixa energia rapidamente. O Thread usa o protocolo unicast SRP para registrar serviços com o roteador de borda e depende dele para anunciar os serviços no link de Wi-Fi ou Ethernet.

Podemos registrar um serviço com o comando srp client.

Acesse a sessão da tela do nó do cliente SRP e inicie o cliente SRP automaticamente:

> srp client autostart enable
Done

Defina o nome do host que será anunciado no link de Wi-Fi/Ethernet:

> srp client host name ot-host
Done

Para que um dispositivo no link Wi-Fi/Ethernet possa alcançar um dispositivo final Thread, o endereço OMR do dispositivo final precisa ser anunciado:

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

No final, registre um serviço _ipps._tcp falso:

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

Aguarde alguns segundos para ver o serviço registrado:

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

Concluímos todo o trabalho de configuração, e o serviço do _ipps._tcp deveria ter sido anunciado no link de Wi-Fi/Ethernet. É hora de descobrir e chegar ao dispositivo final!

6. Conheça o serviço

Descobrir o serviço com um smartphone

54a136a8940897cc.png

Usamos o app Navegador de serviços para descobrir serviços de mDNS com o smartphone Android. Também é possível encontrar um app equivalente para dispositivos móveis iOS. Abra o app. O serviço _ipps._tcp vai aparecer.

Descobrir o serviço com um host do Linux

Se você quiser descobrir o serviço de outro host do Linux, use o comando avahi-browse.

Instale avahi-daemon e avahi-utils:

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

Resolva o serviço:

$ 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 = []
...

Descobrir o serviço com um host do macOS

É possível usar dns-sd no macOS para resolver o serviço:

$ 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. Dar um ping no dispositivo final

Ping de um smartphone

Considere o smartphone Pixel como exemplo. Podemos descobrir o endereço OMR do serviço "ot-service" registrado anteriormente. na página de detalhes da instância de serviço no app do navegador de serviços.

bb992962e68d250b.png 888daa1df1e1a9bf.png

Agora podemos dar um ping no endereço OMR com outro app Network Analyzer.

Infelizmente, a versão para Android do app Network Analyzer não é compatível com consultas de mDNS para o utilitário de ping e não podemos dar um ping no nome do host ot-host.local diretamente. Podemos dar um ping no nome do host com a versão do app para iOS.

Ping de um host do Linux/macOS

O roteador de borda do Thread envia os anúncios de roteador (RA) ICMPv6 para divulgar prefixos (pela opção de informações de prefixo) e rotas (pela opção de informações de rota) no link de Wi-Fi/Ethernet.

Preparar o host do Linux

É importante verificar se a RA e o RIO estão ativadas no seu host:

  1. net.ipv6.conf.wlan0.accept_ra precisa ser pelo menos 1 se o encaminhamento de IP não estiver ativado. Caso contrário, será 2.
  2. net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen não pode ser menor que 64.

o accept_ra é definido como 1 para a maioria das distribuições. Mas pode haver outros daemons de rede que vão substituir essa opção (por exemplo, dhcpcd no Raspberry Pi substituirá accept_ra por 0). É possível verificar o valor accept_ra com:

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

E defina o valor como 1 (ou 2 caso o encaminhamento de IP esteja ativado) com:

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

Na maioria das distribuições do Linux, a opção accept_ra_rt_info_max_plen é padrão como 0. Defina-a como 64 com:

$ 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

A alteração será perdida após a reinicialização do host. Por exemplo, anexe os comandos abaixo a /etc/sysctl.conf para ativar permanentemente o RIO:

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

Pode ser tarde demais para alterar essas configurações porque o OTBR já está enviando mensagens de RA e o intervalo entre duas mensagens de RA não solicitadas pode ser de várias centenas de segundos. Uma maneira é desconectar e reconectar ao AP Wi-Fi para enviar mensagens de solicitação de roteador para que o OTBR responda com as RAs solicitadas. Outra opção é reiniciar a função "Border Routing" no Border Router:

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

Se você estiver tentando se reconectar ao Wi-Fi ou reiniciar a interface Ethernet, certifique-se de que dhcpcd não seja usado para gerenciar sua rede Wi-Fi/Ethernet IPv6. Como o dhcpcd sempre substitui a opção accept_ra toda vez que a interface é reiniciada, e a configuração accept_ra é perdida. Anexe as linhas abaixo ao arquivo de configuração dhcpcd (por exemplo, /etc/dhcpcd.conf) para desativar explicitamente o IPv6 em dhcpcd:

noipv6
noipv6rs

É necessário reiniciar para que a alteração entre em vigor.

Preparar o host do macOS

As duas opções do accept_ra* estão ativadas por padrão, mas é necessário fazer upgrade do sistema para, no mínimo, o macOS Big Sur.

Dê um ping no nome do host ou no endereço IPv6

Agora podemos dar um ping no nome do host ot-host.local com o comando ping -6 (ping6 para 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
...

Esse comando pode falhar em hosts do Linux com o erro "Name or service not known". Isso ocorre porque o comando ping não está resolvendo o nome ot-host.local. com consultas mDNS. Abra /etc/nsswitch.conf e adicione mdns6_minimal à linha que começa com hosts:

hosts:          files mdns4_minimal mdns6_minimal dns

É claro que você sempre pode dar um ping diretamente no endereço IPv6:

$ 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. Cancelar a publicação do serviço no dispositivo final

Para remover o endereço e o serviço registrados do nó do cliente SRP:

> srp client host remove
Done

Não é possível descobrir o serviço _ipps._tcp agora.

9. Parabéns

Parabéns! Você configurou o OTBR como um roteador de borda do Thread para oferecer conectividade de IP bidirecional e descoberta de serviço para dispositivos finais Thread.

Qual é a próxima etapa?

Confira alguns destes codelabs:

Documentos de referência