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

1. Introducción

699d673d05a55535.png

¿Qué es 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 y la nube. Las redes Thread pueden adaptarse a los cambios de topología para evitar fallas de un solo punto.

¿Qué es OpenThread?

OpenThread, lanzado por Google, es una implementación de código abierto de Thread®.

¿Qué es un router de borde Thread?

Un router de borde Thread conecta una red 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, como mínimo, las siguientes funciones:

  • Conectividad de IP bidireccional entre redes Thread y Wi-Fi/Ethernet
  • Descubrimiento de servicios bidireccional a través de mDNS (en el vínculo Wi-Fi/Ethernet) y SRP (en la red Thread).
  • Thread sobre infraestructura 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 OpenThread (OTBR) que lanzó Google es una implementación de código abierto del router de borde Thread.

Qué compilarás

En este codelab, configurarás un router de borde Thread y conectarás tu teléfono celular a un dispositivo final Thread a través del 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 OpenThread con la función SRP
  • Cómo registrar un servicio con SRP
  • Cómo descubrir y conectarse a un dispositivo final Thread

Requisitos

  • Una estación de trabajo de Linux para compilar y escribir en la memoria flash un RCP de Thread, la CLI de OpenThread y probar la multidifusión IPv6
  • Una Raspberry Pi para el router de borde Thread
  • 2 llaves USB nRF52840 de Nordic Semiconductor (una para el RCP y otra para el dispositivo final de Thread)
  • Un teléfono iOS con al menos iOS 14 o un teléfono Android con al menos Android 8.1

2. Cómo configurar OTBR

La forma más rápida de configurar un OTBR es siguiendo la Guía de configuración de OTBR.

Una vez que se complete la configuración del OTBR, usa ot-ctl para validar que el OTBR actúe como un leader de Thread.

$ sudo ot-ctl state
leader
Done

También valida que el OTBR haya configurado automáticamente un prefijo off-mesh-routable (OMR) en los datos de la red de Thread.

$ 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

3. Configura el dispositivo final del cliente de SRP

Compila y escribe en la memoria flash la CLI de OT

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

Sin embargo, en lugar de tener OT_COMMISSIONER y OT_JOINER habilitados, 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

Cómo unirse a la red de Thread

Para unirte a la red Thread, debemos obtener el conjunto de datos operativos activos del dispositivo OTBR. Volvamos a ot-ctl y obtengamos el conjunto de datos activo:

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

Regresa a la sesión de pantalla del nodo cliente de SRP y establece 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 se unió 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 los impresos en la 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

4. Publica el servicio en el dispositivo final

El mDNS se usa ampliamente para publicar el servicio DNS-SD en vínculo local. Sin embargo, los mensajes multicast consumen demasiado ancho de banda y agotan rápidamente la batería de los dispositivos de baja potencia. Thread usa el protocolo SRP unicast para registrar sus servicios con el router de frontera 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 pantalla del nodo cliente de 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 Wi-Fi/Ethernet:

> srp client host name ot-host
Done

Para que un dispositivo en el vínculo Wi-Fi/Ethernet llegue a un dispositivo final de 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

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

5. Descubre el servicio

Cómo descubrir el servicio con un teléfono celular

54a136a8940897cc.png

Usamos la app de Service Browser 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.

Cómo descubrir 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     ""
...

6. Realiza un ping al dispositivo de destino

Cómo hacer ping desde un teléfono celular

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

bb992962e68d250b.png 888daa1df1e1a9bf.png

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

Lamentablemente, la versión para Android de la app de Network Analyzer no admite consultas 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 para iOS de la app).

Cómo usar ping desde un host Linux/macOS

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

Prepara el host de Linux

Es importante asegurarse de que RA y RIO estén habilitados en el host:

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

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

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

Y 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 es 0 de forma predeterminada. Establece 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 RIO de forma permanente:

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

Es posible que ya sea demasiado tarde para cambiar esas configuraciones porque el OTBR ya envió mensajes de RA y el intervalo entre dos mensajes de RA no solicitados podría ser de varios cientos de segundos. Una forma es desconectarse y volver a conectarse al AP Wi-Fi para enviar mensajes de solicitud de router de modo que el OTBR responda con RA solicitados. 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 conectarte a Wi-Fi o reiniciar la interfaz Ethernet, asegúrate de que no se use dhcpcd para administrar tu red IPv6 de Wi-Fi o Ethernet. Porque dhcpcd siempre anula la opción accept_ra cada vez que se reinicia la interfaz y se perderá tu configuración de accept_ra. Agrega las siguientes líneas al archivo de configuración de dhcpcd (p.ej., /etc/dhcpcd.conf) para inhabilitar IPv6 de forma explícita en dhcpcd:

noipv6
noipv6rs

Debes reiniciar el dispositivo 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 tu sistema al menos a macOS Big Sur.

Realiza un ping al nombre de host o a 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 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
...

7. Cómo anular la publicación del servicio en el dispositivo final

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

> srp client host remove
Done

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

8. Felicitaciones

¡Felicitaciones! Configuraste correctamente el OTBR como un router de borde de Thread para proporcionar conectividad IP bidireccional y descubrimiento de servicios para dispositivos finales de Thread.

Próximos pasos

Consulta algunos codelabs sobre los siguientes temas:

Documentos de referencia