🐙

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-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