Router di confine Thread - Connettività IPv6 bidirezionale e scoperta dei servizi basati su DNS

1. Introduzione

699d673d05a55535.png

Che cos'è Thread?

Thread è un protocollo di rete mesh wireless a basso consumo basato su IP che consente comunicazioni sicure tra dispositivi e tra dispositivi e cloud. Le reti Thread possono adattarsi alle modifiche della topologia per evitare errori in un unico punto.

Che cos'è OpenThread?

OpenThread rilasciato da Google è un'implementazione open source di Thread®.

Che cos'è un router di confine Thread?

Un router di confine Thread connette una rete Thread ad altre reti basate su IP, come Wi-Fi o Ethernet. Una rete Thread richiede un router di confine per connettersi ad altre reti. Un router di confine Thread supporta almeno le seguenti funzioni:

  • Connettività IP bidirezionale tra le reti Thread e Wi-Fi/Ethernet.
  • Service Discovery bidirezionale tramite mDNS (su collegamento Wi-Fi/Ethernet) e SRP (su rete Thread).
  • Thread-over-infrastructure che unisce le partizioni Thread tramite link basati su IP.
  • Messa in servizio Thread esterna (ad esempio, un cellulare) per autenticare e connettere un dispositivo Thread a una rete Thread.

OpenThread Border Router (OTBR) rilasciato da Google è un'implementazione open source del router di confine Thread.

Cosa creerai

In questo codelab, configurerai un router di confine Thread e connetterai il tuo cellulare a un dispositivo finale Thread tramite il router di confine.

Obiettivi didattici

  • Come configurare OTBR
  • Come formare una rete Thread con OTBR
  • Come creare un dispositivo CLI OpenThread con la funzionalità SRP
  • Come registrare un servizio con SRP
  • Come scoprire e raggiungere un dispositivo finale Thread

Che cosa ti serve

  • Una workstation Linux per la creazione e il flashing di un RCP Thread, della CLI OpenThread e per il test del multicast IPv6.
  • Un Raspberry Pi per il router di confine Thread.
  • 2 dongle USB Nordic Semiconductor nRF52840 (uno per l'RCP e uno per il dispositivo finale Thread).
  • Uno smartphone iOS con almeno iOS 14 o uno smartphone Android con almeno Android 8.1.

2. Configurare OTBR

Il modo più rapido per configurare un OTBR è seguire la guida alla configurazione dell'OTBR.

Una volta completata la configurazione di OTBR, utilizza ot-ctl per verificare che OTBR funga da leader Thread.

$ sudo ot-ctl state
leader
Done

Verifica inoltre che OTBR abbia configurato automaticamente un prefisso off-mesh-routable (OMR) nei dati di rete 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. Configurare il dispositivo client SRP

Crea e carica l'interfaccia a riga di comando OT

Segui il passaggio 5 del codelab Crea una rete Thread con schede nRF52840 e OpenThread per creare e caricare un dispositivo finale CLI nRF52840.

Tuttavia, anziché avere OT_COMMISSIONER e OT_JOINER abilitati, il nodo CLI richiede le funzionalità OT_SRP_CLIENT e OT_ECDSA.

Pertanto, l'invocazione completa della build dovrebbe essere simile alla seguente:

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

Unirsi alla rete Thread

Per entrare a far parte della rete Thread, dobbiamo ottenere il set di dati operativi attivo dal dispositivo OTBR. Torniamo a ot-ctl e recuperiamo il set di dati attivo:

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

Torna alla sessione della schermata del nodo client SRP e imposta il set di dati attivo:

> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

Poi avvia l'interfaccia Thread:

> ifconfig up
Done
> thread start
Done

Attendi qualche secondo e verifica se l'accesso alla rete Thread è riuscito:

> 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

Assicurati che i dati della rete corrispondano a quelli stampati sul documento OTBR. Ora possiamo eseguire il ping dell'indirizzo OMR di 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. Pubblicare il servizio sul dispositivo finale

mDNS è stato ampiamente utilizzato per pubblicare il servizio DNS-SD su link-local. Tuttavia, i messaggi multicast consumano troppa larghezza di banda ed esauriscono rapidamente la batteria dei dispositivi a basso consumo energetico. Thread utilizza il protocollo SRP unicast per registrare i propri servizi con il router di confine e si affida a quest'ultimo per pubblicizzare i servizi sul collegamento Wi-Fi o Ethernet.

Possiamo registrare un servizio con il comando srp client.

Vai alla sessione dello schermo del nodo client SRP e avvia automaticamente il client SRP:

> srp client autostart enable
Done

Imposta il nome host che verrà pubblicizzato sul link Wi-Fi/Ethernet:

> srp client host name ot-host
Done

Affinché un dispositivo sul collegamento Wi-Fi/Ethernet raggiunga un dispositivo finale Thread, è necessario pubblicizzare l'indirizzo OMR del dispositivo finale:

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

Alla fine, registra un servizio _ipps._tcp fittizio:

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

Attendi qualche secondo e dovresti vedere il servizio registrato:

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

Abbiamo completato tutta la configurazione e il servizio _ipps._tcp dovrebbe essere stato pubblicizzato sul collegamento Wi-Fi/Ethernet. È il momento di scoprire e raggiungere il dispositivo di destinazione.

5. Scopri il servizio

Scoprire il servizio con un cellulare

54a136a8940897cc.png

Utilizziamo l'app Service Browser per rilevare i servizi mDNS con lo smartphone Android. È possibile trovare un'app equivalente anche per i dispositivi mobili iOS. Apri l'app e il servizio _ipps._tcp dovrebbe essere visualizzato.

Scopri il servizio con un host Linux

Se vuoi scoprire il servizio da un altro host Linux, puoi utilizzare il comando avahi-browse.

Installa avahi-daemon e avahi-utils:

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

Risolvi il servizio:

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

Scopri il servizio con un host macOS

Puoi utilizzare dns-sd su macOS per risolvere il problema del servizio:

$ 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. Esegui il ping del dispositivo finale

Ping da un cellulare

Prendiamo come esempio lo smartphone Pixel. Possiamo trovare l'indirizzo OMR del servizio "ot-service" registrato in precedenza nella pagina dei dettagli dell'istanza del servizio nell'app Service Browser.

bb992962e68d250b.png 888daa1df1e1a9bf.png

Ora possiamo eseguire il ping dell'indirizzo OMR con un'altra app Network Analyzer.

Purtroppo, la versione Android dell'app Network Analyzer non supporta le query mDNS per l'utilità ping e non possiamo eseguire il ping del nome host ot-host.local direttamente (possiamo eseguire il ping del nome host con la versione iOS dell'app).

Eseguire il ping da un host Linux/macOS

Il router di confine Thread invia annunci del router ICMPv6 (RA) per pubblicizzare prefissi (tramite l'opzione di informazioni sul prefisso) e route (tramite l'opzione di informazioni sulla route) sul collegamento Wi-Fi/Ethernet.

Prepara l'host Linux

È importante assicurarsi che RA e RIO siano attivi sull'host:

  1. net.ipv6.conf.wlan0.accept_ra deve essere almeno 1 se l'inoltro IP non è attivato e 2 in caso contrario.
  2. net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen non deve essere inferiore a 64.

accept_ra è impostato su 1 per impostazione predefinita per la maggior parte delle distribuzioni. Tuttavia, potrebbero esserci altri daemon di rete che sostituiranno questa opzione (ad esempio, dhcpcd su Raspberry Pi sostituirà accept_ra con 0). Puoi controllare il valore di accept_ra con:

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

e imposta il valore su 1 (o 2 se l'inoltro IP è attivato) con:

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

L'opzione accept_ra_rt_info_max_plen nella maggior parte delle distribuzioni Linux è impostata su 0 per impostazione predefinita. Impostala su 64 con:

$ 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

La modifica andrà persa dopo il riavvio dell'host. Ad esempio, aggiungi i seguenti comandi a /etc/sysctl.conf per abilitare definitivamente RIO:

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

Potrebbe essere troppo tardi per modificare queste configurazioni perché OTBR ha già inviato messaggi RA e l'intervallo tra due messaggi RA non richiesti potrebbe essere di diverse centinaia di secondi. Un modo è disconnettersi e riconnettersi al punto di accesso Wi-Fi per inviare messaggi di richiesta del router in modo che OTBR risponda con annunci del router richiesti. Un'altra opzione è riavviare la funzione di routing di confine sul router di confine:

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

Se stai tentando di riconnettere il Wi-Fi o riavviare l'interfaccia Ethernet, assicurati che dhcpcd non venga utilizzato per gestire la rete IPv6 Wi-Fi/Ethernet. Perché dhcpcd esegue sempre l'override dell'opzione accept_ra ogni volta che l'interfaccia viene riavviata e la configurazione accept_ra andrà persa. Aggiungi le righe seguenti al file di configurazione dhcpcd (ad es. /etc/dhcpcd.conf) per disattivare esplicitamente IPv6 in dhcpcd:

noipv6
noipv6rs

Per applicare la modifica è necessario riavviare.

Prepara l'host macOS

Entrambe le opzioni accept_ra* sono attive per impostazione predefinita, ma devi eseguire l'upgrade del sistema almeno a macOS Big Sur.

Invia un ping al nome host o all'indirizzo IPv6

Ora possiamo eseguire il ping del nome host ot-host.local con il comando ping -6 (ping6 per 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
...

Questo comando potrebbe non riuscire sugli host Linux con l'errore "Name or service not known". Questo perché il comando ping non risolve il nome ot-host.local. con le query mDNS. Apri /etc/nsswitch.conf e aggiungi mdns6_minimal alla riga che inizia con hosts:

hosts:          files mdns4_minimal mdns6_minimal dns

Naturalmente, puoi sempre eseguire il ping dell'indirizzo IPv6 direttamente:

$ 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. Annulla la pubblicazione del servizio sul dispositivo finale

Per rimuovere l'indirizzo e il servizio registrati dal nodo client SRP:

> srp client host remove
Done

Ora non dovresti essere in grado di scoprire il servizio _ipps._tcp.

8. Complimenti

Congratulazioni, hai configurato correttamente OTBR come router di confine Thread per fornire connettività IP bidirezionale e rilevamento dei servizi per i dispositivi finali Thread.

Passaggi successivi

Dai un'occhiata ad alcuni di questi codelab…

Documenti di riferimento