2025年10月22日水曜日

ESP32-CAMをWireGuard経由で使ってみた。

 ESP32でWireGuardが使えるライブラリがあるということで、ESP32-CAMもWireGuardを使ってNAT越えできるのではないかということで試してみた。

よくあるスマホのアプリ対応のWiFiカメラとかだとポート解放とか不要でユーザ登録すればカメラの映像を見れたりするけど、ESP32-CAMもモバイル回線とかのポート開放できないような場面で使えたら便利かも?ということで試してみた。前にUPnPでポートを開けてみたこともあったけど、そもそもグローバルIPがない環境だとこの方法も使えないし。

ESP32-CAM

久しぶりにESP32-CAMのスケッチをビルドするのでまずは環境を最新にしてビルドしてみた。ESP32 Arduino Coreは3.3.2でArduino IDEは2.3.5。前にESP32-CAMのESP32 Camera Driverを最新にしたときの手順で、ESP32 Camera Driver v2.1.3に更新してみた。
まずここで躓いたのがSCCB関連で、sccb-ng.cを削除したらうまくビルドできた。

最新の環境で前回のスケッチがビルドできるようになったので早速WireGuardを組み込んでみる。

とりあえずESP32のWireGuardライブラリをダウンロードしてきてサンプルをビルドしてみたんだけどまさかのArduino core for the ESP32 3.xに非対応という…

Pull requestに上がっていた3.x対応のESP32-WireGuardライブラリがあったのでこれをZipでダウンロードしてきて手動で追加した。テストでサンプルがビルドできたのでこのライブラリをESP32-CAMのスケッチに追加していく。

スケッチを全部貼ると長くなってしまうので前回のスケッチに追加した部分だけを紹介。

#define Tunnel

#ifdef Tunnel
#include <WireGuard-ESP32.h>
char private_key[] = "                                            ";  // [Interface] PrivateKey
IPAddress local_ip(10, 4, 0, 2);                                      // [Interface] Address
char public_key[] = "                                            ";   // [Peer] PublicKey
char endpoint_address[] = "     .f5.si";                      // [Peer] Endpoint
int endpoint_port = 51810;                                            // [Peer] Endpoint
static WireGuard wg;
#endif

まずは各種ライブラリをincludeしてるあたりにこんな感じで設定を追加。サーバ側はこの前設定したDD-WRTなんだけど、ESP32-CAM用にPeerを追加した。IPは同じセグメントで別なIPを割り振る感じ。Peerの設定はクライアントに割り振るIP以外ほぼコピーかな。ESP32ではQRコードではなくてQRコードの下にあるExport Peer Configボタンを押してコンフィグファイルをダウンロードする。そんでもってそのファイルの中のPrivateKeyってところとPublicKeyってところをコピーして上に貼り付け。DD-WRTの設定画面からじゃなくて、コンフィグファイルをダウンロードしてその中身ってのがポイント。

#ifdef Tunnel
  Serial.println("Adjusting system time...");
  configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com");

  struct tm timeInfo;
  if (getLocalTime(&timeInfo)) {
    Serial.print("Local Time  : ");
    Serial.printf("%04d-%02d-%02d ", timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday);
    Serial.printf("%02d:%02d:%02d\n", timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
  }
#endif

WireGuardはNTPから時間を取得する必要があるのでNTPで時計を合わせる部分をsetup()の中のネットに繋がったあたりに追加。mDNSの上ぐらいに追加しておいた。

#ifdef Tunnel
  Serial.println("Initializing WG interface...");
  if (!wg.begin(
        local_ip,
        private_key,
        endpoint_address,
        public_key,
        endpoint_port)) {
    Serial.println("Failed to initialize WG interface.");
  }
#endif

そしてWireGuardに接続する部分をsetup()の中のserver.onの直前ぐらいに追加。これでWireGuardに接続されるとESP32の通信自体が全部WireGuardに流れる形。起動後10.4.0.2に接続すると普通にカメラの映像を確認できた。スタックも前回増やした状態でいい感じに安定して動いている。

ライブラリを使うことによって意外と簡単にESP32からWireGuard VPNに接続できちゃった。これならグローバルIPがなかったり、ポートが開けられない環境に設置して、サーバ側からポート変換で公開できちゃうので便利。お互いにNAT越えできない場合はTailscaleとか使えると便利そうだなぁ。

mDNSライブラリもそのまま動いてるみたいだけどWireGuardで接続している同セグメントからじゃないとmDNSでは解釈できないみたい。他のWireGuardのPeerからはうまく発見できた。IPだとWireGuard経由でも、ESP32-CAMがつながってるWiFiネットワークからでもどっちからもアクセスできた。

フレームレートの比較はどうやってやればよいのかな…

0 件のコメント:

コメントを投稿