스레드 보더 라우터 - 양방향 IPv6 연결 및 DNS 기반 서비스 검색

1. 소개

699d673d05a55535.png

스레드란 무엇인가요?

Thread는 기기 간 및 기기-클라우드 간 보안 통신을 지원하는 IP 기반 저전력 무선 메시 네트워킹 프로토콜입니다. 스레드 네트워크는 토폴로지 변경사항에 적응하여 단일 장애점을 방지할 수 있습니다.

OpenThread란 무엇인가요?

Google에서 출시한 OpenThread는 Thread®의 오픈소스 구현입니다.

스레드 보더 라우터란 무엇인가요?

스레드 보더 라우터는 스레드 네트워크를 Wi-Fi 또는 이더넷과 같은 다른 IP 기반 네트워크에 연결합니다. 스레드 네트워크를 다른 네트워크에 연결하려면 보더 라우터가 필요합니다. 스레드 보더 라우터는 다음 기능을 최소한 지원합니다.

  • 스레드와 Wi-Fi/이더넷 네트워크 간의 양방향 IP 연결
  • mDNS (Wi-Fi/이더넷 링크) 및 SRP (스레드 네트워크)를 통한 양방향 서비스 검색
  • IP 기반 링크를 통해 Thread 파티션을 병합하는 Thread-over-infrastructure
  • 스레드 기기를 인증하고 스레드 네트워크에 연결하는 외부 스레드 커미셔닝 (예: 휴대전화)

Google에서 출시한 OpenThread Border Router (OTBR)는 스레드 보더 라우터의 오픈소스 구현입니다.

빌드할 항목

이 Codelab에서는 스레드 보더 라우터를 설정하고 보더 라우터를 통해 휴대전화를 스레드 종단 기기에 연결합니다.

학습할 내용

  • OTBR 설정 방법
  • OTBR로 Thread 네트워크를 형성하는 방법
  • SRP 기능으로 OpenThread CLI 기기를 빌드하는 방법
  • SRP에 서비스를 등록하는 방법
  • Thread 최종 기기를 검색하고 연결하는 방법

필요한 항목

  • Thread RCP, OpenThread CLI를 빌드 및 플래시하고 IPv6 멀티캐스트를 테스트하기 위한 Linux 워크스테이션
  • 스레드 보더 라우터용 Raspberry Pi
  • Nordic Semiconductor nRF52840 USB 도구 2개 (RCP용 1개, 스레드 엔드 기기용 1개)
  • iOS 14 이상을 실행하는 iOS 휴대전화 또는 Android 8.1 이상을 실행하는 Android 휴대전화

2. OTBR 설정

OTBR을 설정하는 가장 빠른 방법은 OTBR 설정 가이드를 따르는 것입니다.

OTBR 설정이 완료되면 ot-ctl를 사용하여 OTBR이 스레드 leader로 작동하는지 확인합니다.

$ sudo ot-ctl state
leader
Done

또한 OTBR이 스레드 네트워크 데이터에 off-mesh-routable (OMR) 접두사를 자동으로 구성했는지 확인합니다.

$ 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. SRP 클라이언트 최종 기기 설정

OT CLI 빌드 및 플래시

nRF52840 보드 및 OpenThread으로 Thread 네트워크 빌드 Codelab의 5단계에 따라 nRF52840 CLI 최종 기기를 빌드하고 플래시합니다.

하지만 CLI 노드에는 OT_COMMISSIONEROT_JOINER가 사용 설정된 대신 OT_SRP_CLIENTOT_ECDSA 기능이 필요합니다.

따라서 전체 빌드 호출은 다음과 같습니다.

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

스레드 네트워크에 참여

Thread 네트워크에 참여하려면 OTBR 기기에서 활성 운영 데이터 세트를 가져와야 합니다. ot-ctl로 돌아가 활성 데이터 세트를 가져옵니다.

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

SRP 클라이언트 노드 화면 세션으로 돌아가 활성 데이터 세트를 설정합니다.

> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

그런 다음 Thread 인터페이스를 시작합니다.

> ifconfig up
Done
> thread start
Done

몇 초 정도 기다린 후 스레드 네트워크에 성공적으로 연결되었는지 확인합니다.

> 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

네트워크 데이터가 OTBR에 인쇄된 데이터와 일치하는지 확인합니다. 이제 OTBR의 OMR 주소를 핑할 수 있습니다.

> 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. 최종 기기에 서비스 게시

mDNS는 링크-로컬에서 DNS-SD 서비스를 게시하는 데 널리 사용되었습니다. 하지만 멀티캐스트 메시지는 대역폭을 너무 많이 사용하고 저전력 기기의 배터리를 빠르게 소모합니다. Thread는 unicast SRP 프로토콜을 사용하여 경계 라우터에 서비스를 등록하고 경계 라우터를 사용하여 Wi-Fi 또는 이더넷 링크에서 서비스를 광고합니다.

srp client 명령어로 서비스를 등록할 수 있습니다.

SRP 클라이언트 노드 화면 세션으로 이동하여 SRP 클라이언트를 자동으로 시작합니다.

> srp client autostart enable
Done

Wi-Fi/이더넷 링크에 광고할 호스트 이름을 설정합니다.

> srp client host name ot-host
Done

Wi-Fi/이더넷 링크의 기기가 스레드 최종 기기에 도달하려면 최종 기기의 OMR 주소를 광고해야 합니다.

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

마지막으로 가짜 _ipps._tcp 서비스를 등록합니다.

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

몇 초 정도 기다리면 등록된 서비스가 표시됩니다.

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

모든 설정 작업이 완료되었으며 _ipps._tcp 서비스가 Wi-Fi/이더넷 링크에 광고되었을 것입니다. 이제 최종 기기를 검색하고 연결할 시간입니다.

5. 서비스 살펴보기

휴대전화로 서비스 검색

54a136a8940897cc.png

서비스 브라우저 앱을 사용하여 Android 휴대전화에서 mDNS 서비스를 검색합니다. iOS 휴대기기에도 상응하는 앱을 찾을 수 있습니다. 앱을 열면 서비스 _ipps._tcp가 표시됩니다.

Linux 호스트로 서비스를 검색합니다.

다른 Linux 호스트에서 서비스를 검색하려면 avahi-browse 명령어를 사용하면 됩니다.

avahi-daemonavahi-utils를 설치합니다.

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

서비스를 해결합니다.

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

macOS 호스트로 서비스를 검색

macOS에서 dns-sd를 사용하여 서비스를 확인할 수 있습니다.

$ 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. 최종 기기 핑

휴대전화에서 핑하기

Pixel 휴대전화를 예로 들면 서비스 브라우저 앱의 서비스 인스턴스 세부정보 페이지에서 이전에 등록된 서비스 'ot-service'의 OMR 주소를 확인할 수 있습니다.

bb992962e68d250b.png 888daa1df1e1a9bf.png

이제 다른 네트워크 분석기 앱으로 OMR 주소를 핑할 수 있습니다.

안타깝게도 Android 버전의 Network Analyzer 앱은 ping 유틸리티의 mDNS 쿼리를 지원하지 않으므로 호스트 이름 ot-host.local을 직접 핑할 수 없습니다 (iOS 버전의 앱으로 호스트 이름을 핑할 수는 있음).

Linux/macOS 호스트에서 핑

스레드 경계 라우터는 ICMPv6 라우터 광고 (RA)를 전송하여 Wi-Fi/이더넷 링크에서 프리픽스 (프리픽스 정보 옵션 사용) 및 경로 (경로 정보 옵션 사용)를 광고합니다.

Linux 호스트 준비

호스트에서 RA 및 RIO가 사용 설정되어 있는지 확인하는 것이 중요합니다.

  1. net.ipv6.conf.wlan0.accept_ra는 IP 전달이 사용 설정되지 않은 경우 1 이상이어야 하며, 그렇지 않은 경우에는 2이어야 합니다.
  2. net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen64보다 작아서는 안 됩니다.

대부분의 배포판에서는 accept_ra가 기본적으로 1로 설정됩니다. 하지만 이 옵션을 재정의하는 다른 네트워크 데몬이 있을 수 있습니다 (예: Raspberry Pi의 dhcpcdaccept_ra0로 재정의함). 다음을 사용하여 accept_ra 값을 확인할 수 있습니다.

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

다음과 같이 값을 1 (또는 IP 전달이 사용 설정된 경우 2)로 설정합니다.

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

대부분의 Linux 배포판에서 accept_ra_rt_info_max_plen 옵션은 기본적으로 0로 설정되어 있습니다. 다음과 같이 64로 설정합니다.

$ 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

호스트를 재부팅하면 변경사항이 사라집니다. 예를 들어 아래 명령어를 /etc/sysctl.conf에 추가하여 RIO를 영구적으로 사용 설정할 수 있습니다.

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

OTBR이 이미 RA 메시지를 전송하고 있으며 두 개의 요청하지 않은 RA 메시지 간의 간격이 수백 초일 수 있으므로 이러한 구성을 변경하기에는 너무 늦을 수 있습니다. 한 가지 방법은 Wi-Fi AP의 연결을 해제했다가 다시 연결하여 라우터 요청 메시지를 전송하여 OTBR이 요청된 RA로 응답하도록 하는 것입니다. 다른 옵션은 보더 라우터에서 보더 라우팅 기능을 다시 시작하는 것입니다.

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

Wi-Fi를 다시 연결하거나 이더넷 인터페이스를 다시 시작하려는 경우 Wi-Fi/이더넷 IPv6 네트워크를 관리하는 데 dhcpcd가 사용되지 않았는지 확인합니다. dhcpcd는 인터페이스가 재시작될 때마다 항상 accept_ra 옵션을 재정의하므로 accept_ra 구성이 손실됩니다. dhcpcd 구성 파일 (예: /etc/dhcpcd.conf)에 아래 줄을 추가하여 dhcpcd에서 IPv6를 명시적으로 사용 중지합니다.

noipv6
noipv6rs

변경사항을 적용하려면 재부팅해야 합니다.

macOS 호스트 준비

accept_ra* 옵션은 모두 기본적으로 사용 설정되어 있지만 시스템을 macOS Big Sur 이상으로 업그레이드해야 합니다.

호스트 이름 또는 IPv6 주소 핑

이제 ping -6 명령어 (macOS의 경우 ping6)를 사용하여 호스트 이름 ot-host.local을 핑할 수 있습니다.

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

이 명령어는 Linux 호스트에서 "Name or service not known" 오류와 함께 실패할 수 있습니다. ping 명령어가 mDNS 쿼리로 ot-host.local. 이름을 확인하지 않기 때문입니다. /etc/nsswitch.conf을 열고 hosts로 시작하는 줄에 mdns6_minimal를 추가합니다.

hosts:          files mdns4_minimal mdns6_minimal dns

물론 언제든지 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
...

7. 기기 종료 서비스 게시 취소

SRP 클라이언트 노드에서 등록된 주소 및 서비스를 삭제하려면 다음 단계를 따르세요.

> srp client host remove
Done

이제 _ipps._tcp 서비스를 검색할 수 없습니다.

8. 축하합니다

축하합니다. OTBR을 스레드 보더 라우터로 설정하여 스레드 엔드 기기에 양방향 IP 연결 및 서비스 검색을 제공했습니다.

다음 단계

다음 Codelab을 확인하세요.

참조 문서