Router de borde Thread: detección de conectividad IPv6 y servicio basados en DNS

1. Introducción

699d673d05a55535.png

¿Qué es un router de borde de Thread?

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

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

  • Conectividad de IP bidireccional entre redes Thread y Wi-Fi o Ethernet.
  • Detección bidireccional de servicios mediante mDNS (en vínculos Wi-Fi o Ethernet) y SRP (en redes Thread).
  • Thread-over-Infrastructure que combina particiones de Thread en vínculos basados en IP
  • Comisión externa de Thread (por ejemplo, un teléfono celular) para autenticar y unir un dispositivo Thread a una red Thread.

El router de borde de Thread (OTBR) lanzado por 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 de extremo de Thread mediante el router de borde.

Qué aprenderás

  • Cómo configurar OTBR
  • Cómo formar una red Thread con OTBR
  • Cómo compilar un dispositivo de CLI de Thread con la función de SRP
  • Cómo registrar un servicio con SRP
  • Cómo descubrir y llegar a un dispositivo final de Thread

Requisitos

  • Un dispositivo Raspberry Pi de 3/4 y una tarjeta SD con capacidad de 8 GB como mínimo.
  • 2 placas de desarrollo Nordic Semiconductor nRF52840.
  • Un PA de Wi-Fi sin Guarding de publicidad de router IPv6 habilitado en el router.
  • Debes tener un teléfono con iOS 14 o Android 8.1 como mínimo.

2. Configurar OTBR

Configura Raspberry Pi

Es fácil configurar un dispositivo Raspberry Pi con la herramienta rpi-imager. Para ello, debes seguir las instrucciones en raspberrypi.org (en lugar de usar la versión más reciente de Raspberry Pi OS en la herramienta, descarga 2021-05-07-raspios-buster-armhf-lite por tu cuenta). Para completar los pasos del teléfono celular en este codelab, debes conectar la placa Raspberry Pi a un PA de Wi-Fi. Sigue esta guía para configurar la conectividad inalámbrica. Es conveniente acceder a Raspberry Pi con SSH y consultar las instrucciones aquí.

Obtener código OTBR

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

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

Compilación e instalación de 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 o Ethernet) que se especifica con INFRA_IF_NAME. OTBR crea la interfaz Thread y se llama wpan0 de forma predeterminada, y la interfaz de infraestructura tiene un valor predeterminado de wlan0 si no se especifica INFRA_IF_NAME de forma explícita. Si tu Raspberry Pi está conectado mediante un cable Ethernet, especifica el nombre de la interfaz Ethernet (p.ej., eth0):

$ INFRA_IF_NAME=eth0 ./script/setup

Verifica 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 porque requiere un chip RCP para ejecutarse.

Reinicia Raspberry Pi para aplicar los cambios.

Cómo compilar e instalar el firmware RCP

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

Sigue el paso 4 del codelab Build a Thread with nRF52840 boards and OpenThread para compilar y escribir en la memoria flash un dispositivo RCP nRF52840.

$ script/build nrf52840 USB_trans

Iniciar OTBR y verificar el estado

Conecta la placa nRF52840 a tu Raspberry Pi y, luego, 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 detalles.

Formar 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 Thread 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. Configura el dispositivo final de cliente de SRP

Cree y escriba en la CLI de OT

Sigue el paso 5 del codelab Build a Thread with nRF52840 boards and OpenThread para compilar y escribir en la memoria flash un dispositivo final de la CLI nRF52840.

Sin embargo, en lugar de tener habilitados OT_COMMISSIONER y OT_JOINER, el nodo de la CLI requiere 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 de OTBR

Para unir la red Thread creada por el servicio otbr-agent, debemos obtener el conjunto de datos operativo activo del dispositivo OTBR. Volvamos a la línea de comandos de otbr-agent y obtenga el conjunto de datos activo:

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

Regresa a la sesión de pantalla del nodo de cliente 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 correctamente a la red Thread:

> 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 el que se imprime 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. Publicar el Servicio en el Dispositivo Final

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

Podemos registrar un servicio con el comando srp client.

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

> srp client autostart enable
Done

Establece el nombre de host que se anunciará en el vínculo de Wi-Fi o Ethernet:

> srp client host name ot-host
Done

Para que un dispositivo en el vínculo de Wi-Fi o 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 podremos ver el servicio registrado:

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

Completamos toda la configuración y el servicio de _ipps._tcp debería haberse anunciado en el vínculo de Wi-Fi o Ethernet. Es hora de descubrir y llegar al dispositivo final ahora.

6. Descubre el servicio

Descubra el servicio con un teléfono celular

54a136a8940897cc.png

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

Descubra 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 al dispositivo final

Hacer ping desde un teléfono celular

Tomemos el teléfono Pixel como ejemplo. Podemos encontrar la dirección OMR del servicio registrado anteriormente "ot-service" en la página de detalles de la instancia de servicio en la app de 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 de Android de la app de Network Analyzer no admite consultas de mDNS para la utilidad de ping y no podemos hacer ping directamente al nombre de host ot-host.local (podemos hacer ping al nombre de host con la versión de iOS de la app).

Haz ping desde un host de Linux o macOS

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

Prepara el host de Linux

Es importante asegurarse de que las cuentas adquiridas recientemente y las de RA y RIO estén habilitadas en su host:

  1. net.ipv6.conf.wlan0.accept_ra debe ser al menos 1 si el reenvío de IP no está habilitado y 2 en caso contrario.
  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, es posible que haya otros daemons de red que anularán esta opción (por ejemplo, dhcpcd en Raspberry Pi anulará accept_ra en 0). Puedes verificar el valor accept_ra con lo siguiente:

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

Establece 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

La opción accept_ra_rt_info_max_plen en la mayoría de las distribuciones de Linux se establece de forma predeterminada en 0, configúrala en 64 con lo siguiente:

$ 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 permanentemente RIO:

$ 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 de RA y el intervalo entre dos mensajes de RA no solicitados podría ser de varios cientos de segundos. Una forma es desconectarte y volver a conectarte a un PA de Wi-Fi para enviar mensajes de solicitudes del router, de modo que OTBR responda con 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 intentas volver a conectar Wi-Fi o reiniciar la interfaz de Ethernet, asegúrate de que no se use dhcpcd para administrar tu red IPv6 o Ethernet. Debido a que dhcpcd siempre anula la opción accept_ra cada vez que se reinicia la interfaz, se perderá la configuración de accept_ra. Agregue líneas debajo del archivo de configuración dhcpcd (p.ej., /etc/dhcpcd.conf) para inhabilitar explícitamente IPv6 en dhcpcd:

noipv6
noipv6rs

Debes reiniciar para que se aplique el cambio.

Prepara el host de macOS

Ambas opciones de accept_ra* están habilitadas de forma predeterminada, pero debes actualizar el sistema a macOS Big Sur al menos.

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
...

Es posible que este comando falle en los hosts de 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 las 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 a la dirección IPv6 directamente:

$ 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. Anular la publicación del servicio en el dispositivo final

Para quitar la dirección y el servicio registrados en el nodo de cliente de SRP, haz lo siguiente:

> srp client host remove
Done

No deberías poder descubrir el servicio de _ipps._tcp ahora.

9. Felicitaciones

Felicitaciones, configuraste correctamente OTBR como router de borde de Thread a fin de 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