🚪

Cloudflare Tunnel を使って自宅をデータセンターみたいにする

2023/11/30に公開

シーエー・アドバンス Advent Calendar 2023 3日目


最近ブラウザの edge でAIによる画像の生成ができるようなので、とりあえずアイキャッチ画像を生成して記事に張ってみた!(プロンプト: Generate an image of many servers are connected with each other and chrismas tree in the back but in the way of Utagawa Hiroshige style inspired by The fifty-three stations of the Tokaido.)

弊社もアドベントカレンダーの時期なので、記事書いてみます!

https://qiita.com/advent-calendar/2023/ca-advance

Cloudflare Tunnel をご存知でしょうか?

https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/

別に新しいサービスでも無いのですが、恥ずかしながら自分は最近知りました 🫣

Cloudflare Tunnel は固定のパブリックIPアドレスを使うこと無く、自宅にあるウェブサーバーやSSHサーバーに、自宅の外からアクセスできるようになる便利なサービスです。

このサービスを使うと、以下のような構成で環境が作れます。


上記 cloudflare tunnel の公式ドキュメントから引用

このサービスを使って嬉しいことは、

  • レンタルサーバーやホスティングサービスを使わずに、無料でウェブサイトを公開できる(Cloudflare Tunnel 使うだけなら無料)。
  • SSH で自宅の Linux サーバーに接続できるようになるので、検証用サーバーとして活用できる。例としては、、、
    • Linux のツールやソフトウェアの挙動確認を行う環境として利用
    • プログラムの作成、実行する環境として利用
    • etc...

つまり、自宅のPCやサーバーを、データセンターのサーバーのように扱えるということです!(誇大広告)

tunnel の技術を使わずにやろうとすると、自宅の回線に固定のIPアドレスを割り振ってもらう必要があるので、そうすると、ISPからその料金を請求されますが、これなら、その費用もかかりません!

業務で使っている aws の環境とか、サーバーであれこれ試すのは怖い・・・ので、そういうときに使える環境として、最近自分も使っています。

そこで、自分がどうやって Cloudflare Tunnel を導入したか、手順をご紹介しようかなと思います。
公式のドキュメント見ればわかることばかりですが、実際やってみるとドキュメントだけでは分かりづらいような箇所もあったので、参考になれば幸いです!

Cloudflare Tunnel を使って実現したこと

具体的には、以下をできるようにしました。

  • 自宅の外から、自宅のマシンに ssh できる
  • webサイトを自宅のマシンでホストして、一般に公開する(localhost ではなく、普通にドメインのURLでサイトにアクセスできる)

図にすると、以下のような感じです。

SSH 接続

  • 自宅のマシンをサーバー(右)とし、cloudflare の tunnel プログラムを常駐起動させる
  • サーバーに ssh 接続する端末側(左)でも、tunnel のプログラムを起動して、その tunnel 経由でサーバーに ssh 接続する

自宅のWebサイトを一般公開

  • (SSH 接続と同様に)自宅のマシンをサーバー(右)とし、cloudflare の tunnel プログラムを常駐起動させる
  • Cloudflare の管理画面で Tunnel を設定すると、自動的に、Cloudflare 上で CNAME のDNSレコードが作成されて、そのレコードが自宅マシンのサーバー(右)にプロキシします。
    • (ちなみに)自宅マシンで稼働する web サイトからは、localhost からリクエストが来ているように見えます。

手順

上記の SSH と HTTP に対応したトンネル環境を作る手順です。
ただし以下の点だけ注意してください。

流れ

  1. Cloudflare アカウントを作成(無料)
  2. Cloudflare にサイトを追加(無料)
  3. ドメインレジストラの DNS 設定に、Cloudflare の nameserver を指定する
  4. Cloudflare tunnel の作成と起動
  5. Cloudflare Tunnel 経由でSSH や HTTP の通信を行う

1. Cloudflare アカウントを作成(無料)

詳細は割愛しますが、普通にメールアドレスとか登録するだけで簡単に作れたかと思います。
アカウント作成するだけならお金もかからない。

2. Cloudflare にサイトを追加(無料)

Cloudflare のダッシュボードにログインするとこんな画面が出てきます。
Add site でサイトを追加します。

そしたら、ドメインを入力する画面が出てくるので、こちらで自分が所有管理しているドメインを入力します。

その後、プランを選ぶ画面が出てきますが、Cloudflare Tunnel を使うだけなら、Free で大丈夫です。

3. ドメインレジストラの DNS 設定に、Cloudflare の nameserver を指定する

Cloudflare Tunnel の仕組みでは、Cloudflare の DNS も使っているので、
ドメインの nameserver を Cloudflare の DNS の nameserver に変更します。

(これで、Cloudflare Tunnel の機能が、Cloudflare側で、DNS レコードを自動で作るようになる)

Cloudflare の nameserver の情報は、Cloudflare のダッシュボードの DNS のところで確認できます。

DNS を開くと、以下の画面が出てきて、下の方に namesavers の情報があります。

cloudflare の nameservers の情報を、ドメインレジストラのドメイン管理の画面で、設定します。自分はエックスサーバーというところで、ドメインを入手したので、エックスサーバーでの nameserver の設定画面を載せますが、どこでドメインを取得してもだいたい似たようなUIで設定できるはずです。

4. Cloudflare tunnel の作成と起動

Cloudflare のダッシュボードから、Cloudflare Zero Trust のダッシュボードを開きます。

Tunnel のメニューを開いて、Add a tunnel をクリックします。

Tunnel に任意の名前をつけて、save tunnel します。

次の画面で、Choose your enviornment で、docker を選択し、
docker コマンドが表示されるので、自宅のマシン上で、このコマンドを実行しますが、
内容はは少し書き換えて実行します。

変更を加えたコマンドはこちら↓

dockerコマンド
docker run -d --network=host cloudflare/cloudflared:latest tunnel --no-autoupdate run --token TOP-SECRET-TOKEN

変更している点:

  • -d を追加してデーモン化
  • --network=host にして、コンテナのネットワークインターフェースと、ホストマシンのインターフェースを一体化。これで、Tunnel の設定時に、localhost で、トンネルが起動しているマシンのことを参照できるようになる。こうしないと、マシンそのものの、IPアドレス(LAN 内のプライベートな) を Tunnel 設定で指定する必要があり、IPアドレスをいちいち調べたりするのが面倒だというのと、DHCP環境だと変わる可能性もあるので、このネットワーク設定にしています。

docker コマンドの実行がうまくいって、tunnel が作成されると、以下のように connected と表示されるようになり、tunnel の準備が完了です。

トンネルの作成と起動ができたので、実際の通信を行うための設定をしていきます。

トンネルの一覧から、作成したトンネルの をクリックして configure します。

public hostname タブをクリックし、Add a public hostname をクリックします。

すると次のような画面が出てきます。

このスクリーンショットでは、SSH接続のための設定になっています。
Type には SSH を指定して、URL として、localhost:22 を指定しています。

(docker コンテナのトンネルを --network=host で起動していないと、ここで localhost の指定をしてもトンネルの通信ができないので注意!)

Subdomain の値は自由に決めて大丈夫ですが、わかりやすく ssh としています。
もしドメインが example.com であれば、ssh 接続の際に参照するドメインは ssh.example.com となります。

更に、同じ要領で、HTTP での通信のための設定も追加します。
この設定を入れると、自宅のマシンでホストされているウェブサイトの公開もできるようになります。

こちらは、Type を HTTP にしています。ポートも通常の 80 番なので、URL の部分は localhost だけで大丈夫です。(こちらも docker コンテナが --network=host で起動していることが前提です!)

Subdomain はウェブサイトなので、www にしてみました。(でもなんでも任意のサブドメインで大丈夫)

ちなみに、サブドメインの部分と対応するURLのポート番号を変えて、このプロセスを繰り返せば、複数のウェブサイトをホストして公開することも可能です!

5. Cloudflare Tunnel 経由でSSH や HTTP の通信を行う

SSH の接続

記事冒頭でお見せした以下の画像の様に、ssh 接続を行います。

1. (前提) cloudflared をインストール

まず、ssh の接続元となるクライアント端末(上記画像だと左の端末)に、
cloudflared のコマンドをインストールしてください。
インストール方法は以下のページで確認できます。

https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/

上記のページにある通り、Mac に brew でインストールすることも可能なので、自分はそうしました。

brew の情報↓

terminal
❯ brew info cloudflared
==> cloudflared: stable 2023.10.0 (bottled), HEAD
Cloudflare Tunnel client (formerly Argo Tunnel)
https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide
/usr/local/Cellar/cloudflared/2022.12.1 (7 files, 35MB) *
  Poured from bottle on 2023-01-14 at 22:21:33
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/c/cloudflared.rb
License: Apache-2.0
==> Dependencies
Build: go@1.20 ✘
==> Options
--HEAD
	Install HEAD version
==> Analytics
install: 1,714 (30 days), 4,108 (90 days), 16,271 (365 days)
install-on-request: 1,672 (30 days), 3,938 (90 days), 15,820 (365 days)
build-error: 0 (30 days)

2. トンネルを起動

cloudflared がインストールされた状態で、以下のコマンドを実行し、tunnel を起動します。(クライアント側でのトンネル起動です、サーバー側は既に起動してある前提)

terminal
❯ cloudflared access ssh --hostname ssh.example.com --url localhost:3322
2023-11-30T13:26:10Z INF Start Websocket listener host=localhost:3322

cloudflared access ssh が接続元のクライアントでトンネルを起動するコマンドです。

  • --hostname
    • こちらは tunnel の設定時にサブドメインを設定しましたが、そのサブドメインを指定します。
  • --url
    • トンネルのURLです。後ほど、ssh 接続を行うときに、localhost:3322 を接続先とします。ポート番号は空いている番号であれば何でも大丈夫です。

3. ssh コマンドで接続する

以下のコマンドで、トンネル に ssh 接続します。

terminal
ssh ssh://your_username@localhost:3322

port 番号を通常の 22 番ではなく、3322 を使いたいので、URL風な引数を ssh に渡しています。

your_username は適宜接続先のサーバーに存在するユーザーに書き換えてください。

トンネルの --url で指定したように、localhost をこちらでも指定しています。
しかし、実際に接続される先のサーバーは、このマシンではなく、cloudflare トンネルの終端があるリモートマシンです!

これで、自宅の外からでも、自宅のサーバーに SSH できるようになりました!

ただ、この方法は、トンネル起動ssh 接続コマンド実行 という 2 ステップで少し手間です。

これを1ステップで接続できるようにするために、以下を ssh config に追記してあげます。

~/.ssh/config
Host cloudflare-tunnel
  HostName ssh.example.com
  User your_username
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
  • HostName
    • cloudflare tunnel 設定時に決めたサブドメイン
  • User
    • 接続時のユーザー(接続先のサーバーに有効なユーザーとして存在すること)
  • ProxyCommand
    • 接続時に実行するコマンドを指定
    • ssh 接続実行と同時に(直前に?)cloudlared でトンネルを起動した上で、ssh 接続を行う

上記の設定を追記した後は、以下のように、シンプルに ssh 接続できるようになります。

ssh cloudflare-tunnel

HTTP のトンネルでウェブサイトを起動する

トンネルの設定自体は、cloudflare の画面から既に済んでいるので、自宅のマシン上で、何かしらのウェブサーバーを 80 番ポートで待ち受ける形で起動するだけです。

例えば、nginx の docker コンテナなど簡単に起動できて、疎通確認に使えます。

docker run -p 80:80 -d --rm --name nginx-container nginx:latest

cloudflare tunnel のサブドメインとかの設定がうまく行っていれば、その時に設定したサブドメインで nginx の初期画面が開けるはずです!

今回の例だと、https://www.example.com で行けるかと思います。

Cloudflare Tunnel を使ってウェブサイトを公開すると、自動的に HTTPS が有効になるおまけ付きです。

まとめ


コンピュータが発掘される1万年後の地球

以上、Cloudflare Tunnel を掘ってみました!

Linux サーバー使いたいけど、レンタルサーバーとかお金はかけたくない、、、
というとき、この方法はお金もかからないのでおすすめです!

弊社の2023年のアドベントカレンダーがあるので、よかったら他の記事も是非見て行ってください
👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
https://qiita.com/advent-calendar/2023/ca-advance

参考

https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/

  • 基本は公式見れば問題ないです。
  • smb サーバーをトンネルで公開する方法とかもあって参考になります。

https://www.youtube.com/watch?v=ey4u7OUAF3c&t=2s

  • 概要とか使い方をサクッと知りたい人はこの短い動画もおすすめです。

Discussion