Google は、黒人コミュニティのための人種的公平の促進に取り組んでいます。詳細をご覧ください。

スレッド境界ルーター - 双方向 IPv6 接続と DNS ベースのサービス ディスカバリ

1. はじめに

10000555535.png

Thread Border Router とは

スレッドは IP ベースの低電力ワイヤレス メッシュ ネットワーク プロトコルであり、デバイス間やデバイス間の通信を安全に行うことができます。スレッド ネットワークは、トポロジの変更に適応して、単一障害点を回避できます。

スレッド境界ルーターは、Wi-Fi やイーサネットなど、他の IP ベースのネットワークに Thread ネットワークを接続します。スレッド ネットワークに他のネットワークに接続するには、境界ルーターが必要です。スレッドボーダー ルーターは、少なくとも次の機能をサポートします。

  • Thread と Wi-Fi/イーサネット ネットワーク間の双方向 IP 接続。
  • mDNS(Wi-Fi またはイーサネット リンク)と SRP(スレッド ネットワーク)を介した双方向サービス ディスカバリ。
  • IP ベースのリンクを介してスレッド パーティションをマージするスレッド オーバー インフラストラクチャ。
  • スレッド デバイスを認証してスレッド ネットワークに参加させる外部スレッド コミッショニング(スマートフォンなど)。

Google がリリースした OpenThread ボーダー ルーター(OTBR)は、スレッドボーダー ルーターのオープンソース実装です。

作成するアプリの概要

この Codelab では、Thread Border Router をセットアップし、Border Router を介してスマートフォンを Thread End デバイスに接続します。

学習内容

  • OTBR の設定方法
  • OTBR を使用してスレッド ネットワークを形成する方法
  • SRP 機能を備えた OpenThread CLI デバイスをビルドする方法
  • SRP にサービスを登録する方法
  • スレッドエンド デバイスを見つけてリーチする方法。

必要なもの

  • Raspberry Pi 3/4 デバイスと 8 GB 以上の SD カード。
  • Nordic Semiconductor nRF52840 開発ボード x 2
  • ルーターで IPv6 Router アドバタイズメント ガードが有効になっていない 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 には、スレッドストラップと Thread Border Router を設定する 2 つのスクリプトがあります。

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

OTBR は、INFRA_IF_NAME で指定したスレッド インターフェースとインフラストラクチャ ネットワーク インターフェース(Wi-Fi/イーサネットなど)の両方で動作します。Thread インターフェースは 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 による Thread ネットワークの構築 Codelab のステップ 5 に沿って、nRF52840 CLI エンドデバイスをビルドしてフラッシュします。

ただし、OT_COMMISSIONEROT_JOINER を有効にするのではなく、CLI ノードに OT_SRP_CLIENTOT_ECDSA の機能が必要です。

そのため、完全なビルド呼び出しは次のようになります。

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

OTBR ネットワークに参加する

otbr-agent サービスによって作成された Thread ネットワークに参加するには、OTBR デバイスからアクティブなオペレーショナル データセットを取得する必要があります。otbr-agent コマンドラインに戻り、アクティブなデータセットを取得します。

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

SRP クライアント ノード画面セッションに戻り、アクティブなデータセットを設定します。

> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff
Done

次に、Thread インターフェースを開始します。

> ifconfig up
Done
> thread start
Done

数秒待ってから、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

ネットワーク データが OTBR に出力されたデータと一致することを確認してください。これで、OTBR の OMR アドレスに対して ping を実行できるようになりました。

> 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. エンドデバイスで Service を公開する

mDNS は、リンクローカル上で DNS-SD サービスを公開するために広く利用されています。ただし、マルチキャスト メッセージでは帯域幅の使用量が多くなり、低消費電力のデバイスでは電池が早く消耗します。スレッドは、ユニキャストの SRP プロトコルを使用してサービスを Border Router に登録し、Border Router を使用して Wi-Fi またはイーサネット リンクでサービスをアドバタイズします。

srp client コマンドを使用して、サービスを登録できます。

SRP クライアント ノードの画面セッションに移動し、SRP クライアントを自動起動します。

> srp client autostart enable
Done

Wi-Fi またはイーサネット リンクでアドバタイズされるホスト名を設定します。

> srp client host name ot-host
Done

Wi-Fi/イーサネット リンク上のデバイスが Thread エンドデバイスに到達するには、エンドデバイスの 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

すべての設定作業が完了し、Wi-Fi/イーサネット リンクで _ipps._tcp サービスがアドバタイズされているはずです。さっそくデバイスを見つけてデバイスを手に入れましょう。

6. Service を探す

スマートフォンでサービスを検索する

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

7. エンドデバイスに ping を実行する

スマートフォンから ping する

Pixel スマートフォンを例にとると、サービス ブラウザ アプリのサービス インスタンスの詳細ページで、登録済みのサービス「ot-service」の OMR アドレスを確認できます。

bb992962e68d250b.png 888daa1df1e1a9bf.png

これで、別の Network Analyzer アプリで OMR アドレスを ping できました。

残念ながら、Android バージョンの Network Analyzer アプリは ping ユーティリティの mDNS クエリをサポートしていないため、ホスト名 ot-host.local に直接 ping することはできません(iOS バージョンのアプリでは ping を使用できます)。

Linux/macOS ホストから ping を実行する

Thread Border Router は、Wi-Fi/イーサネット リンクでプレフィックス(Prefix Information Option 経由)とルート(Route Information オプション経由)をアドバタイズするために、ICMPv6 ルーター アドバタイズメント(RA)を送信します。

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 メッセージを送信しており、2 件の非要請型 RA メッセージの間隔が数百秒もあるため、構成の変更は遅すぎる可能性があります。方法の 1 つは、Wi-Fi AP を切断して再接続し、ルーター リクエスト メッセージを送信して、OTBR が要請型 RA で応答できるようにすることです。もう 1 つのオプションは、Border Router で Border Routing 関数を再起動することです。

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

Wi-Fi の再接続やイーサネット インターフェースの再起動を試みる場合は、Wi-Fi やイーサネットの IPv6 ネットワークの管理に dhcpcd を使用していないことを確認します。インターフェースが再起動されるたびに dhcpcd が常に accept_ra オプションをオーバーライドするため、accept_ra の設定は失われます。dhcpcd で IPv6 を明示的に無効にするには、以下の行を dhcpcd 構成ファイル(例: /etc/dhcpcd.conf)に追加します。

noipv6
noipv6rs

変更を反映させるには再起動が必要です。

macOS ホストを準備する

どちらの accept_ra* オプションもデフォルトで有効になっていますが、少なくとも macOS Big Sur にアップグレードする必要があります。

ホスト名または IPv6 アドレスに対して ping を実行する

コマンド ping -6 を使用してホスト名 ot-host.local に ping を実行できるようになりました(macOS の場合は ping6)。

$ 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 を実行することもできます。

$ 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 がスレッド境界ルーターとして正常に設定され、Thread エンドデバイスに双方向の IP 接続とサービス ディスカバリが可能になりました。

次のステップ

以下の Codelab をご覧ください。

リファレンス ドキュメント