Router de borde de Thread: conectividad IPv6 bidireccional y descubrimiento de servicios basado en DNS

1. Introducción

699d673d05a55535.png

¿Qué es un router de borde Thread?

Thread es un protocolo de red en malla inalámbrica de bajo consumo basado en IP que permite comunicaciones seguras entre dispositivos y entre dispositivos. Las redes de Thread pueden adaptarse a los cambios de topología para evitar puntos únicos de fallo.

Un router de borde de Thread conecta una red de Thread a otras redes basadas en IP, como Wi-Fi o Ethernet. Una red Thread requiere un router de borde para conectarse a otras redes. Un router de borde de Thread admite mínimamente las siguientes funciones:

  • Conectividad IP bidireccional entre redes Thread y Wi-Fi/Ethernet.
  • Descubrimiento de servicios bidireccional a través de mDNS (en vínculo Wi-Fi/Ethernet) y SRP (en la red Thread).
  • Subproceso sobre la infraestructura que combina particiones de Thread en vínculos basados en IP
  • Comisión de Thread externa (por ejemplo, un teléfono celular) para autenticar y unir un dispositivo Thread a una red de Thread.

El router de borde de OpenThread (OTBR) que lanzó Google es una implementación de código abierto del router de borde de Thread.

Qué compilarás

En este codelab, configurarás un router de borde de Thread y conectarás tu teléfono celular a un dispositivo final de Thread a través de él.

Qué aprenderás

  • Cómo configurar OTBR
  • Cómo formar una red Thread con OTBR
  • Cómo compilar un dispositivo de la CLI de OpenThread con la función SRP
  • Cómo registrar un servicio en SRP
  • Cómo descubrir un dispositivo final de Thread y comunicarse con él

Requisitos

  • Un dispositivo Raspberry Pi 3/4 y una tarjeta SD con al menos 8 GB de capacidad.
  • 2 placas de desarrollo de Nordic Semiconductor nRF52840.
  • Un PA de Wi-Fi sin IPv6 Router Advertising Guard habilitado en el router.
  • Un teléfono con iOS 14 (como mínimo) o Android 8.1 (como mínimo).

2. Configurar OTBR

Configurar Raspberry Pi

Configurar un dispositivo Raspberry Pi nuevo con la herramienta rpi-imager es sencillo. Para ello, sigue las instrucciones de raspberrypi.org (en lugar de usar la versión más reciente del SO Raspberry Pi en la herramienta, descarga 2021-05-07-raspios-buster-armhf-lite). Para completar los pasos para teléfonos celulares de este codelab, debes conectar la placa Raspberry Pi a un punto de acceso de Wi-Fi. Sigue esta guía para configurar la conectividad inalámbrica. Es conveniente acceder a Raspberry Pi con SSH. Obtén instrucciones aquí.

Obtener código OTBR

Accede a Raspberry Pi y clona ot-br-posix desde GitHub:

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

Compila e instala OTBR

OTBR tiene dos secuencias de comandos que inician y configuran el router de borde de Thread:

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

OTBR funciona tanto en una interfaz de Thread como en una interfaz de red de infraestructura (p.ej., Wi-Fi/Ethernet), que se especifica con INFRA_IF_NAME. OTBR crea la interfaz de Thread y recibe el nombre wpan0 de forma predeterminada. La interfaz de infraestructura tiene un valor predeterminado de wlan0 si INFRA_IF_NAME no se especifica de forma explícita. Si la placa Raspberry Pi está conectada a través de un cable Ethernet, especifica el nombre de la interfaz Ethernet (p.ej., eth0):

$ INFRA_IF_NAME=eth0 ./script/setup

Comprueba si OTBR se instaló correctamente:

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

Se espera que el servicio otbr-agent no esté activo, ya que requiere un chip RCP para ejecutarse.

Reinicia la Raspberry Pi para que se apliquen los cambios.

Compila e instala el firmware RCP

OTBR admite un chip de radio 15.4 en modo Radio Coprocesador (RCP). En este modo, la pila de OpenThread se ejecuta en el lado del host y transmite o recibe fotogramas a través del transceptor IEEE802.15.4.

Sigue el paso 4 del codelab Cómo compilar una red Thread con placas nRF52840 y OpenThread para compilar y escribir en la memoria flash un dispositivo RCP nRF52840:

$ script/build nrf52840 USB_trans

Inicia la OTBR y verifica el estado

Conecta la placa nRF52840 a la placa Raspberry Pi e inicia el servicio otbr-agent:

$ sudo service otbr-agent restart

Verifica que el servicio otbr-agent esté activo:

$ 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. Cómo formar una red Thread

Hay un comando ot-ctl que se puede usar para controlar el servicio otbr-agent. ot-ctl acepta todos los comandos de la CLI de OpenThread. Consulta la Guía de la CLI de OpenThread para obtener más información.

Crea una red Thread con 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

Espera unos segundos, deberíamos poder ver que OTBR actúa como un leader de subproceso y hay un prefijo off-mesh-routable (OMR) en los datos de red de 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 del cliente de SRP

Compila e instala en la memoria flash de la CLI de OT

Sigue el paso 5 del codelab Cómo compilar una red Thread con placas nRF52840 y OpenThread para compilar y escribir en la memoria flash un dispositivo final de la CLI de nRF52840.

Pero, en lugar de tener habilitados OT_COMMISSIONER y OT_JOINER, el nodo de la CLI requiere las funciones OT_SRP_CLIENT y OT_ECDSA.

Por lo tanto, la invocación de compilación completa debería verse de la siguiente manera:

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

Únete a la red OTBR

Para unir la red de Thread que creó el servicio otbr-agent, necesitamos obtener el conjunto de datos operativo activo del dispositivo OTBR. Regresemos a la línea de comandos de otbr-agent y obtengamos el conjunto de datos activo:

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

Regresa a la sesión de la pantalla del nodo de cliente de SRP y configura el conjunto de datos activo:

> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

Luego, inicia la interfaz de Thread:

> ifconfig up
Done
> thread start
Done

Espera unos segundos y verifica si te uniste a la red Thread se realizó correctamente:

> 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

Asegúrate de que los datos de red coincidan con los que están impresos en OTBR. Ahora podemos hacer ping a la dirección OMR de 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. Publicación del Servicio en el Dispositivo Final

La mDNS se ha usado ampliamente en la publicación del servicio de DNS-SD en vínculos locales. Sin embargo, los mensajes multidifusión consumen demasiado ancho de banda y agotan la batería de los dispositivos de baja potencia rápidamente. Thread usa el protocolo SRP de unidifusión para registrar sus servicios con el router de borde y depende de este para anunciar los servicios en el vínculo Wi-Fi o Ethernet.

Podemos registrar un servicio con el comando srp client.

Ve a la sesión de la pantalla del nodo del cliente de SRP y, luego, inicia el cliente de SRP automáticamente:

> srp client autostart enable
Done

Establece el nombre de host que se anunciará en el enlace Wi-Fi/Ethernet:

> srp client host name ot-host
Done

Para que un dispositivo con el vínculo Wi-Fi/Ethernet llegue a un dispositivo final Thread, se debe anunciar la dirección OMR del dispositivo final:

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

Al final, registra un servicio _ipps._tcp falso:

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

Espera unos segundos y deberíamos poder ver el servicio registrado:

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

Se completaron todos los trabajos de configuración y se debería haber anunciado el servicio _ipps._tcp en el vínculo Wi-Fi/Ethernet. Es hora de descubrir y llegar al dispositivo final.

6. Descubre el servicio

Descubre el servicio con un teléfono celular

54a136a8940897cc.png

Usamos la app del Navegador de servicios para descubrir servicios de mDNS con el teléfono Android. También se puede encontrar una app equivalente para dispositivos móviles iOS. Abre la app y debería aparecer el servicio _ipps._tcp.

Descubre el servicio con un host de Linux

Si quieres descubrir el servicio desde otro host de Linux, puedes usar el comando avahi-browse.

Instala avahi-daemon y avahi-utils:

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

Resuelve el servicio:

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

Descubre el servicio con un host de macOS

Puedes usar dns-sd en macOS para resolver el servicio:

$ 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. Haz ping en el dispositivo final

Cómo hacer ping desde un teléfono celular

Tomemos el teléfono Pixel como ejemplo. Podemos buscar la dirección OMR del servicio “OT-service” registrado anteriormente. en la página de detalles de la instancia de servicio en la app del navegador de servicios.

bb992962e68d250b.png 888daa1df1e1a9bf.png

Ahora podemos hacer ping a la dirección OMR con otra app de Network Analyzer.

Lamentablemente, la versión para Android de la app de Network Analyzer no admite consultas de mDNS para la utilidad ping y no podemos hacer ping al nombre de host ot-host.local directamente (podemos hacer ping al nombre de host con la versión de iOS de la app).

Haz ping desde un host de Linux/macOS

El router de borde de Thread envía anuncios de router ICMPv6 (RA) para anunciar prefijos (mediante la opción de información de prefijo) y rutas (mediante la opción de información de ruta) en el vínculo Wi-Fi/Ethernet.

Preparar host de Linux

Es importante que te asegures de que la RA y el RIO estén habilitados en tu host:

  1. net.ipv6.conf.wlan0.accept_ra debe ser de al menos 1 si el reenvío de IP no está habilitado. De lo contrario, debe ser 2.
  2. net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen no debe ser menor que 64.

El valor predeterminado de accept_ra es 1 para la mayoría de las distribuciones. Sin embargo, puede haber otros daemons de red que anulen esta opción (por ejemplo, dhcpcd en Raspberry Pi anulará accept_ra a 0). Puedes verificar el valor accept_ra con lo siguiente:

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

Configura el valor en 1 (o 2 en caso de que el reenvío de IP esté habilitado) con lo siguiente:

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

De forma predeterminada, la opción accept_ra_rt_info_max_plen en la mayoría de las distribuciones de Linux es 0. Configúrala en 64 con el siguiente comando:

$ 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

El cambio se perderá después de reiniciar el host. Por ejemplo, agrega los siguientes comandos a /etc/sysctl.conf para habilitar RIO de forma permanente:

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

Puede ser demasiado tarde para cambiar esas configuraciones porque el OTBR ya ha estado enviando mensajes RA, y el intervalo entre dos mensajes RA no solicitados podría ser de varios cientos de segundos. Una forma es desconectarse y volver a conectarse al PA de Wi-Fi para enviar mensajes de solicitud de router, de modo que OTBR responda a las RA solicitadas. Otra opción es reiniciar la función de enrutamiento de borde en el router de borde:

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

Si estás intentando volver a conectar la red Wi-Fi o reiniciar la interfaz Ethernet, asegúrate de que no se use dhcpcd para administrar la red IPv6 de Wi-Fi o Ethernet. dhcpcd siempre anula la opción accept_ra cada vez que se reinicia la interfaz y se pierde la configuración de accept_ra. Agrega las siguientes líneas al archivo de configuración dhcpcd (p.ej., /etc/dhcpcd.conf) para inhabilitar explícitamente IPv6 en dhcpcd:

noipv6
noipv6rs

Debes reiniciar el dispositivo para que se aplique el cambio.

Prepara host de macOS

Ambas opciones de accept_ra* están habilitadas de forma predeterminada, pero debes actualizar tu sistema a macOS Big Sur, como mínimo.

Haz ping al nombre de host o la dirección IPv6

Ahora, podemos hacer ping al nombre de host ot-host.local con el 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
...

Este comando puede fallar en hosts Linux con el error "Name or service not known". Esto se debe a que el comando ping no resuelve el nombre ot-host.local. con consultas de mDNS. Abre /etc/nsswitch.conf y agrega mdns6_minimal a la línea que comienza con hosts:

hosts:          files mdns4_minimal mdns6_minimal dns

Por supuesto, siempre puedes hacer ping directamente a la dirección 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. Anula la publicación del Servicio para el dispositivo final

Para quitar la dirección y el servicio registrados desde el nodo cliente de SRP, sigue estos pasos:

> srp client host remove
Done

No deberías poder descubrir el servicio _ipps._tcp en este momento.

9. Felicitaciones

Felicitaciones, configuraste correctamente OTBR como router de borde de Thread para proporcionar conectividad IP bidireccional y descubrimiento de servicios para dispositivos finales de Thread.

¿Qué sigue?

Consulta algunos codelabs sobre los siguientes temas:

Documentos de referencia