SSH に VPN 箱なんてジャマ ... 2018 - 2024
はじめに
グローバル IP アドレスを持たないサーバーへの Clodflare を介した SSH 接続について新しい方法(Access for Infrastructure)が出てました。従来の方法含め、Free Plan で利用でできる機能を書いておきます。
... 2018 年、それは自分たちのために作られた。
However, SSH connections held us back. Whenever we needed to push code or review a pull request, we had to fall back to our cumbersome VPN.
やんちゃだな...
方法 | クライアント側環境 | SSH 接続先 | サーバー側環境 | SSH プロキシー |
証明書認証対応 と Cloudflare SSH CA API |
Blog | |
---|---|---|---|---|---|---|---|
1 | クライアントサイド cloudflared | cloudflared access | 公開ホスト名 🍊 |
cloudflared tunnel (Public Hostname) |
なし 透過 |
Short-lived certificate CA access/apps/ca |
Announcing SSH Access through Cloudflare 2018 Public keys are not enough for SSH security 2019 |
2 | WARP-to-Tunnel | WARP | プライベートIP or プライベートホスト名 |
cloudflared tunnel (Private Network) |
なし 透過 |
なし | Building many private virtual networks through Cloudflare Zero Trust 2022 |
3 | WARP-to-Tunnel + SSH プロキシーとコマンドログ |
WARP | プライベートIP or プライベートホスト名 |
cloudflared tunnel (Private Network) |
あり MITM |
Gateway SSH proxy CA access/gateway_ca |
Introducing SSH command logging 2022 |
4 NEW 推奨 |
WARP-to-Tunnel + Access for インフラストラクチャ |
WARP | プライベートIP or プライベートホスト名 |
cloudflared tunnel (Private Network) |
あり MITM |
Gateway SSH proxy CA access/gateway_ca |
Fearless SSH: short-lived certificates bring Zero Trust to infrastructure 2024 |
Notes
- 1, 2 は SSH クライアントとサーバーが直接接続、3, 4 は Cloudflare を介して接続
- 1, 2 から 3, 4 に移行する場合は、サーバーのホストキーが変わる(初回のみ)
- 3, 4 はクライアントに SSH 認証を求めない(WARP で組織にログインすればよく、クライアント側の鍵管理から開放)
- 1(の証明書認証), 3 は Access(WARP)ログインのユーザー名を元に証明書が作成されるため、それと SSH のユーザー名が合致するようにするのが基本
- 4 は SSH ログインユーザー名を元に証明書が作成されるのでそこを気にする必要はなく、また、Cloudlare 側で SSH ユーザー名を参照しログインを制限する機能を提供
- 2 - 4 でプライベートホスト名で接続する場合は、名前解決ができるよう準備
- これからは 4 が推奨
SSH with Access for Infrastructure (recommended)
- 4 は 1 と 3 のイイとこ取りといった感じ
1. クライアントサイド cloudflared
👉️ Blog
SSH を HTTPS にラップし、Public Hostname 経由で繋ぎます。
Cloudflare は SSH をプロキシーしないので、SSH クライアントとサーバーの直接接続になります。
クライアント側は cloudflared access
を利用します。
パブリックホストに Cloudflare Access (Self-hosted)
を追加し、SSH サーバーの前で HTTP で認証・認可をかけます(かけるのが推奨)。
SSH サーバーで証明書での認証を有効にすれば、Access の認証を SSH サーバーのログインに利用し、運用の簡素化とセキュリティの強化、ユーザービリティの向上が見込めます。
Cloudflare SSH CA が一時的なユーザー証明書を作成しクライアントに利用させます。
接続例
SSH クライアント
証明書認証の場合。
$ cat .ssh/config
Match host remote.example.com exec "/opt/homebrew/bin/cloudflared access ssh-gen --hostname %h"
ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h
IdentityFile ~/.cloudflared/%h-cf_key
CertificateFile ~/.cloudflared/%h-cf_key-cert.pub
$ ssh ubuntu@remote.example.com
A browser window should have opened at the following URL:
https://remote.example.com/cdn-cgi/access/cli?...
If the browser failed to open, please visit the URL above directly in your browser.
ブラウザが開かれ、Access 認証に進む。
認証・認可が完了すると、ログインできる。
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.5.0-1023-oracle x86_64)
Access から渡された JWT や SSH 鍵、証明書は ~/.cloudflared に保存。
$ ls .cloudflared/
remote.example.com-cf_key
remote.example.com-cf_key.pub
remote.example.com-cf_key-cert.pub
remote.example.com-xxx-token
<team>.cloudflareaccess.com-org-token
SSH サーバー
接続元の IP アドレスは cloudflared tunnel
稼働マシン。
Accepted publickey for ubuntu from 172.16.0.147 port 35314 ssh2: ECDSA-CERT SHA256:I... ID 1... (serial 4...) CA ECDSA SHA256:f...
Cloudflare
SSH CA の設定箇所
Access > Service auth > SSH
👉️ API endpoint
ブラウザーでの SSH
Public Hostname に対するブラウザーでの SSH 接続も可能。
Access > Applications > Settings
2. WARP-to-Tunnel
👉️ Blog
WARP-to-Tunnel で Private Network 上の SSH サーバーに接続します。
WARP デバイスに SSH サーバーのローカルネットワークへの接続性を提供します。
クライアントサイド cloudflared の 1 対 1 設計に比べ、スケールできる利点があります。
Cloudflare は SSH をプロキシーしないので、SSH クライアントとサーバーの直接接続になります。
Gateway の Firewall Policy(Network)で接続を制御することができます。
SSH 接続に対する Access による認証認可はありません。
接続例
SSH クライアント
C:\Users\K> ssh -i .ssh/key ubuntu@172.16.0.147
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-1019-oracle x86_64)
SSH サーバー
Accepted publickey for ubuntu from 172.16.0.147 port 42494 ssh2: RSA SHA256:W...
Cloudflare
宛先 SSH サーバー IP/Port を Allow。(設定しなくても、暗黙の許可あり)
Gateway > Firewall policies > Network
Logs > Gateway > Network
3. WARP-to-Tunnel + SSH プロキシーとコマンドログ
👉️ Blog
Gateway で SSH をプロキシーし認証運用を簡素化、また、コマンドログを取り監査を強化することができます。
宛先 SSH サーバーはパブリック・プライベートどちらのアドレスでもいいです。
プライベートに接続する場合は WARP-to-Tunnel を利用します。
SSH クライアント
既存環境に追加実装されると Cloudflare が SSH をプロキシーするので、鍵が変わる(初回のみ)。
C:\Users\K>ssh aduser1@172.16.0.147
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
Remove し、再接続。
C:\Users\K>ssh-keygen -R 172.16.0.147
# Host 172.16.0.147 found: line 16
SSH 認証要求されず接続が可能。
C:\Users\K>ssh -v aduser1@172.16.0.147 whoami 2>&1 |findstr Authenticated
Authenticated to 172.16.0.147 ([172.16.0.147]:22) using "none".
Cloudflare
Gateway Firewall Policy Network で Audit SSH
のルールを追加。
Gateway > Firewall policies > Network
Port は 22 決め打ちのため、指定しない。指定すると Audit SSH が選べなくなる。
Logs > Gateway > Network
Network のログは一行にまとまる。
(Allow のポリシー名で、Action が ALLOW から AUDIT SSH に上書きされる)
SSH CA の設定箇所
👉️ API Endpoint
クライアントサイド cloudflared の場合と違う。
SSH コマンドログ
SSH コマンドログを取り出す。
Logs > Gateway > SSH
右端の Download
暗号化されたファイルをダウンロードして複合すると、その SSH セッションが丸裸。
$ ./ssh-log-cli decrypt -i $LOGFILE -k ssh_log_enc_key
$ unzip $LOGFILE-decrypted.zip
extracting: term_data.txt
extracting: term_times.txt
$ cat term_data.txt
Session started on 2024-11-02 08:14:03+00 [TERM="unknown" COLUMNS="126" LINES="30"]
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-1019-oracle x86_64)
:
:
aduser1@sv01:~$ cat /var/log/auth.log
cat: /var/log/auth.log: Permission denied
aduser1@sv01:~$
:
:
Script done on 2024-11-02 08:14:28+00 [COMMAND_EXIT_CODE="1"]
4. WARP-to-Tunnel + Access for インフラストラクチャ
👉️ Blog
Access for Infrastructure は SSH 含めた Non HTTP アプリの新しい接続方法。今後はコレに置き換わっていくと思います。
2024年11月時点では SSH のみのサポート。
SSH では Access ポリシーによる制御の他に、SSH コマンドログを取ることもできます。
手順にしたがって作成します。
すでに SSH プロキシーを実施している場合 Cloudflare SSH CA(Gateway)が存在するので、新しく作る必要はありません。
接続例
SSH クライアント
Target
で定義された宛先に接続。
warp-cli
で宛先を確認できるのでわかりやすい。
C:\Users\K>warp-cli target list
╭───────────┬──────────┬──────┬────────────────┬──────────────────────┬────────────────────╮
│ Target ID │ Protocol │ Port │ Attributes │ IP (Virtual Network) │ Usernames │
├───────────┼──────────┼──────┼────────────────┼──────────────────────┼────────────────────┤
│ ********* │ SSH │ 22 │ hostname: tun2 │ 172.16.0.253 (*****) │ ubuntu, aduser1 │
╰───────────┴──────────┴──────┴────────────────┴──────────────────────┴────────────────────╯
実装前に接続していたホストと鍵が変わる。
C:\Users\K>ssh aduser1@172.16.0.253
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
認証指定なしで接続が可能。
C:\Users\K>ssh -v aduser1@172.16.0.253 whoami 2>&1 | findstr Authenticated
Authenticated to 172.16.0.253 ([172.16.0.253]:22) using "none".
WARP のログインユーザー以外でも接続可能。
C:\Users\K>ssh ubuntu@172.16.0.253 whoami
ubuntu
C:\Users\K>ssh aduser1@172.16.0.253 whoami
aduser1
Cloudflare
Access > Applications > Policy
SSH user
から消したユーザーは接続できなくなる。
C:\Users\K>ssh -v ubuntu@172.16.0.253
Received disconnect from 172.16.0.253 port 22:14: origin auth failed
Disconnected from 172.16.0.253 port 22
Logs > Access
ログイン失敗のログも残る。
SSH コマンドログ
SSH コマンドログは Access のログに。
Logs > Access
SSH プロキシーとコマンドログ とはダウンロード場所が違うが、ファイル内容の確認方法は同じ。
まとめ
Access for Infrastructure は今後の機能拡張もされていきそうなので、これベースの設計に切り替えたり新設したりするのが良さそうです。
Discussion