SSHポートフォワーディングの解明:ローカル、リモート、ダイナミックトンネルの解説
データベース、Webアプリ、SOCKSプロキシ向けの実用的なコマンドを使って、ローカル、リモート、ダイナミックSSHポートフォワーディングを学びます。
SSHポートフォワーディングを解明:ローカル、リモート、ダイナミックトンネルの解説
SSHポートフォワーディングを使うと、ネットワークサービスを直接公開する代わりに、暗号化されたSSH接続を介してそのサービスにアクセスできます。これは通常、データベース、ダッシュボード、開発サーバーがSSHホストからは到達可能だが、自分のラップトップからは直接アクセスできない場合に使用します。
一般的な3つの形式は、ローカルフォワーディング、リモートフォワーディング、ダイナミックフォワーディングです。これらは似た構文を使用しますが、待受ポートの位置が異なります。
SSHポートフォワーディングの機能
SSHポートフォワーディング(SSHトンネリングとも呼ばれる)は、SSHセッションを介して、あるホストとポートから別のホストとポートへトラフィックをリダイレクトします。宛先は最終接続を行う側で解決されます。ローカルフォワーディングではSSHサーバーがターゲットに接続します。リモートフォワーディングではSSHクライアントがターゲットに接続します。
これにより、以下の利点が得られます:
- セキュリティ:クライアントとターゲットサービス間で暗号化されていないトラフィックを暗号化します。
- アクセス制御:現在地から直接アクセスできないプライベートネットワークやファイアウォールの背後で動作するサービスへのアクセスを許可します。
- ネットワークの橋渡し:異なるネットワークセグメントを安全に接続します。
ローカルポートフォワーディング(-L)
ローカルポートフォワーディングは最も一般的なタイプです。これにより、ローカルマシンのポートから、SSHサーバーを経由してリモートマシンのポートへの接続を転送できます。基本的に、リモートネットワーク上で動作するサービスを、ローカルマシン上で動作しているかのように見せかけます。
仕組み:
- ローカルマシンでSSHクライアントを起動します。
- SSHが待受するローカルポート(
local_port)を指定します。 - ローカルマシンの
local_portへの接続はすべて、SSH接続を介してremote_hostとremote_portに転送されます。
構文:
ssh -L [local_bind_address:]local_port:remote_host:remote_port [user@]ssh_server_host
local_bind_address:バインドするローカルマシンのアドレス(オプション)。省略した場合、クライアント設定で別途指定がない限り、OpenSSHは通常ループバックアドレスにバインドします。local_port:SSHが待受するローカルマシンのポート。remote_host:SSHサーバーが接続するターゲットマシンのホスト名またはIPアドレス。remote_port:トラフィックの転送先となるremote_host上のポート。user@ssh_server_host:接続先のSSHサーバーのユーザー名とホスト名/IPアドレス。
実用的な使用例: リモートサーバーのプライベートIPアドレスで動作するデータベースサーバーへのアクセス。
会社の内部ネットワークからのみアクセス可能なデータベースサーバー(例:192.168.1.100:5432上のPostgreSQL)があるとします。自宅のラップトップからローカルポートフォワーディングを使用してアクセスできます:
ssh -L 5433:192.168.1.100:5432 your_user@your_ssh_server.com
- このコマンドは
your_ssh_server.comに接続します。 - ローカルマシン(デフォルトでは
localhost)のポート5433を開きます。 localhost:5433への接続はすべて、your_ssh_server.comを経由して192.168.1.100:5432に転送されます。
これで、ローカルのデータベースクライアントをlocalhost:5433に接続するように設定でき、トラフィックはリモートデータベースサーバーに安全にトンネリングされます。
ヒント: ssh -Nを使用すると、リモートコマンドを実行せずにトンネルを作成できます。これはバックグラウンドトンネルに便利です。
ssh -N -L 5433:192.168.1.100:5432 your_user@your_ssh_server.com
リモートポートフォワーディング(-R)
リモートポートフォワーディングを使用すると、リモートSSHサーバーのポートからローカルマシンまたはローカルマシンからアクセス可能な別のマシンのポートへの接続を転送できます。これは、ローカルマシンで動作するサービスをリモートサーバーやそのネットワークからアクセス可能にするのに便利です。
仕組み:
- ローカルマシンでSSHクライアントを起動します。
- SSHサーバー上でSSHが待受するリモートポート(
remote_port)を指定します。 - SSHサーバーの
remote_portへの接続はすべて、SSH接続を介してローカルマシンに戻され、指定されたdestination_hostとdestination_portに転送されます。
構文:
ssh -R [remote_bind_address:]remote_port:destination_host:destination_port [user@]ssh_server_host
remote_bind_address:(オプション)待受ポートをバインドするSSHサーバー上のアドレス。デフォルトはlocalhost(つまり、SSHサーバー自身のみがこのポートに接続できる)。リモートネットワーク上の他のマシンからの接続を許可するには、0.0.0.0または*を使用します。remote_port:SSHサーバー上でSSHが待受するポート。destination_host:SSHクライアントが接続するターゲットマシンのホスト名またはIPアドレス(サービスがローカルマシン上にある場合は、多くの場合localhost)。destination_port:トラフィックの転送先となるdestination_host上のポート。user@ssh_server_host:接続先のSSHサーバーのユーザー名とホスト名/IPアドレス。
実用的な使用例: ローカルWebサーバーをリモートネットワークに公開する。
ラップトップでWebアプリケーションを開発しており、会社の内部ネットワークにしかアクセスできない同僚にデモを見せたいとします。また、そのネットワークからアクセス可能なSSHサーバー(your_ssh_server.com)を持っているとします。
ラップトップで次のコマンドを実行します:
ssh -R 8080:localhost:3000 your_user@your_ssh_server.com
- このコマンドは
your_ssh_server.comに接続します。 your_ssh_server.comにポート8080で待受するよう指示します。your_ssh_server.com:8080への接続はすべて、SSHトンネルを介してラップトップ(localhost)のポート3000(Webサーバーが動作しているポート)に転送されます。
これで、同僚はブラウザでhttp://your_ssh_server.com:8080にアクセスすることで、あなたのWebアプリケーションにアクセスできます。トラフィックはブラウザからSSHサーバーへ、トンネルを通ってラップトップへ、そしてWebサーバーへと流れます。
警告: 一般的なOpenSSH設定では、remote_portはSSHサーバー自身からのみ到達可能です。リモートネットワーク上の他のマシンが転送されたポートにアクセスできるようにするには、remote_bind_addressを明示的に0.0.0.0または*に設定し、SSHサーバーがGatewayPorts設定(例:clientspecifiedまたはyes)でそれを許可していることを確認してください。
ssh -R 0.0.0.0:8080:localhost:3000 your_user@your_ssh_server.com
ダイナミックポートフォワーディング(-D)
ダイナミックポートフォワーディングは、ローカルマシン上にSOCKSプロキシを作成します。これは間違いなく最も柔軟なタイプであり、SOCKSプロキシをサポートする任意のアプリケーションをSSH接続経由でトンネリングできます。特定のポートを転送する代わりに、SSHはローカルポートで待受し、SOCKSプロキシサーバーとして動作します。
仕組み:
- ローカルマシンでSSHクライアントを起動します。
- SSHがSOCKSプロキシとして待受するローカルポート(
local_port)を指定します。 - アプリケーション(Webブラウザなど)を、SOCKSプロキシとして
localhost:local_portを使用するように設定します。 - アプリケーションがこのプロキシを介してリクエストを行うと、SSHはトラフィックをSSHサーバーに転送し、SSHサーバーがアプリケーションに代わって最終的な宛先に接続します。
構文:
ssh -D [local_bind_address:]local_port [user@]ssh_server_host
local_bind_address:(オプション)待受SOCKSプロキシポートをバインドするローカルマシンのアドレス。デフォルトはlocalhost。local_port:SSHがSOCKSプロキシとして待受するローカルマシンのポート。user@ssh_server_host:接続先のSSHサーバーのユーザー名とホスト名/IPアドレス。
実用的な使用例: 公共Wi-Fiからの安全なWebブラウジング。
信頼できない公共Wi-Fiネットワークに接続している場合、トラフィックは脆弱です。ダイナミックポートフォワーディングを使用して、すべてのWebブラウジングトラフィックを暗号化されたSSH接続経由で信頼できるサーバーにトンネリングできます。
ラップトップで次のコマンドを実行します:
ssh -D 1080 your_user@your_trusted_server.com
- このコマンドは
your_trusted_server.comに接続します。 - ローカルマシンのポート
1080を開き、SOCKSプロキシとして動作します。
次に、Webブラウザや他のアプリケーションを、localhostのポート1080でSOCKSプロキシを使用するように設定します。アプリケーションにSOCKS5リモートDNSオプションがある場合は、ローカルネットワークでDNSルックアップを行いたくない場合に使用します。
ブラウザのトラフィックはSSHサーバーに送信され、SSHサーバーが宛先サイトに接続します。HTTPSは依然として重要です。SSHトンネルはSSHサーバーまでの経路を保護しますが、その後のすべてのホップを保護するわけではありません。
ヒント: -Dと-Cを組み合わせて圧縮を有効にできます。これは低速なネットワークリンクで有益です。
ssh -C -D 1080 your_user@your_trusted_server.com
高度な考慮事項とベストプラクティス
- SSHサーバー設定(
sshd_config):一部の転送機能にはサーバー側の許可が必要です。トンネルがどこでも待受または接続できると仮定する前に、AllowTcpForwarding、PermitOpen、PermitListen、GatewayPortsを確認してください。 - ファイアウォール:クライアント、サーバー、または中間ネットワーク上のファイアウォールがSSH接続や転送に使用されるポートをブロックする可能性があることを覚えておいてください。必要なポート(通常はSSH自体のポート22)が開いていることを確認してください。
- セキュリティ:ポートフォワーディングはトラフィックを暗号化しますが、トンネルのセキュリティはSSHサーバーのセキュリティに依存します。強力なSSHキーを使用し、パスワード認証を無効にし、SSHサーバーを最新の状態に保ってください。
- 信頼性:スクリプトの場合は、
-o ExitOnForwardFailure=yesを追加して、要求された転送を作成できない場合にSSHが終了するようにします。長時間実行されるトンネルの場合は、autosshや監視対象サービスを検討してください。
まとめ
ラップトップがプライベートなリモートサービスにアクセスする必要がある場合は-Lを使用します。リモートホストがラップトップの近くにあるものにアクセスする必要がある場合は-Rを使用します。信頼できるSSHサーバーを介したSOCKSプロキシが必要な場合は-Dを使用します。バインドは厳密に保ち、サーバーポリシーを確認し、すべてのトンネルを一時的なネットワーク開放として扱ってください。