1. はじめに
Thread ボーダー ルーターとは
Thread は IP ベースの低消費電力ワイヤレス メッシュ ネットワーク プロトコルであり、デバイス間およびデバイス間のセキュアな通信を可能にします。スレッド ネットワークは、トポロジの変更に適応して単一障害点を回避できます。
Thread ボーダー ルーターは、Thread ネットワークを Wi-Fi やイーサネットなどの他の IP ベースのネットワークに接続します。Thread ネットワークが他のネットワークに接続するには、ボーダー ルーターが必要です。Thread ボーダー ルーターは、少なくとも次の関数をサポートしています。
- Thread ネットワークと Wi-Fi/イーサネット ネットワーク間の双方向 IP 接続。
- mDNS(Wi-Fi/イーサネット リンク上)と SRP(Thread ネットワーク上)を介した双方向サービス ディスカバリ。
- IP ベースのリンクで Thread パーティションを結合する Thread-over インフラストラクチャ。
- Thread デバイスを認証して Thread ネットワークに参加するための外部 Thread コミッショニング(スマートフォンなど)
Google がリリースした OpenThread ボーダー ルーター(OTBR)は、Thread ボーダー ルーターのオープンソース実装です。
作成するアプリの概要
この Codelab では、Thread ボーダー ルーターをセットアップし、ボーダー ルーターを介してスマートフォンを Thread エンドデバイスに接続します。
学習内容
- OTBR のセットアップ方法
- OTBR で Thread ネットワークを形成する方法
- SRP 機能を使用して OpenThread CLI デバイスを作成する方法
- SRP にサービスを登録する方法
- Thread エンドデバイスを検出して到達する方法。
必要なもの
- Raspberry Pi 3/4 デバイスと、8 GB 以上の容量を持つ SD カード。
- Nordic Semiconductor の nRF52840 開発ボード 2 枚。
- ルーターで IPv6 Router Advertisement Guard が有効になっていない 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 ボーダー ルーターをブートストラップしてセットアップするスクリプトが 2 つあります。
$ cd ot-br-posix $ ./script/bootstrap $ INFRA_IF_NAME=wlan0 ./script/setup
OTBR は、INFRA_IF_NAME
で指定された Thread インターフェースとインフラストラクチャ ネットワーク インターフェース(Wi-Fi/イーサネットなど)の両方で機能します。Thread インターフェースは OTBR 自体によって作成され、デフォルトでは wpan0
という名前が付けられ、インフラストラクチャ インターフェースのデフォルト値は wlan0
になります(INFRA_IF_NAME
が明示的に指定されていない場合)。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 は、Radio Co-Processor(RCP)モードで 15.4 無線チップをサポートしています。このモードでは、OpenThread スタックがホスト側で実行され、IEEE802.15.4 トランシーバ上でフレームを送受信します。
Codelab「nRF52840 ボードと OpenThread を使用して Thread ネットワークを構築する」のステップ 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. Thread ネットワークを形成する
otbr-agent
サービスの制御に使用できる ot-ctl
コマンドがあります。ot-ctl
は、すべての OpenThread CLI コマンドを受け入れます。詳しくは、OpenThread CLI ガイドをご覧ください。
OTBR で Thread ネットワークを形成する:
$ 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 のビルドとフラッシュ
Codelab「nRF52840 ボードと OpenThread を使用して Thread ネットワークを構築する」のステップ 5 に沿って、nRF52840 CLI エンドデバイスをビルドしてフラッシュします。
ただし、CLI ノードでは、OT_COMMISSIONER
と OT_JOINER
を有効にする代わりに、OT_SRP_CLIENT
機能と OT_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. エンドデバイスでサービスを公開する
mDNS は、リンクローカルの DNS-SD サービスを公開するために広く使用されています。しかし、マルチキャスト メッセージは帯域幅を大量に消費するため、低電力デバイスではすぐにバッテリーが消耗します。Thread は、ユニキャスト SRP プロトコルを使用してサービスをボーダー ルーターに登録し、ボーダー ルーターを利用して 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
すべてのセットアップ作業が完了し、_ipps._tcp
サービスが Wi-Fi/イーサネット リンクでアドバタイズされているはずです。最後のデバイスを見つけて手に入れましょう。
6. Service の詳細
スマートフォンでサービスを見つける
Android スマートフォンでは、サービス ブラウザ アプリを使用して mDNS サービスを検出します。iOS モバイル デバイス用の同等のアプリもあります。アプリを開くと、_ipps._tcp
サービスが表示されます。
Linux ホストでサービスを検出する
別の Linux ホストからサービスを検出するには、avahi-browse
コマンドを使用します。
avahi-daemon
と avahi-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 を送信する
Google Pixel を例にとると、以前に登録されたサービス「ot-service」の OMR の住所がわかります。サービス ブラウザ アプリのサービス インスタンスの詳細ページ。
これで、別のネットワーク アナライザ アプリを使用して OMR アドレスを ping できます。
残念ながら、Android 版のネットワーク アナライザ アプリは ping ユーティリティの mDNS クエリに対応していないため、ホスト名 ot-host.local
に直接 ping することはできません(iOS 版のアプリではホスト名に対して ping を実行できます)。
Linux/macOS ホストから ping する
Thread ボーダー ルーターは、ICMPv6 のルーター アドバタイズメント(RA)を送信して、Wi-Fi/イーサネット リンク上のプレフィックス(プレフィックス情報オプション経由)とルート(ルート情報オプション経由)をアドバタイズします。
Linux ホストを準備する
RA と RIO がホストで有効になっていることが重要です。
- IP 転送が有効になっていない場合、
net.ipv6.conf.wlan0.accept_ra
は1
以上、それ以外の場合は2
にする必要があります。 net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen
は64
以上にする必要があります。
ほとんどのディストリビューションで、accept_ra
はデフォルトで 1
に設定されています。ただし、このオプションをオーバーライドする他のネットワーク デーモンが存在する場合もあります(たとえば、Raspberry Pi の dhcpcd
は accept_ra
を 0
にオーバーライドします)。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 で応答できるようにすることです。また、ボーダー ルーターのボーダー ルーティング機能を再起動することもできます。
$ 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 を実行する
これで、コマンド ping -6
(macOS の場合は ping6
)を使用してホスト名 ot-host.local
に ping を実行できます。
$ 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 ボーダー ルーターとして正常にセットアップし、Thread エンドデバイスに双方向の IP 接続とサービス ディスカバリを提供できるようになりました。
次のステップ
以下の Codelab をご覧ください。