第6章 ポート転送(SSHトンネル)
ポート転送(SSH トンネル)とは
ポート転送(ポートフォワーディング)は、SSH の暗号化された通信経路(トンネル)の中に別の TCP 通信を通す技術です。
この技術を使うことで、インターネットに直接公開されていない社内 Web 画面やプライベートなデータベース(MySQL や PostgreSQL など)に対し、手元の PC から安全にアクセスできるようになります。
SSH のポート転送には、通信の向きや用途に応じて以下の 3 種類が存在します。
-
ローカルポート転送(-L):
手元 PC のポートへの通信を、SSH サーバ経由で目的のリモートサーバへ転送します。
-
リモートポート転送(-R):
リモートサーバのポートへの通信を、SSH サーバ経由で手元のローカル PC へ転送します。
-
ダイナミックポート転送(-D):
手元 PC を SOCKS プロキシ化し、任意の宛先への通信を SSH サーバ経由で中継します。
1. ローカルポート転送(-L)
リモートネットワーク内に存在する非公開サービスへアクセスする最も代表的な手法です。
[手元 PC (localhost:8080)] ===(SSH暗号化トンネル)===> [SSH サーバ] ───> [社内Web (192.168.1.200:80)]
コマンド構文
ssh -L <ローカルポート>:<転送先ホスト>:<転送先ポート> <ユーザー名>@<SSHサーバ>
具体例:リモートのデータベースに接続する
外部から接続できないリモートサーバ上の PostgreSQL(ポート 5432)に接続したい場合:
ssh -L 15432:localhost:5432 user@ssh-server
このコマンドを実行している間、手元 PC の localhost:15432 に接続するだけで、自動的にリモートサーバ上の localhost:5432 へパケットが暗号化転送されます。手元の GUI データベースクライアントから安全に操作できます。
2. リモートポート転送(-R)
手元のローカル PC で動作している開発用サーバーなどを、離れたリモートサーバ側からアクセス可能にする手法です。
[リモートクライアント] ───> [SSH サーバ (:8080)] ===(SSH暗号化トンネル)===> [手元 PC (localhost:3000)]
コマンド構文
ssh -R <リモートポート>:<ローカルホスト>:<ローカルポート> <ユーザー名>@<SSHサーバ>
具体例:手元で開発中の Web アプリを共有する
手元の PC で動いている Node.js 開発サーバー(ポート 3000)を、リモートサーバのポート 8080 で待ち受けて公開する場合:
ssh -R 8080:localhost:3000 user@ssh-server
リモートサーバ上で curl http://localhost:8080 を実行すると、手元 PC のポート 3000 で動作する Web アプリが応答します。
▸ リモートポートを外部ホストに公開する場合(GatewayPorts)
デフォルトでは、リモート転送されたポートはリモートサーバ自身のループバック(127.0.0.1)にのみバインドされます。外部の第三者マシンからもアクセス可能にするには、サーバ側の /etc/ssh/sshd_config で GatewayPorts yes を有効化する必要があります。
3. ダイナミックポート転送(-D)
手元 PC の指定ポートを SOCKS5 プロキシサーバーとして機能させます。 Web ブラウザ等のプロキシ設定をこれに向けることで、ブラウザからのすべてのアクセスがあたかも SSH サーバからアクセスしているかのように振る舞います。
コマンド構文
ssh -D <ローカルポート> <ユーザー名>@<SSHサーバ>
具体例:SOCKS プロキシの起動
ssh -D 1080 user@ssh-server
手元 PC のブラウザ設定で SOCKS5 プロキシとして 127.0.0.1:1080 を指定すると、安全でないフリー Wi-Fi 環境からでも、すべてのブラウジング通信を SSH 暗号化トンネル経由で行うことができます。
トンネル専用の便利なオプション(-N と -f)
ポート転送のトンネルを維持するだけで、リモートサーバのシェルプロンプトを操作する必要がない場合は、以下のオプションを組み合わせます。
-N: リモートコマンドを実行せず、ポート転送のみを行う。-f: 認証完了後、直ちにプロセスをバックグラウンドへ移行する。
# バックグラウンドでローカルポート転送を常駐
ssh -f -N -L 15432:localhost:5432 user@ssh-server
バックグラウンド接続を終了したい場合は、kill コマンドで対象プロセスの PID を停止します。
.ssh/config によるポート転送の自動化
コマンドラインで長い引数を指定する代わりに、~/.ssh/config に転送定義をあらかじめ記述しておくことができます。
# 社内 DB トンネル用定義
Host tunnel-db
HostName 203.0.113.10
User developer
IdentityFile ~/.ssh/id_ed25519_dev
IdentitiesOnly yes
# ローカル 15432 をリモートの 5432 に転送
LocalForward 15432 localhost:5432
# SOCKS プロキシ用定義
Host socks-proxy
HostName 203.0.113.20
User proxy-user
IdentityFile ~/.ssh/id_ed25519_proxy
IdentitiesOnly yes
# ローカル 1080 を SOCKS プロキシ化
DynamicForward 1080
これにより、単に ssh tunnel-db や ssh -f -N tunnel-db と実行するだけで、意図したポート転送が即座に開始されます。