🐙

SSH に VPN 箱なんてジャマ ... 2018 - 2024

2024/11/04に公開

はじめに

グローバル IP アドレスを持たないサーバーへの Clodflare を介した SSH 接続について新しい方法が出てました。従来の方法含め、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-TunnelPrivate 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