IoTLT Advent Calendar、初めてお声がけいただき、光栄です!
みなさんよろしくお願いいたします。
今回の記事の背景から
現在取り組んでいるプロジェクトで、SIM Wi-Fiルータを使った遠隔地のIoT機器を管理する必要が出てきました。CloudflareのIPトンネルを使うと最も簡単にそしてポート解放などしなくてもリーモートからターゲットにアクセスできるようになると聞いたので、下図のような構成を試してみましたので、共有いたします。
IoT機器側のネットワーク
図の左半分を指しています。Raspberry Pi 4Bを無線LANで接続しています。これ以外にも、2.4GHz帯の無線LANで温度センサーユニットなどが繋がっていますが、これらはアウトバウンドでただデータを吐き出すだけなので、このテストには含めていません。
ネットワークとしては、TP-LinkのMR600にMeeqのSIM(Sofrbank回線)を指してインターネットに接続しています。Raspberry Pi 4には、Raspberry Pi AI Cameraが繋がっていて、実は人流の測定をしています。今回、POCということで、さまざまな調整をこの期間にするため、外部からこのRaspberry Piへ安全に入る必要があり、今回の事前テストとなりました。
PC側のネットワーク
図の右側ですが、これはどこにでもある、自宅の光回線から、無線LANのアクセスポイントを介してMacがインターネットにアクセスできる環境となっています。
PCからRaspberry Piにアクセスする方法
ChatGPTに、"一般的にインターネットに繋がっている家庭のルーター兼アクセスポイントの下にある機器に外部からアクセスさせるためにはどのような設定などをするか教えてください。"と聞いたところ、ポートフォワーディングからDMZや、VPNなどの方法が例示されましたが、最近では、Cloudflare Tunnelが近年最も便利との回答がありました。今回はそもそもこのCloudflare Tunnelを試してみたいと思っていましたので、素直にCloudflare Tunnelを試してみることにします。
Cloudflare Tunnelの仕組みは、簡単にいうと、ラズベリーパイ側でCloudflarにアクセスするエージェントCloudflaredが常に動いていて、外部からCloudflarにアクセスしてきたセッションを接続するという仕組みです。
起動のところから順に流れを見ていきたいと思います。
起動フェーズ
(1) Raspberry Pi 起動
↓
(2) systemd により cloudflared を自動起動
- cloudflared は config.yml を読み込んで動作開始
↓
(3) cloudflared → Cloudflare Edge へアウトバウンド接続
- Pi → Cloudflare(HTTPS / QUIC)で接続
- cert.pem & tunnel-id.json を用いて認証
- Cloudflare 側にトンネルを登録
↓
(4) トンネルが「待機状態(ready)」になる
- cloudflared は Cloudflare と接続維持(心拍)を開始して待機
外部からの接続フェーズ
外部ユーザー(例:Mac)が SSH / VNC を開始した時:
(5) ユーザーがサービスへアクセス
- SSH: ssh pi@pi-ssh.example.com
- VNC: vncviewer pi-vnc.example.com
↓
(6) Cloudflare Edge が接続要求を受信
- DNS 解決(pi-ssh.example.com → Cloudflare)
- Zero Trust Access 認証(有効時)
- 対応するトンネルへルーティング
↓
(7) Cloudflare Edge → Pi へ逆方向のトンネルセッション開始
- 外部 → Cloudflare → Raspberry Pi の cloudflared
↓
(8) cloudflared がローカルサービスへ接続
- SSH: localhost:22
- VNC: localhost:5901
↓
(9) 外部ユーザー ↔ Pi が双方向接続される
- 安全なエンドツーエンドセッションが成立する
接続維持フェーズ
(10) cloudflared が常時実行する役割
- Cloudflare との心拍チェック(keepalive)
- 切断時の自動再接続
- 複数セッションの多重化
- QUIC / HTTP2 など最適プロトコル選択
(11) 接続終了時
- Cloudflare → Pi → クライアントの各段階でセッションをクリーンに終了
cloudflared(IPトンネル)の要点まとめ
- cloudflared は サーバではなくクライアント
→ Pi → Cloudflare への外向き通信のみで動作 - 外部ユーザーは Pi に直接接続しない
→ 実際に接続しているのは Cloudflare Edge - 逆トンネル(Reverse Tunnel)方式
→ Pi 側へのポート開放不要 / SIM・CGNAT でも動作 - Access 認証を入れると安全性が高まる
Cloudflare Tunnelの落とし穴
落とし穴というか、知らなかったことを共有します。
それは、Cloudflareで管理しているドメインがないと先に進めないということです。
Cloudflareはかなりの機能を無償の範囲で使うことができますが、このIPトンネル機能もかなりの量を無償で使うことができますが、ドメインを持っていないと先進めませんので、ドメインを取得する必要があります。
今回のために、一つ.comドメインを取得しました。
MR600のセットアップ
TP-LinkのMR600は、SIMが入る無線LANアクセスポイントで、クライアント64台の無線接続と4つの有線LANのポートを持っています。上位に光などの回線もある場合には、そちらにも繋いでおいて、通常のWi-Fiルーターとして使うこともでき、4GのSIM側は、バックアップとして機能させることもできるようになっています。
設定も至って簡単で、SIMのプロファイルを選ぶか、新規作成して、APNなどの情報をセットするだけで動き始めました。
Raspberry PiにCloudflare Tunnelをセットアップする
前提条件(必要なもの)
• Cloudflare アカウント(無料)
• Cloudflare で管理されているドメイン<=これが重要
例: example.com
• Raspberry Pi(Bookworm)
例: Raspberry Pi 4 / 5 / Zero2W など
• Pi がインターネットに接続できる(SIMルーター・WiFiなど)
• Mac(接続側)に TigerVNC Viewer をインストール予定
全体構成
今回は、PC(Mac)からSSHとVNCでRaspberry Piに接続します。
SSH → pi-ssh.example.com
VNC → pi-vnc.example.com
1つのトンネル内で両方扱います。
STEP 1:Raspberry Pi 側のセットアップ
1-1 必要パッケージをインストール
(A) TigerVNC Server
Bookworm(Wayland)では RealVNC が使えないため TigerVNC を使用します。
sudo apt update
sudo apt install tigervnc-standalone-server tigervnc-common
(B) cloudflared のインストール
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
念の為、インストールされたか確認
cloudflared --version
1-2. cloudflared を Cloudflare アカウントに紐付ける(rootで)
Cloudflare Tunnel を systemd で動かす場合、
cloudflared は root ユーザーで動くため、cert.pem と tunnel JSON も root のホームに必要。
Raspberry Piのターミナルから
sudo -s
cloudflared tunnel login
これを実行すると、URL が表示されるので PCのブラウザで開いて、
Cloudflare にログイン → ドメイン選択 → 許可。
ここで管理しているドメインがないと先に進めないので、ない場合は、何かドメインを購入する必要があります。年額7ドル台のドメインもあり、私は十数ドルの.comドメインを作り先に進みました。
ドメインの許可に成功すると Pi 側に:
Your certificate has been saved to:
/root/.cloudflared/cert.pem
ができます。
1-3. トンネル作成(rootのまま)
下記のコマンドを実行すると、トンネルIDと資格情報ファイル(<ID>.json)が生成されますので、トンネルIDを控えておきます。
cloudflared tunnel create pi-remote
1-4. VNC の起動設定
今回のRaspberry Pi 4Bには、Debian 13 (trixie) ベースのRaspberry Pi OS(64bit, aarch64)を入れています。VNCには、RealVNCを使うため、GUIは、Wayklandではなく、X11に変えています。もし、トラブルに見舞われたときには、この項目を思い出して確認をお願いします。
VNCを使う場合は、VNCサーバーを起動しておきます。
1-5. Cloudflare トンネル設定(config.yml)を作成(rootのまま)
下記のコマンドでエディターを使って、config.ymlを作成します。
mkdir -p /etc/cloudflared
nano /etc/cloudflared/config.yml
トンネルIDには、1-3で控えておいたトンネルIDを使います。
下記の内容を.ymlファイルに書き込みます。
tunnel: pi-remote
credentials-file: /root/.cloudflared/<トンネルID>.json
ingress:
- hostname: pi-ssh.example.com
service: ssh://localhost:22
- hostname: pi-vnc.example.com
service: tcp://localhost:5900 # TigerVNC :1 → 5901
- service: http_status:404
host名は、紐づけたドメイン名からなるhost名に置き換えます。
1-6. cloudflared の systemd サービス化(rootのままもしくはsudo)
cloudflaredをsystemdのサービスとして登録して自動起動するように設定します。
サービスの作成
cloudflared service install
デーモンの有効化と起動
systemctl enable --now cloudflared
そして、次のコマンドで状態を確認しておきます。
systemctl status cloudflared
1-7 hostをDNSに登録する
ローカル構成(Local config)方式でトンネルを作りましたので、外部からこのトンネルtにアクセスできるようにするため、hostを下記の手順でDNS登録します。
sudo -s
cloudflared tunnel route dns pi-remote pi-ssh.example.com
cloudflared tunnel route dns pi-remote pi-vnc.example.com
※example.comは、自分のドメイン名に置き換えて実行します。
PC側から下記のコマンドを使って、名前が解決されているかを確認します。
nslookup pi-ssh.example.com
1-7 PC(Mac)から接続する準備
cloudflared を macOS にインストール
brew install cloudflared
Cloudflare Access へのログイン(初回だけ)
cloudflared login
ブラウザが開いてドメインを選択
認証成功後、Mac にクレデンシャルが保存されます
1-8 SSHの実行
Cloudflare Tunnel を介してのSSH では、直接 ssh user@pi-ssh.example.com では繋がりません。
代わりに、Mac 側で tunnel proxy を開きます。
cloudflared access tcp --hostname pi-ssh.ai-jinryu.com --url localhost:2222
このコマンドで、Mac 上で TCP プロキシが起動されます。
成功すると、下記のように表示されます。
INF Listening on 127.0.0.1:2222
INF Proxying TCP connections to pi-ssh.example.com
その後、ポートに2222を指定して、sshを起動すると接続できるようになります。
ssh admin@localhost -p 2222
1-9 コマンドを短くする(オプション)
毎回接続の度に長いコマンドを打つのは面倒なので、~/.ssh/config に以下を追加して、
ssh pi-remote
だけで繋げられるようにしておきます。
Host pi-remote
HostName localhost
Port 2222
User admin
ProxyCommand cloudflared access tcp --hostname pi-ssh.example.com --url localhost:2222
1-10 VNC を Cloudflare Tunnel 経由で接続する
Mac側は、TigerTNCを使用していますので、それを前提にしています。
SSHと同様にVNC用のTCP プロキシの設定をします。
cloudflared access tcp --hostname pi-vnc.example.com --url localhost:5901
Macで、TigerVNCを起動し、接続先に下記を指定すると、接続ができます。
localhost:5901
終わりに
そもそもMeeqのSIMは、大容量通信をするというより、IoTセンサーからの小さなデータを集約しながら送るのが主ですが、リモートにあるRaspberry Piを監視したり、制御するためにはこの方法はとても有用なで、これからもいろいろ試していきたいと思います。

