はじめに
Cloudflare Tunnelを使用すると、安全で効率的に自宅のサーバーにリモートアクセスが可能。この記事では、Cloudflare Tunnelを設定してSSHアクセスを実現し、さらにTunnelをdaemon化する方法を解説する。
サーバー側のCloudflaredの準備
インストール
まずはcloudflaredをインストールする。
# `apt` 経由でインストールする
sudo apt update
sudo apt install cloudflared
ログイン
cloudflaredを使用するためには、Cloudflareアカウントにログインしcert.pem
を取得する必要がある。
cloudflared tunnel login
# ログインをするとURLが表示されるので、ブラウザで認証を行いキーを取得する
A browser window should have opened at the following URL:
https://dash.cloudflare.com/argotunnel?aud=&callback=https%3A%2F%2Flogin.cloudflareaccess.org********************
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}/.cloudflared/cert.pem
Tunnelの準備
作成
トンネルを作成する。
# 例: sudo cloudflared tunnel create mylocalserver
sudo cloudflared tunnel create <トンネル名>
設定が正しく行われたか確認するには、以下のコマンドを使用する。
ls ~/.cloudflared/
# 以下、トンネルIDで始まる.jsonファイルとcert.pemがあれば正しく設定されている
<トンネルのID>.json cert.pem
トンネルの一覧を表示する。
sudo cloudflared tunnel list
設定
コンフィグファイル作成
config.yml
ファイルを作成し、トンネルの設定を記述する。
touch ~/.cloudflared/config.yml
以下の内容をconfig.yml
に書き込む。
tunnel: <トンネルUUID>
credentials-file: <トンネルUUIDファイルパス>.json
ingress:
- hostname: <ssh用のmylocalserver hostname>
service: ssh://<ローカルサーバーアドレスorホスト名>:22
- service: http_status:404
設定ファイルを/etc/cloudflared
に移動する。
sudo mkdir /etc/cloudflared
sudo cp ~/.cloudflared/* /etc/cloudflared
DNS設定
トンネルで設定したサービスにプロキシするためのDNSレコードを追加する。
# ssh用のDNSの設定
sudo cloudflared tunnel route dns <トンネル名> <ssh用のmylocalserver hostname>
ルーティング
プライベートネットワークにアクセスするために、IPアドレスまたはCIDRをルーティングする。
sudo cloudflared tunnel route ip add <IP/CIDR> <トンネルUUID or トンネル名>
# 例: sudo cloudflared tunnel route ip add 192.168.86.0/24 test-tunnel
ルーティング設定を確認する。
sudo cloudflared tunnel route ip show
トンネルの起動
トンネルを起動する。
sudo cloudflared tunnel run
# 以下の様なログがでたらOK
2024-XX-XXTXX:XX:XXZ INF Starting tunnel tunnelID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
...
設定ファイルを直接指定する場合は以下のコマンドを使用する。
sudo cloudflared tunnel --config /path/your-config-file.yml run <トンネルUUID or トンネル名>
トンネルの確認
トンネルの情報を確認する。
sudo cloudflared tunnel info <トンネルUUID or トンネル名>
# 以下の様ログがでたらOK
NAME: <トンネル名>
ID: <トンネルUUID>
CREATED: 2024-06-18 03:55:20.46502 +0000 UTC
CONNECTOR ID CREATED ARCHITECTURE VERSION ORIGIN IP EDGE
************ 2024-06-18T05:38:03Z linux_amd64 2024.6.0 ***.***.***.*** 1xkix03, 1xkix04, 2xkix05
トンネルのdaemon化
systemdサービスとして設定
systemd
を使用して、cloudflared
をサービスとして設定し、自動的に起動するようにする。以下の内容を/etc/systemd/system/cloudflared.service
に記述する。
[Unit]
Description=cloudflared
After=network-online.target
Wants=network-online.target
[Service]
TimeoutStartSec=0
Type=notify
ExecStart=/usr/bin/cloudflared --no-autoupdate tunnel run
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
systemctl
の設定を更新する。
sudo systemctl daemon-reload
sudo systemctl enable cloudflared
sudo systemctl stop cloudflared
sudo systemctl start cloudflared
動作確認を行う。
ps aux|grep cloudflared|grep -v grep
root 125629 0.3 0.0 1260968 40544 ? Ssl 14:38 0:00 /usr/bin/cloudflared --no-autoupdate tunnel run
SSH接続の設定
公開鍵の作成
クライアント上で以下のコマンドを実行し鍵を作成する。
ssh-keygen -t rsa -f ~/.ssh/cloudflare_tunnel -C <username@cloudflare_tunnel>
鍵の確認
公開鍵と秘密鍵が作成されているか確認する。
ls ~/.ssh/cloudflare_tunnel*
公開鍵のコピー
公開鍵をコピーする。
cat ~/.ssh/cloudflare_tunnel.pub
サーバー側に公開鍵を追加
サーバー側の.ssh/authorized_keys
に公開鍵を登録する。
cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.old
cat >> ~/.ssh/authorized_keys
ssh-rsa ************************************* username@cloudflare_tunnel
# Ctrl+Dで確定
クライアント側のsshのconfig設定
~/.ssh/config
に以下の設定を追加する。
Host <ssh用のホスト名>
User <ログインユーザー名>
HostName <ssh用のホスト名>
IdentityFile ~/.ssh/cloudflare_tunnel
ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
ssh接続の確認
SSH接続を確認する。
ssh <ssh用のホスト名>
# 無事クライアントからリモートのSSHサーバーへ接続
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.153.1-microsoft-standard-WSL2 x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
...
TunnelのFirewall
Cloudflare Tunnelを使用して、すべてのインバウンドトラフィックをブロックし、cloudflaredからのアウトバウンドトラフィックのみを許可することで、ポジティブセキュリティモデルを実装できる。トンネル構成で指定されたサービスのみが外部に公開される。この記事では、OSレベルでのFirewallについて解説する。
OSのFirewall
OSレベルのファイアウォールルールを使用して、すべてのインバウンドトラフィックをブロックし、アウトバウンドトラフィックのみを許可できる。例えば、サーバーがLinux上で動作している場合、iptablesを使用してファイアウォールルールを設定できる:
現在のファイアウォールルールを確認する:
sudo iptables -L
ローカルホストが自身と通信することを許可する:
sudo iptables -A INPUT -i lo -j ACCEPT
既に確立された接続と関連するトラフィックを許可する:
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
新しいSSH接続を許可する:
sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT
その他のすべてのインバウンドトラフィックをドロップする:
以下のコマンドには注意が必要。現在のSSH接続を保持していないか、新しいSSH接続を許可していない場合、ログアウトされシステムに再びSSH接続できなくなる。
sudo iptables -A INPUT -j DROP
ファイアウォールルールを設定した後、以下のコマンドを使用して現在のiptables設定を確認する:
sudo iptables -L
トンネルを実行し、すべての構成されたサービスがトンネル経由で外部からアクセス可能であることを確認するが、サーバーの外部IPアドレス経由ではアクセスできないことを確認する。また、Cloudflare Accessを使用してアプリケーションを保護することもできる。
Tunnelのログ
Tunnelのログは、cloudflaredインスタンスとCloudflareのグローバルネットワーク間、およびcloudflaredとオリジンサーバー間のすべてのアクティビティを記録する。これらのログを使用して、Cloudflareトンネルの接続性やパフォーマンスの問題を調査することができる。サーバーに永続的なログを保存するように構成するか、任意のクライアントマシンからリアルタイムのログをストリーミングすることができる。
サーバー上でログを表示
オリジンサーバーにアクセスできる場合、トンネルを開始する際にログを有効にすることができる:
cloudflared tunnel --loglevel debug run <UUID>
--loglevel
フラグはローカルcloudflaredインスタンスのログレベルを示し、{debug, info, warn, error, fatal}のいずれかを指定できる(デフォルトはinfo)。デバッグレベルでは、cloudflaredはリクエストURL、メソッド、プロトコル、コンテンツ長、すべてのリクエストおよびレスポンスヘッダーをログに記録して表示する。ただし、これによりログに機密情報が表示される可能性があることに注意。
ログをファイルに書き込む
デフォルトでは、cloudflaredはログをstdoutに出力し、サーバーにはログを保存しない。--logfile
フラグを使用してログをファイルに保存することができる:
cloudflared tunnel --logfile mytunnel.log run <UUID>
ローカルマシンでログを表示
Cloudflareトンネルのリアルタイムログは、ダッシュボードやcloudflaredがインストールされた任意のマシンから表示できる。リモートログストリームを使用する場合、トンネルを実行しているサーバーにSSH接続する必要はない。
WEBダッシュボード
必要条件
- cloudflaredバージョン2023.5.1以上がオリジンサーバーにインストールされていること。
- トンネルがアクティブでリクエストを受信できること。
ログを表示
- Zero Trustで、Networks > Tunnelsに移動し、トンネルを選択する。
- サイドバーで、表示したいcloudflaredインスタンスのコネクタIDを選択する。
- 「Begin log stream」を選択する。
CLI
cloudflaredデーモンは、アカウント内の任意のトンネルからローカルコマンドラインにログをストリームすることができる。
必要条件
- cloudflaredバージョン2023.5.1以上がローカルマシンとオリジンサーバーの両方にインストールされていること。
- トンネルがアクティブでリクエストを受信できること。
ログを表示
- ローカルマシンで、cloudflaredをZero Trustアカウントに認証する:
cloudflared tunnel login
- 特定のトンネルに対して
cloudflared tail
を実行する:cloudflared tail <UUID>
- JSONメッセージの構造化されたビューを取得するために、出力を
jq
のようなツールにパイプすることができる:cloudflared tail --output=json <UUID> | jq .
ログのフィルタリング
ログのストリーミング量を減らすために、イベントタイプ(--event
)、イベントレベル(--level
)、サンプリングレート(--sampling
)でログをフィルタリングできる。これにより、特にオリジンが通常高負荷のときに、オリジンへのパフォーマンス影響を軽減できる。例えば:
cloudflared tail --level debug <UUID>
フラグ | 説明 | 許可される値 | デフォルト値 |
---|---|---|---|
--event | イベント/リクエストのタイプでフィルタリングする。 | cloudflared, http, tcp, udp | すべてのイベント |
--level | このレベル以上のログを返す。サーバー上の--loglevel 設定とは独立して動作する。 |
debug, info, warn, error, fatal | debug |
--sampling | ログの総数の一部をサンプリングする。 | 0.0から1.0の数値 | 1.0 |
レプリカのログを表示
同じトンネルに対して複数のcloudflaredインスタンス(レプリカ)を実行している場合、ログをストリームする個々のインスタンスを指定する必要がある:
- Zero Trustで、Networks > Tunnelsに移動し、トンネルを選択する。
- 表示したいcloudflaredインスタンスのコネクタIDを見つける。
- cloudflared tailでコネクタIDを指定する:
cloudflared tail --connector-id <CONNECTOR ID> <UUID>
パフォーマンスの考慮事項
ログセッションは1時間のみ開かれる。すべてのログシステムはパフォーマンスのオーバーヘッドを引き起こし、この制限はトンネルのエンドツーエンド遅延への長期的な影響を防ぐのに役立つ。高スループットトンネルのログをストリーミングする場合、Cloudflareは意図的にサービスの安定性をログの配信よりも優先する。ドロップされたログの数を減らすには、少ないログをリクエストすることを試みる。すべてのログを確認するには、リモートでログをストリーミングする代わりにサーバー上でログを表示する。
コマンド一覧
Tunnelの管理
コマンド | 説明 |
---|---|
cloudflared tunnel login |
ブラウザウィンドウが開き、Cloudflareアカウントにトンネルを認証する。 |
cloudflared tunnel list |
すべてのアクティブなトンネル、その作成時間、および関連する接続を表示する。-d フラグを使用して削除されたトンネルを含めることができる。 |
cloudflared tunnel create <NAME or UUID> |
トンネルを作成し、Cloudflareエッジに登録し、このトンネルを実行するための認証ファイルを生成する。 |
cloudflared tunnel route |
トラフィックをトンネル経由でルーティングする。 |
cloudflared tunnel route lb <NAME or UUID> <load balancer name> <load balancer pool> |
トンネルを指すプールを持つロードバランサーを作成する。 |
cloudflared tunnel route ip add <IP/CIDR> <NAME or UUID> |
ネットワークルートスペース(CIDR形式)をルーティングテーブルに追加する。このネットワークスペースは、Cloudflare WARPを使用し、同じアカウントに登録されているユーザーのマシンからのリクエストに対して到達可能になる。また、指定されたトンネルにプロキシされ、トンネルから到達可能なIPにリクエストが届く。特定の仮想ネットワークにIPルートを割り当てるには、--vnet オプションを使用する。 |
cloudflared tunnel route ip show (or list) |
組織のプライベートルーティングテーブルを表示する。追加のフラグを使用して結果をフィルタリングできる。 |
cloudflared tunnel route ip delete |
指定されたCIDRの行をルーティングテーブルから削除する。その部分のネットワークはWARPクライアントから到達できなくなる。 |
cloudflared tunnel route ip get <IP/CIDR> |
特定のIPをプロキシするために使用されるルーティングテーブルの行を確認する。これにより構成をチェックおよび検証できる。 |
cloudflared tunnel route dns |
トンネルを指すDNS CNAMEレコードのホスト名を作成する。 |
cloudflared tunnel --config path/config.yaml run <NAME or UUID> |
トンネルを実行し、サーバーとCloudflareエッジ間で高可用性の接続を作成する。トンネルの名前またはUUIDを最後のコマンドライン引数として、または構成ファイルでtunnel: <NAME> を使用して指定することができる。 |
cloudflared tunnel info <NAME or UUID> |
名前またはUUIDで特定されたトンネルのアクティブなコネクタに関する詳細を表示する。 |
cloudflared tunnel cleanup <NAME or UUID> |
指定されたUUIDまたは名前を持つトンネルの接続を削除する。cloudflaredが正常にシャットダウンされなかった場合(例えば、killコマンドが発行された場合など)、トンネルを削除または実行する際のエラーを解決するのに役立つ。 |
cloudflared tunnel cleanup --connector-id <CONNECTOR-ID> <NAME or UUID> |
指定されたコネクタIDを持つcloudflaredレプリカを切断および削除する。すべてのレプリカを表示するには、cloudflared tunnel info <NAME or UUID> を実行する。 |
cloudflared tunnel delete <NAME or UUID> |
指定された名前またはUUIDを持つトンネルを削除する。アクティブな接続がある場合、トンネルは削除できない。強制的に削除するには、-f フラグを使用する。 |
cloudflared tunnel vnet add <NAME or UUID> |
IPルートを割り当てるための仮想ネットワークを作成する。この仮想ネットワークをZero Trust組織のデフォルトにするには、-d フラグを使用する。 |
cloudflared tunnel vnet delete <NAME or UUID> |
指定された名前またはUUIDを持つ仮想ネットワークを削除する。仮想ネットワークを削除する前に、すべてのIPルートを削除する必要がある。 |
cloudflared tunnel vnet list |
すべてのアクティブな仮想ネットワーク、デフォルトの仮想ネットワーク、およびその作成時間を表示する。 |
cloudflared tail <UUID> |
特定のトンネルからログをライブストリーミングするセッションを開始する。詳細については、トンネルログを参照すること。 |
cloudflaredの管理
コマンド | 説明 |
---|---|
cloudflared update |
公式ダウンロードサーバーで新しいバージョンを確認する。新しいバージョンが存在する場合、エージェントバイナリを更新し、終了する。存在しない場合、アクションは行われない。このコマンドは、cloudflaredがGitHubのバイナリまたはソースからインストールされた場合にのみ動作する。詳細は、更新手順を参照すること。 |
cloudflared version |
cloudflaredのバージョン番号とビルド日を表示する。 |
cloudflared help |
cloudflaredのトップレベルコマンドの一覧を表示する。 |
用語集
用語 | 説明 |
---|---|
トンネル(Tunnel) | オリジンサーバーとCloudflareのグローバルネットワーク間で確立できる安全な、アウトバウンドのみの経路。各トンネルには名前とUUIDが割り当てられる。 |
トンネルUUID(Tunnel UUID) | トンネルに割り当てられた英数字の一意のID。特定のトンネルを参照する際に使用する。 |
トンネル名(Tunnel name) | ユーザーがトンネルに対して選択する一意で使いやすい識別子。複数のサービスにトラフィックをプロキシするため、ホスト名である必要はない。 |
コネクタ(Connector) | cloudflaredと呼ばれるコネクタは、オリジンサーバーからCloudflareのグローバルネットワークへの接続を確立する。2つの異なるデータセンターに4つの長時間接続を作成することで高可用性を提供する。 |
レプリカ(Replica) | トンネルを一度作成し、複数のユニークなコネクタインスタンス(cloudflared)でそのトンネルを実行することができる。これらのインスタンスはレプリカと呼ばれる。 |
リモート管理トンネル(Remotely-managed tunnel) | Zero TrustのNetworks > Tunnelsで作成されたトンネル。トンネルの構成はCloudflareに保存され、ダッシュボードやAPIを使用して管理できる。 |
ローカル管理トンネル(Locally-managed tunnel) | コマンドラインでcloudflared tunnel create <NAME> を実行して作成されたトンネル。トンネルの構成はローカルのcloudflaredディレクトリに保存される。 |
デフォルトのcloudflaredディレクトリ(Default cloudflared directory) | cloudflaredは、トンネルの認証ファイルやcloudflared loginを実行したときに生成されるcert.pemファイルを保存するためのデフォルトディレクトリを使用する。 |
構成ファイル(Configuration file) | cloudflaredの操作マニュアルとして機能するYAMLファイル。任意のディレクトリに構成ファイルを保存でき、ファイルパスを指定することでcloudflaredの動作を詳細に制御できる。 |
cert.pem | cloudflaredトンネルログインを実行したときにCloudflareによって発行される証明書ファイル。新しいトンネルを作成、既存のトンネルを削除、DNSレコードの変更、トンネルルーティングの構成に必要。 |
認証ファイル(Credentials file) |
cloudflared tunnel create <NAME> を実行したときに作成される。トンネルの認証情報がJSON形式で保存され、各トンネルに固有のもの。 |
イングレスルール(Ingress rule) | どのローカルサービスにトラフィックをプロキシするかを指定するルール。構成ファイルに記載するか、cloudflared tunnel ingress を実行するときに指定する。 |
クイックトンネル(Quick tunnels) | trycloudflare.comのランダムなサブドメインからなるURLを生成し、ローカルホストのポート8080にトラフィックを送る。 |
仮想ネットワーク(Virtual networks) | プライベートネットワーク上のリソースを論理的に分離するためのソフトウェア抽象化。エンドユーザーがリソースに接続するには、WARPクライアント設定で仮想ネットワークを選択し、目的のIPを入力する。 |