はじめに
Cloudflare Tunnel は、手軽に内部のサーバーを公開できるサービスです。固定グローバルIPや、インバウンドのポート開放も不要で便利です。ngrok あたりが類似サービスに当たるかなと思います。
これまで、複数のサーバーを公開する際は、サーバーごとに cloudflared (トンネルを張るデーモン) をインストール、個別のトンネルを張っていました。しかし、だんだん面倒になってきました。
Ingress rules という機能を利用すると、一つのトンネルで、ホスト名と転送先サービスのセットを複数定義できることを知りました。便利そうなので試してみました。
公式ドキュメントがしっかりしてるのでありがたいです。一次情報は公式ドキュメントを参照してください。
やりたいこと
こんなイメージです。1つの cloudflared でトラフィックを受けてリクエストホスト名に応じて各サービスに転送します。
トラフィックを受けて、といっても直接このサーバーがポートを開放して待ち受けるわけではありません。実際は cloudflared が Cloudflare にトンネルを張り、DNS のレコードとそのトンネルを対応付けることにより、間接的にトラフィックがくるようなイメージです。
設定
基本的に公式ドキュメント通りです。今回は CLI で設定を進めます。
設定1. cloudflared のインストール
インストール方法はいろいろありますが、ここではさくっと dnf
でインストールします。
curl -fsSl https://pkg.cloudflare.com/cloudflared-ascii.repo | sudo tee /etc/yum.repos.d/cloudflared.repo sudo dnf install cloudflared
単一のバイナリでも提供されてて便利ですね。
設定2. 認証
clouldflared logint tunnel
コマンドでログインします。
$ cloudflared login tunnel A browser window should have opened at the following URL: https://dash.cloudflare.com/argotunnel?aud=略 If the browser failed to open, please visit the URL above directly in your browser. You have successfully logged in. If you wish to copy your credentials to a server, they have been saved to: /home/admin/.cloudflared/cert.pem
表示された認証用の URL を開き、Cloudflare にログインし、トンネルを利用する Zone を選択します。
この段階で、~/.cloudflared/cert.pem
というファイルが生成されます。
設定3. トンネルの作成
トンネルを作成します。
トンネルには名前を付ける必要があります。ここでは、複数のサーバーへの転送を束ねる意味合いとして gateway
とします。
$ cloudflared tunnel create gateway Tunnel credentials written to /home/admin/.cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel. Created tunnel gateway with id aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
トンネルの認証情報を含むファイルが生成されます。同時に、トンネルに対する ID も生成されます。上記のログでは aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
です。
cloudflared tunnel list
コマンドで、トンネルの一覧が確認できます。
$ cloudflared tunnel list You can obtain more detailed information for each tunnel with `cloudflared tunnel info <name/uuid>` ID NAME CREATED CONNECTIONS aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa gateway 2023-08-05T10:57:44Z
なお、この段階ではトンネル自体は作成したものの、Cloudflare 上に定義ができただけで、まだトンネルは張れていません。
$ cloudflared tunnel info gateway Your tunnel aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa does not have any active connection.
設定4. 設定ファイルの作成
トンネルを張るための設定ファイルを作成します。この設定ファイルに、利用する認証情報ファイルのパスや、Ingress rules などを指定します。
デフォルトで読み込んでくれるパスである ~/.cloudflared/config.yml
として以下の内容で作成します。説明用にコメントをつけています。
# トンネルのID tunnel: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa # トンネル作成時に生成された認証情報ファイル credentials-file: /home/admin/.cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json # Ingress rules # どのホスト名のリクエストを内部のどのサービスに転送するかの設定 ingress: - hostname: sv01.example.com service: https://10.0.1.1 # ローカルの転送先 sv01 originRequest: noTLSVerify: true # 証明書検証の無視(ラボ環境のため) - hostname: sv02.example.com service: https://10.0.1.2 # ローカルの転送先 sv02 originRequest: noTLSVerify: true # 証明書検証の無視(ラボ環境のため) - service: http_status:404 # どのホスト名にもマッチしない場合
設定項目の意味は公式ドキュメントに掲載されています。
最後の service: http_status:404
は、どのホスト名にもマッチしないときの挙動を指定しています。仕様上、この定義がないとエラーになるめ、無難に 404 を返すようにしています。実際は、今回の DNS の設定の仕方(後述)によって、指定ホスト名以外のトラフィックはトンネルにこないはずです。
設定5. トラフィックのルーティング
ドメイン上に CNAME レコードを作成し、トンネルを紐づけてトラフィックをルーティングします。
今回は、2つのホスト(sv01
、sv02
)を先ほど作成したトンネルに紐づけます。
$ cloudflared tunnel route dns gateway sv01 2023-08-05T11:20:23Z INF Added CNAME sv01.example.comwhich will route to this tunnel tunnelID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa $ cloudflared tunnel route dns gateway sv02 2023-08-05T11:20:26Z INF Added CNAME sv02.example.comwhich will route to this tunnel tunnelID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
ワイルドカード *
を指定して、あらゆるホスト名の指定をトンネルに向けることもできますが、少し抵抗があったので今回はやめておきます。
設定6. トンネルの起動
準備ができたので、いよいよトンネルを起動します。
$ cloudflared tunnel run gateway 2023-08-05T11:22:57Z INF Starting tunnel tunnelID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa ...(略)... 2023-08-05T11:22:58Z INF Registered tunnel connection connIndex=0 connection=略 2023-08-05T11:22:59Z INF Registered tunnel connection connIndex=1 connection=略 2023-08-05T11:23:00Z INF Registered tunnel connection connIndex=2 connection=略 2023-08-05T11:23:01Z INF Registered tunnel connection connIndex=3 connection=略
なお、--loglevel debug
をつけて、cloudflared tunnel --loglevel debug run gateway
のようにして起動すると、アクセスごとにログが表示されるので、動作確認に便利です。
トンネルを起動している状態で、cloudflared tunnel info
を実行すると、起動していることが確認できます。
$ cloudflared tunnel info gateway NAME: gateway ID: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa CREATED: 2023-08-05 10:57:44.021508 +0000 UTC CONNECTOR ID CREATED ARCHITECTURE VERSION ORIGIN IP EDGE bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb 2023-08-05T11:37:50Z linux_amd64 2023.7.3 203.0.113.1 2xKIX, 2xNRT
サービスとしてトンネルの起動できるようなので、別途試してみたいと思います。
動作確認のアクセス
トンネルを起動した状態で、今回ルールを定義した以下 2ホストのアクセスをして目的の画面が開けばOKです。
https://sv01.example.com
https://sv02.example.com
cloudflared tunnel run
をフォアグラウンドで起動しているため、Ctrl+C で終了するとトンネルが停止してアクセスもできなくなります。
ホスト追加時のオペレーション
今後、公開したいサーバー/サービスが増えてきたら、以下の手順で対応する予定です。
- 設定ファイル
~/.cloudflared/config.yml
へingress
の追記 - CNAME の追加
cloudflared tunnel route dns gateway 追加ホスト名前
- トンネルの再開
おわりに
Cloudflare Tunnel の Ingress rules で、複数サービスへの転送をまとめて定義する方法を試してみました。
一通りコマンドで済むのが良かったです。
この手の役割は、常時起動している機器、たとえばルーターに仕込んでみたくなりました。