Cloudflare Zero Trust Tunnel を利用して自宅の Ubuntu 機にインターネット経由で SSH 接続する

Cloudflare の Zero Trust Tunnel という機能を利用して、自宅の Ubuntu 機にインターネット経由で SSH 接続できるようにする。

Cloudflare が提供するネットワークに乗って VPN トンネルを作る感じになるので、昔ながらの「自宅サーバ」のようにルータ設定をいじくって22番ポートを開放したりする必要はない。

ただ、Cloudflare の設定画面などが頻繁に変わっており、ネット上のどの記事を参考にすれば良いか中々分かりづらかった。コマンドライン (cloudflared コマンド) で設定を完結できそうではあるが、今回は Cloudflare の Web コンソールを使っての作業手順としてまとめる。

前提 : 所有ドメインの DNS を Cloudflare で管理するようにしておく

前提として、自分が所有する独自ドメインがあること。そしてそのドメインの DNS 設定を Cloudflare 上で行えるようにしておく必要がある。

自分の場合は Value-Domain で取得したドメインがあり、コレまでは Value-Domain の DNS 設定を利用していたので、Cloudflare の Web コンソールにて「ドメインの登録」というモノを行った。

具体的には、ブラウザで Cloudflare のダッシュボードにログインしたら、左メニューの「ドメイン登録」→「ドメインの登録」を選択する。

ココで所有するドメインを入力すると、自動的に現在の DNS 設定を引っ張ってきてくれる。

あとは Value-Domain 側に、Cloudflare 指定のネームサーバを2つ設定してやり、変更反映を待つ。そうすると DNS 設定を Cloudflare 上で出来るようになる。なお、Value-Domain の管理画面からは「DNS 設定」の項目が消える。

ココら辺は画面の指示に従ってやっていくだけですんなり実施できた。

サーバ側に cloudflared をインストールする

まずは SSH 接続したい Ubuntu マシンに cloudflared コマンドをインストールする。

$ sudo mkdir -p --mode=0755 /usr/share/keyrings
$ curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
$ echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
$ sudo apt-get update && sudo apt-get install -y cloudflared

$ cloudflared --version
cloudflared version 2025.1.0 (built 2025-01-07-1219 UTC)

そしたら Zero Trust Tunnel を構築するためのログインを行う。

$ cloudflared tunnel login

ブラウザが開くと思うので、適宜 Cloudflare にログインする。

Web コンソールでトンネルを設定していく

この後、コマンドラインでは $ cloudflared tunnel create したり config.yml を書いたり $ cloudflared tunnel route dns コマンドを叩いたり…という感じで進めていくのだが、ちょっとよく分からなくなったので、Cloudflare の Web コンソールで設定をやり直した。

ココまでで初期設定は完了。

続いて、「パブリックホスト名の設定」で、どういうサブドメインにアクセスした時に SSH 接続するか、という設定を行う。

その他の設定は変更不要。コレでパブリックホスト名を保存すれば OK。

最後にプライベートネットワークを指定しておく。自分は適当に 192.168.1.0/24 という CIDR で登録しておいた。正直よく分からん。w

以上で、トンネル設定が完了した。ココまでの設定で、DNS 設定の中に指定したサブドメインに対するレコードが自動的に追加されているはずだ。

アプリケーション設定を行う

引き続き、左メニューの「Access」→「アプリケーション」に進み、「アプリケーションを追加する」から設定を行っていく。

「次へ」と進み、各種設定を進める。

最後の「ブラウザレンダリング」で SSH を選択しておくと、https://sub.example.com にブラウザでアクセスした時に SSH 接続ができるようになる。

コレで、指定のサブドメインに対するアクセスの認証設定などが出来た。

クライアント PC から ssh コマンドで接続を試してみる

さて、それではクライアント PC から ssh コマンドで接続してみる。ちょっと面倒だが、クライアント PC にも cloudflared コマンドのインストールが必要なので、そこだけ留意。今回は WSL Ubuntu で実施したので、前述のサーバ側でのインストール手順と同じモノを利用した。

cloudflared コマンドがインストールできたら、~/.ssh/config を次のように設定する。

Host sub.example.com
  HostName      sub.example.com
  Port          22
  User          username
  IdentityFile  ~/.ssh/example
  ProxyCommand  /usr/local/bin/cloudflared access ssh --hostname %h

このように準備したら、$ ssh sub.example.com コマンドで接続する。初回のみ、ProxyCommand に書いたとおり cloudflared コマンドを経由してログイン認証を求められるかと思うので、起動したブラウザに従ってログイン認証を行う。

コレで Cloudflare Zero Trust Tunnel 経由で SSH 接続ができるはずだ。

ブラウザレンダリングの SSH 接続を試してみる

最後に、ブラウザレンダリングの SSH 接続を試す。ココでちょっとつまづいた。

SSH 接続するサーバ側の、/etc/ssh/sshd_config ファイルで次のように設定しておく。特に PubkeyAcceptedAlgorithms がないと、秘密鍵・パスワードの形式が合わないとしてエラーになってしまうので入れておく。

# root ユーザでのログインを禁止する
PermitRootLogin no
# パスワード認証を無効にする
PasswordAuthentication no
# 公開鍵認証を有効にする
PubkeyAuthentication yes
# ssh-rsa 方式の公開鍵を許可する
PubkeyAcceptedAlgorithms +ssh-rsa

設定をしたら $ sudo systemctl restart ssh で設定変更のため再起動する。

で、ブラウザで https://sub.example.com にアクセスしてみると、Cloudflare が用意したログインページが開く。まずは SSH 接続したいユーザ名を入力する。

そして次の画面で、SSH 接続に利用する「SSH 秘密鍵」をペーストする。パスワード欄は、SSH 秘密鍵のパスフレーズを入れてなければ空欄で良い。

コレでブラウザレンダリングの SSH 接続ができるはずだ。

以上

いやー思ったよりも設定ダルかったな…。終わってしまえば仕組みは分かるけど、なかなか再現性のある手順でまとめるのはめんどくさい。w