SSHトンネル実践ガイド: ローカルおよびリモートのポートフォワーディング
(labs.iximiuz.com)要約概要
- SSHトンネルは、外部から直接アクセスできないサービスに安全に接続したり、内部サービスを外部へ一時的に公開したりするための技術である。
- SSHポートフォワーディングは大きく ローカルフォワーディング、リモートフォワーディング、動的ローカルフォワーディング、動的リモートフォワーディング に分けられる。
-LはローカルのSSHクライアントがポートを開き、-RはリモートのSSHサーバーがポートを開く。- Bastion Hostを活用すると、SSHサーバー自体だけでなく、そのサーバーがアクセス可能な別のプライベートネットワーク上のサービスにも接続できる。
- 動的フォワーディングは特定の宛先を固定せず、SOCKSプロキシを作成して複数のホストとポートにアクセスできるようにする。
- リモートフォワーディングを外部ネットワークに公開するには、SSHサーバーの
GatewayPorts設定を確認する必要がある。
序論
SSHトンネルの目的
-
SSHはリモートコマンド実行だけでなく、ネットワークトラフィックを暗号化して転送するトンネル機能も提供する。
-
別途VPNや専用プロキシプログラムを使わなくても、標準のSSHコマンドだけでプライベートネットワークへのアクセスやサービス公開が可能である。
-
代表的な活用例は次のとおり。
- 公開サーバーを経由して内部VPCサービスへ接続
- リモート開発サーバーのローカルポートをユーザーPCのブラウザーで開く
- 自宅やプライベートネットワークのサービスを外部へ一時公開
- ローカルブラウザーのデバッグポートをリモート開発エージェントに接続
-
SSHトンネルを理解する際は、次の2点を区別する必要がある。
- どの装置が新しいポートを開いて待ち受けるのか
- トンネルを通過したトラフィックが、どの装置の視点で宛先へ接続するのか
本論
ローカルフォワーディングはリモートサービスをローカルへ接続する
- ローカルポートフォワーディングは、リモートサーバー、またはリモートサーバーがアクセスできるサービスを、ユーザーPCのローカルポートへ接続する方式である。
- 基本的なコマンド構成は次のとおり。
ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr
-
SSHクライアントがユーザーPCの
local_portで接続を待ち受ける。 -
そのポートに入ってきたトラフィックはSSHトンネルを経由して
remote_addr:remote_portへ転送される。 -
最終宛先への接続は、SSHサーバーが置かれたネットワークの視点で行われる。
-
主な活用例は次のとおり。
- リモートのMySQL、PostgreSQL、Redisへの接続
- プライベートネットワーク内でのみ公開されているWebアプリケーションへの接続
- サーバーの外部インターフェースに公開していないコンテナポートへの接続
Bastion Hostはプライベートネットワークアクセスを中継する
-
remote_addrとSSH接続先であるsshd_addrは同じ装置である必要はない。 -
SSHサーバーが別の内部サービスへアクセスできるなら、そのサーバーを中継地点として使える。
-
このような中継サーバーは Bastion Host または Jump Host と呼ばれる。
-
一般的な接続構成は次のとおり。
- ユーザーPCから公開されたBastion HostへSSH接続
- Bastion HostがアクセスできるVPC内部サービスへトラフィックを転送
-
これにより、外部公開されていないデータベース、検索クラスター、内部APIなどに接続できる。
リモートフォワーディングはローカルサービスをリモートへ公開する
- リモートポートフォワーディングは、ユーザーPCや内部ネットワーク上のサービスを、外部SSHサーバーのポートに接続する方式である。
- 基本的なコマンド構成は次のとおり。
ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr
-
リモートSSHサーバーが
remote_portを開いて接続を待ち受ける。 -
そのポートに入ってきたトラフィックはSSHトンネルを通じて、SSHクライアント側の
local_addr:local_portへ転送される。 -
主な活用例は次のとおり。
- ノートPC上で動作中の開発サーバーを外部デモ用に公開
- ホームラボのサービスをインターネットからアクセスできるように接続
- ローカルブラウザーのデバッグポートをリモート開発環境へ提供
外部公開にはGatewayPorts設定が必要である
- デフォルト設定では、リモートフォワーディングのポートはSSHサーバーの
localhostにのみバインドされることがある。 - この場合、そのサービスにはリモートサーバー内部からはアクセスできるが、外部からはアクセスできない。
- リモートサーバーのグローバルIP経由でアクセスできるようにするには、
sshd_configで次の設定を確認する必要がある。
GatewayPorts yes
- この設定ではポートを外部インターフェースへ公開できるため、ファイアウォールやアクセス制御も併せて適用すべきである。
- 開発サービスをパブリックインターネットへ直接公開すると、認証されていないアクセスや攻撃の可能性が高まる。
ローカル装置はプライベートネットワークのJump Hostになり得る
-
リモートフォワーディングの宛先は、SSHクライアントが実行される装置そのものに限定されない。
-
ユーザーPCが自宅ネットワーク内の別サーバーへアクセスできるなら、その内部サーバーのポートもリモートSSHサーバー経由で公開できる。
-
このとき、ユーザーPCは次の2つのネットワークをつなぐ中継装置になる。
- 自宅ネットワークまたはプライベート開発ネットワーク
- 公開SSHゲートウェイサーバー
-
これを利用すると、インターネットに直接接続されていないホームサーバーや内部開発サーバーのサービスにも外部からアクセスできる。
動的ローカルフォワーディングはローカルSOCKSプロキシを作る
- 通常のローカルフォワーディングは、1つのローカルポートを1つの宛先に固定する。
- 動的ローカルフォワーディングはSSHクライアント上にSOCKSプロキシを作成する。
- 基本的なコマンド構成は次のとおり。
ssh -D [local_addr:]local_port [user@]sshd_addr
-
ユーザーPCの指定ポートでSOCKSプロキシが動作する。
-
SOCKSをサポートするアプリケーションは、接続のたびに異なる宛先アドレスとポートを指定できる。
-
実際の宛先接続は、リモートSSHサーバーのネットワークの視点で行われる。
-
1本のSSH接続でリモートのプライベートネットワーク上にある複数サービスへアクセスできる点が、固定型ローカルフォワーディングとの違いである。
-
主な活用例は次のとおり。
- Bastion Host経由で複数の内部APIを呼び出す
- プライベートネットワーク内のWebアプリケーションを探索する
- 1台のEC2インスタンス経由で複数のVPCエンドポイントへ接続する
動的リモートフォワーディングはリモートSOCKSプロキシを作る
-Rオプションで固定宛先を省略すると、リモートSSHサーバー上にSOCKSプロキシを作成できる。- 基本的なコマンド構成は次のとおり。
ssh -R [bind_address:]port [user@]gateway_addr
- リモートゲートウェイサーバーが指定ポートでSOCKS接続を待ち受ける。
- プロキシに入ってきたリクエストはSSHトンネルを経由してクライアント側へ転送される。
- 最終宛先への接続は、SSHクライアントが存在するネットワークの視点で行われる。
- これを利用すると、リモートサーバーからユーザーPCがアクセス可能な自宅ネットワーク全体やプライベートネットワークへアクセスできる。
- 動的リモートフォワーディングには、クライアント側でOpenSSH 7.6以降が必要である。
- リモートSOCKSプロキシを外部インターフェースに公開するには、通常のリモートフォワーディングと同様に
GatewayPorts設定が必要である。
バックグラウンド実行オプションはトンネルのみを維持する
- SSH接続後にコマンドを実行せず、ポートフォワーディングだけを維持したい場合は
-Nオプションを使う。 - トンネルをバックグラウンドに移すには
-fオプションも併用できる。 - 種類ごとの例は次のとおり。
ssh -f -N -L ...
ssh -f -N -R ...
ssh -f -N -D ...
- 自動化や長時間運用の環境では、トンネル終了、再接続、障害検知の仕組みも別途用意する必要がある。
コマンドはポートを開く場所で区別する
ssh -LはローカルのSSHクライアントが新しいポートを開く。ssh -RはリモートのSSHサーバーが新しいポートを開く。ssh -DはローカルのSSHクライアント上にSOCKSプロキシを作る。- 宛先を省略した
ssh -RはリモートのSSHサーバー上にSOCKSプロキシを作る。 - コマンドを覚えるための基本ルールは次のとおり。
-L = local:remote
-R = remote:local
- コロンの左側にあるアドレスとポートが、新たに開かれるリスニングポイントである。
localはSSHクライアント自身、またはクライアントがアクセス可能な内部装置を意味する場合がある。remoteはSSHサーバー自身、またはサーバーがアクセス可能な別の内部装置を意味する場合がある。
結論
SSHトンネルはアクセス方向に応じて選ぶ
-
リモートサービスを自分のPCで利用したいなら、ローカルフォワーディング
-Lを使う。 -
自分のPCや内部サービスをリモートサーバー側へ公開したいなら、リモートフォワーディング
-Rを使う。 -
リモートネットワーク上の複数の宛先へ柔軟にアクセスしたいなら、動的ローカルフォワーディング
-Dを使う。 -
クライアント側ネットワーク全体をリモートゲートウェイから柔軟にアクセス可能にしたいなら、宛先を省略した動的リモートフォワーディング
-Rを使う。 -
SSHトンネルを設計するときは、次の項目を優先的に確認すべきである。
- 新しいポートを開く必要がある場所
- 最終宛先へアクセスできる装置
GatewayPorts、ファイアウォール、SSHアクセス権限の設定- 外部公開によって生じ得るセキュリティリスク
-
核心となる判断基準は サービスをどちら側に見せるのか、そしてどの装置が宛先へ実際にアクセスできるのか である。
まだコメントはありません。