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

1. 소개

699d673d05a55535.png

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

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

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

  • 스레드와 Wi-Fi/이더넷 네트워크 간의 양방향 IP 연결입니다.
  • mDNS (Wi-Fi/이더넷 링크) 및 SRP (스레드 네트워크)를 통한 양방향 서비스 검색입니다.
  • IP 기반 링크를 통해 스레드 파티션을 병합하는 인프라에 스레드를 사용합니다.
  • 스레드 기기를 인증하고 스레드 네트워크에 조인하기 위한 외부 스레드 수수료 (예: 휴대전화)

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

빌드할 항목

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

학습할 내용

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

필요한 항목

  • Raspberry Pi 3/4 기기 및 8GB 이상의 기능을 갖춘 SD 카드
  • Nordic Semiconductor nRF52840 개발자 보드 2개
  • 라우터에 IPv6 라우터 공지 가드가 사용 설정되지 않은 Wi-Fi AP
  • iOS 14 이상을 실행하는 iOS 휴대전화 또는 Android 8.1 이상을 실행하는 Android 휴대전화

2. OTBR 설정

Raspberry Pi 설정

raspberrypi.org의 안내에 따라 rpi-imager 도구로 새 Raspberry Pi 기기를 설정하면 됩니다. 도구에서 최신 Raspberry Pi OS를 사용하는 대신 2021-05-07-raspios-buster-armhf-lite를 직접 다운로드하면 됩니다. 이 Codelab에서 휴대전화 단계를 완료하려면 Raspberry Pi를 Wi-Fi AP에 연결해야 합니다. 무선 연결을 설정하려면 이 가이드를 따르세요. SSH를 사용하여 Raspberry Pi에 로그인하면 편리합니다. 여기에서 지침을 확인할 수 있습니다.

OTBR 코드 받기

Raspberry Pi에 로그인하고 GitHub에서 ot-br-posix를 클론합니다.

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

OTBR 빌드 및 설치

OTBR에는 스레드 보더 라우터를 부트스트랩하고 설정하는 두 가지 스크립트가 있습니다.

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

OTBR은 INFRA_IF_NAME로 지정된 스레드 인터페이스와 인프라 네트워크 인터페이스 (예: Wi-Fi/이더넷)에서 모두 작동합니다. 스레드 인터페이스는 OTBR 자체에서 생성되고 기본적으로 wpan0로 이름이 지정되며, INFRA_IF_NAME가 명시적으로 지정되지 않으면 인프라 인터페이스의 기본값은 wlan0입니다. Raspberry Pi가 이더넷 케이블로 연결되어 있는 경우 이더넷 인터페이스 이름 (예: eth0)을 지정합니다.

$ INFRA_IF_NAME=eth0 ./script/setup

OTBR이 성공적으로 설치되었는지 확인합니다.

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

otbr-agent 서비스를 실행하려면 RCP 칩이 필요하므로 활성화되지 않은 것으로 예상됩니다.

Raspberry Pi를 재부팅하여 변경사항을 적용합니다.

RCP 펌웨어 빌드 및 플래시

OTBR은 무선 보조 프로세서 (RCP) 모드에서 15.4 무선 칩을 지원합니다. 이 모드에서 OpenThread 스택은 호스트 측에서 실행되며 IEEE802.15.4 트랜시버를 통해 프레임을 전송/수신합니다.

nRF52840 보드 및 OpenThread로 스레드 네트워크 빌드 Codelab의 4단계에 따라 nRF52840 RCP 기기를 빌드하고 플래시합니다.

$ script/build nrf52840 USB_trans

OTBR 시작 및 상태 확인

nRF52840 보드를 Raspberry Pi에 연결하고 otbr-agent 서비스를 시작합니다.

$ sudo service otbr-agent restart

otbr-agent 서비스가 활성 상태인지 확인합니다.

$ 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. 스레드 네트워크 형성

otbr-agent 서비스를 제어하는 데 사용할 수 있는 ot-ctl 명령어가 있습니다. ot-ctl는 모든 OpenThread CLI 명령어를 허용합니다. 자세한 내용은 OpenThread CLI 가이드를 참고하세요.

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

몇 초 동안 OTBR이 스레드 leader 역할을 하고 스레드 네트워크 데이터에 off-mesh-routable (OMR) 접두어가 있음을 확인할 수 있습니다.

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

OT CLI 빌드 및 플래시

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

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

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

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

OTBR 네트워크에 가입

otbr-agent 서비스에서 만든 스레드 네트워크에 참여하려면 OTBR 기기에서 활성 작업 데이터 세트를 가져와야 합니다. otbr-agent 명령줄로 돌아가서 활성 데이터 세트를 가져옵니다.

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

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

> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

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

> 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

5. 최종 기기에 서비스 게시

mDNS는 링크-로컬에서 DNS-SD 서비스를 게시하는 데 널리 사용됩니다. 하지만 멀티캐스트 메시지는 대역폭을 너무 많이 소모하므로 저전력 기기의 배터리가 빠르게 소모됩니다. 스레드는 유니캐스트 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/이더넷 링크에 공지되어야 합니다. 이제 최종 기기를 찾아 도달할 시간입니다.

6. 서비스 살펴보기

휴대전화로 서비스 찾기

54a136a8940897cc.png

Google에서는 서비스 브라우저 앱을 사용하여 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     ""
...

7. 최종 기기 핑하기

휴대전화에서 핑하기

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

bb992962e68d250b.png 888daa1df1e1a9bf.png

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

안타깝게도 네트워크 분석기 앱의 Android 버전은 핑 유틸리티에 관한 mDNS 쿼리를 지원하지 않으므로 호스트 이름 ot-host.local에 직접 핑할 수 없습니다 (iOS 버전의 앱에서는 호스트 이름을 핑할 수 있음).

Linux/macOS 호스트에서 핑

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

Linux 호스트 준비

RA 및 RIO가 호스트에서 사용 설정되어 있는지 확인해야 합니다.

  1. IP 전달이 사용 설정되지 않은 경우 net.ipv6.conf.wlan0.accept_ra1, 그 외에는 2이어야 합니다.
  2. net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen은(는) 64 이상이어야 합니다.

대부분의 배포판에서 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 메시지 간의 간격이 수백 초일 수 있으므로 이러한 구성을 변경하기에는 너무 늦을 수 있습니다. 한 가지 방법은 OTBR이 요구된 RA로 응답하도록 Wi-Fi AP의 연결을 끊었다가 다시 연결하여 라우터 요청 메시지를 전송하는 것입니다. 또 다른 옵션은 경계 라우터에서 경계 라우팅 함수를 다시 시작하는 것입니다.

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

8. 최종 기기에서 서비스 게시 취소

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

> srp client host remove
Done

지금은 _ipps._tcp 서비스를 검색할 수 없습니다.

9. 축하합니다

수고하셨습니다. 스레드 보더 라우터로 OTBR을 설정하여 스레드 최종 기기에 양방향 IP 연결과 서비스 검색을 제공합니다.

다음 단계

다음 Codelab을 확인하세요.

참조 문서