SORACOM UG Online #6 で発表した、ESP32でSORACOM Arcつないでみたの発表資料です。
ESP32でSORACOM ArcつないでみたSORACOM UG ONLINE #6 2021/07/27Kenta Ida (@ciniml)
View Slide
自己紹介•井田 健太 (@ciniml)•仕事:FPGAの論理設計•使用言語:C++, SystemVerilog, Rust, C#•組込みRust本の1割くらい書きました(サンプルアプリ作ったり、デバッガ試したり)→2021/7/27ESP32 SORACOM Arcで つないでみた 2
SORACOM Discovery 2021 Online 当日2021/7/27ESP32 SORACOM Arcで つないでみた•SORACOM Arcが発表された• WireGuardによるVPNにてインターネットからSORACOMサービスに接続•ESP32等で接続できるとおもしろいのでは?• ESP32: EspressifのWiFi+BT付きマイコン•ESP32向けWireGuard実装を探したが見つからず放置3
およそ2週間後くらい facebookにて2021/7/27ESP32 SORACOM Arcで つないでみた 4
およそ2週間後くらい facebookにて2021/7/27ESP32 SORACOM Arcで つないでみたこれは煽りに違いないやれってことですね!5
もうちょっとくわしく2021/7/27ESP32 SORACOM Arcで つないでみた•lwIP(組込み向けIPスタック)向けWireGuard実装あり!• https://github.com/smartalock/wireguard-lwip• 3条項BSDライセンス•ESP-IDF (ESP32公式フレームワーク) もlwIP使用• Arduino core for the ESP32も同じ•動かせるのでは?6
調整してみた結果をTweet2021/7/27ESP32 SORACOM Arcで つないでみた 7
やっぱばれた2021/7/27ESP32 SORACOM Arcで つないでみた 8
どういうこと?2021/7/27ESP32 SORACOM Arcで つないでみた•100.127.100.127(pong.soracom.io)からのping応答→SORACOMサービスにつながってるESP-IDFの標準ログフォーマット(つまりESP32で動いている)9
動かすためにやったこと(1)2021/7/27ESP32 SORACOM Arcで つないでみた•WireGuard for lwIPのIPv6有効版lwIP対応• 基本的に ipaddr_t を使うように修正• IPv4が必要な部分は適宜変換関数・マクロを呼ぶように修正10
ビルド通った!2021/7/27ESP32 SORACOM Arcで つないでみた•ビルド通ったので動かしてみた•試しに自宅VPN用のWireGuardに接続•つながった!• が、Endpointにしかpingが届かない• VPN接続先ネットワーク内のホストに到達できず…•なんでだ?ESP32スマートフォンWireGuardEndpoint(RPi4)インターネット他のホスト11
動かすためにやったこと(2)2021/7/27ESP32 SORACOM Arcで つないでみた•アプリ送信データがWiFiに直接流れる…•lwIPはルーティング機構が存在しない• netif指定でsend: netif経由で送信• それ以外: デフォルトnetif経由で送信•WireGuard netifをデフォルトに変更アプリWireGuardnetifWiFinetifsendudp_sendto修正前: デフォルト=WiFiアプリWireGuardnetifWiFinetifudp_sendto_netif(WiFi)send修正前: デフォルト=WireGuard12
動かすためにやったこと(3)2021/7/27ESP32 SORACOM Arcで つないでみた•WireGuardのハンドシェークは現在時刻を使用している•要求受信側はハンドシェーク時の時刻が前回より進んでいない場合ハンドシェーク拒否• RTCでの時刻保持やNTPでの時刻同期が必要•今回はNTPで時刻同期するようにして対応• ESP32 ArduinoではconfigTime関数呼び出すだけ13
もうちょっと応用例2021/7/27ESP32 SORACOM Arcで つないでみた•pingは面白くないのでHarvest Dataにデータ投げる例ESP32uptime (起動後経過時間) [ms]count (送信回数)64[bit] = 8[byte]2つ=16[byte]バイナリ{"uptime":1016378,"count":201,"imsi":"...","name":"","location":null,"timestamp":1627205656599}OrbitでJSONに変換 Harvest Dataに投入14
もうちょっと応用例2021/7/27ESP32 SORACOM Arcで つないでみた•Harvestで結果確認15
Arduino Library化2021/7/27ESP32 SORACOM Arcで つないでみた•WireGuard IF部分をESP32用にArduino Library化•Arcでuptime送信サンプル付き16
Arduino Library化2021/7/27ESP32 SORACOM Arcで つないでみた• 使い方は簡単• WireGuard型変数宣言• NTP時刻調整• WireGuard::begin呼び出し• ArcのJSONに含まれている接続情報を引数で渡す• あとはWiFi同様に通信処理を記述// WireGuard configuration --- UPDATE this configuration from JSONchar private_key[] = "(Private Key) "; // [Interface] PrivateKeyIPAddress local_ip(1,2,3,4); // [Interface] Addresschar public_key[] = "(Public Key)"; // [Peer] PublicKeychar endpoint_address[] = "link.arc.soracom.io"; // [Peer] Endpointint endpoint_port = 11010; // [Peer] Endpoint...static WireGuard wg;static HTTPClient httpClient;void setup(){Serial.begin(115200);Serial.println("Connecting to the AP...");WiFi.begin(ssid, password);while( !WiFi.isConnected() ) {delay(1000);}Serial.println("Adjusting system time...");configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp","time.google.com");Serial.println("Connected. Initializing WireGuard...");wg.begin(local_ip,private_key,endpoint_address,public_key,endpoint_port);}17
現状の課題(1/2)2021/7/27ESP32 SORACOM Arcで つないでみた•乱数生成処理の妥当性• WireGuard for lwIPではサンプルでrand()を使って実装• 必ず置き換えるようにとコード中にコメントあり• randは容易に推測可能なため•とりあえずESP32のハードウェア乱数+ mbedTLSのCTR-DRBG実装で乱数生成を実装•専門ではないのでこれでいいのかよくわからん…• だれか詳しい人おしえてください。18
現状の課題(2/2)2021/7/27ESP32 SORACOM Arcで つないでみた•WireGuard接続情報はスケッチにハードコード• 真面目に使うなら暗号化NVSに保存などが必要19
未確認事項2021/7/27ESP32 SORACOM Arcで つないでみた•通信パフォーマンスがどれくらいか不明• 余裕があったらiperfサンプルあたり動かしたい• ESP32向け最適化の余地があるかも20
ソースコードなど2021/7/27ESP32 SORACOM Arcで つないでみた•https://github.com/ciniml/WireGuard-ESP32-Arduino•https://github.com/ciniml/ESP32_WireGuard21
おしまい2021/7/27ESP32 SORACOM Arcで つないでみた 22