ローカルおよびリモートSSHポートフォワーディングによるトンネリングの実装

SSHポートフォワーディングを使用して、安全なネットワークアクセスとファイアウォールの通過を実現します。この包括的なガイドでは、ローカル(`-L`)とリモート(`-R`)の両方のSSHトンネリング技術の実践的な実装について詳しく説明します。必須の構文を学び、リモートサービスへのアクセスとローカルサービスの公開の重要な違いを理解し、データベース接続の保護や開発環境の共有などのタスクの明確な例を確認します。キーベースの認証を使用して、永続的で安全なバックグラウンドトンネルを作成するための重要なベストプラクティスが含まれています。

ローカルおよびリモートSSHポートフォワーディングによるトンネリングの実装

SSHポートフォワーディングは、ファイアウォール、プライベートサブネット、または厄介なベンダーネットワークが単純な経路をブロックするまで忘れがちなツールの1つです。そして、それが最も迅速でクリーンな修正方法になります。踏み台ホストを経由してデータベースにアクセスしたり、ラップトップからプライベート管理ページをテストしたり、ローカル開発サーバーをラップトップに直接アクセスできないマシンに公開したりするために使用できます。

基本的な考え方は単純です。SSHは接続の一方の側でリッスンポートを開き、暗号化されたSSHセッションを介してトラフィックを他方の側の宛先に運びます。人々がつまずくのは方向です。-Lを使用したローカルフォワーディングでは、マシンがSSHサーバーの近くにあるものに到達できるようになります。-Rを使用したリモートフォワーディングでは、SSHサーバーの近くにあるものがマシンの近くにあるものに到達できるようになります。

ローカルフォワーディング:リモートサービスをラップトップに持ち込む

必要なサービスがSSHサーバーから到達可能だが、ワークステーションからは到達できない場合にローカルフォワーディングを使用します。

ssh -L 15432:db.internal.example:5432 [email protected]

これが接続されると、ラップトップは127.0.0.1:15432でリッスンします。psql、DBeaver、またはアプリケーション設定をそのローカルポートに向けると、SSHはトラフィックをbastion.example.comに送信し、踏み台はdb.internal.example:5432への接続を開きます。

コマンドを左から右に読みます:

ローカルマシンのポート : SSHサーバーから見た宛先ホスト : 宛先ポート

この「SSHサーバーから見た」という詳細が重要です。データベースがプライベートネットワーク内でのみdb.internal.exampleという名前である場合、ラップトップがその名前を解決する必要はありません。踏み台が解決します。データベースが踏み台上のlocalhostでのみリッスンしている場合は、代わりにこれを使用します:

ssh -L 15432:127.0.0.1:5432 [email protected]

リッスンポートがワークステーション上にあるため、ローカルフォワーディングは通常、より安全なデフォルトです。デフォルトでは、OpenSSHはローカルフォワーディングされたポートをループバックインターフェースにバインドするため、Wi-Fiやオフィスネットワーク上の他のマシンはトンネルを使用できません。明示的に指定することもできます:

ssh -L 127.0.0.1:15432:db.internal.example:5432 [email protected]

本当にトンネルを他のホストと共有するつもりでない限り、0.0.0.0にバインドすることは避けてください。次のようなコマンドは、ラップトップのポート15432に到達できる誰でもプライベートデータベースへのプロキシとしてラップトップを使用できるようにします:

ssh -L 0.0.0.0:15432:db.internal.example:5432 [email protected]

これはラボでは役立つかもしれませんが、通常のワークステーションで必要なことはほとんどありません。

リモートフォワーディング:サーバーを介してローカルサービスを公開する

リモートフォワーディングはリッスン側を反転させます。サービスがマシン上で実行されているが、SSHサーバーの近くにある誰かまたは何かがそれに到達する必要がある場合に使用します。

ssh -R 18080:127.0.0.1:3000 [email protected]

これにより、public.example.comはポート18080でリッスンするよう要求されます。そのポートへの接続は、SSHを介してラップトップの127.0.0.1:3000に戻されます。これは、Webhookレシーバーをテストしたり、一時的なデモを共有したり、ラップトップに直接コールバックできないステージングシステムからのコールバックをデバッグしたりする場合に便利です。

よくある驚きが1つあります。リモートフォワーディングされたポートは、デフォルトでSSHサーバーのループバックにバインドされることがよくあります。つまり、curl http://127.0.0.1:18080public.example.comで実行すると機能しますが、ブラウザからのhttp://public.example.com:18080は機能しない可能性があります。

リモートフォワーディングされたポートを他のマシンから到達可能にするには、SSHサーバーがそれを許可する必要があります。/etc/ssh/sshd_configでは、関連する設定は通常次のとおりです:

GatewayPorts clientspecified

その後、パブリックバインドを要求できます:

ssh -R 0.0.0.0:18080:127.0.0.1:3000 [email protected]

これは慎重に使用してください。サーバーを介してローカルサービスを公開しています。その前にファイアウォールを配置し、高いランダムポートを使用し、管理ツール、開発データベース、または認証されていないアプリをインターネットに公開しないでください。

トンネルを退屈で信頼性の高いものに保つ

長時間実行されるトンネルの場合、通常はリモートホストでシェルを必要としません:

ssh -N -L 15432:db.internal.example:5432 [email protected]

-Nは「リモートコマンドを実行しない」ことを意味します。トンネルがNAT、VPN、またはアイドルTCPセッションをドロップするクラウドロードバランサーを通過する場合は、キープアライブを追加します:

ssh -N \
  -o ServerAliveInterval=30 \
  -o ServerAliveCountMax=3 \
  -L 15432:db.internal.example:5432 \
  [email protected]

無人使用の場合は、裸のssh -fコマンドよりも、systemdユーザーサービス、autossh、またはプロセススーパーバイザーを優先してください。-fによるバックグラウンド実行は機能しますが、起動の失敗や古いトンネルに気づきにくくなります。

ssh -fN -L 15432:db.internal.example:5432 [email protected]

-fNを使用する場合は、最初に-fなしで同じコマンドをテストしてください。パスワードプロンプト、不明なホストキープロンプト、ポートの競合は、フォアグラウンドで診断する方がはるかに簡単です。

トラブルシューティングチェックリスト

トンネルが接続されているがアプリケーションがまだ失敗する場合は、推測する代わりに各ホップを確認してください。

まず、ローカルリスナーが存在することを確認します:

ss -ltnp | grep 15432

次に、SSHサーバーから宛先をテストします:

ssh [email protected] 'nc -vz db.internal.example 5432'

それが失敗した場合、SSHフォワーディングが問題ではありません。踏み台がサービスに到達できない、名前がそこで解決されない、セキュリティグループがポートをブロックしている、またはサービスが間違ったインターフェースにバインドされています。

リスナーが起動しない場合、ローカルポートがすでに使用中である可能性があります:

lsof -iTCP:15432 -sTCP:LISTEN

リモートフォワーディングがremote port forwarding failedのようなメッセージで失敗した場合、サーバーがTCPフォワーディングをブロックしている可能性があります。sshd_configAllowTcpForwardingを確認し、要求されたポートがすでに使用されているかどうかを確認してください。

維持する価値のあるセキュリティ習慣

キーベースの認証を使用し、トンネルに使用するアカウントを制限してください。専用のトンネルユーザーの場合、制限されたシェルアクセス、ファイアウォールルール、および必要な方向に応じてPermitOpenPermitListenなどのSSHオプションを組み合わせることができます。これらの制御により、便利なトンネルが広範なネットワークアクセスに変わるのを防ぎます。

トンネルには、コマンドだけでなく、意図に基づいてメモやランブックに名前を付けてください。「踏み台を経由した本番レポートレプリカへのラップトップ15432」は、シェル履歴の謎のssh -L行よりも監査が容易です。

ローカルフォワーディングは内部に到達するのに役立ちます。リモートフォワーディングは、他の人があなたに向かって到達できるようにします。この区別が明確になれば、ほとんどのSSHトンネリングの問題は、どの側がリッスンしているか、どの側が宛先を解決するか、そしてそれらの間にどのファイアウォールがあるかを確認する問題になります。

実際に見られるいくつかのパターン

一般的な本番パターンは、データベースメンテナンストンネルです。プライベートサブネットにレポートレプリカがあり、厳格なSSHアクセスを持つ踏み台ホストがあり、ラップトップにアナリストツールがあります。ローカルフォワーディングがきれいに適合します:

ssh -N -L 127.0.0.1:15432:reporting-db.internal:5432 [email protected]

ラップトップ上のアプリケーションは、プライベートデータベースホスト名ではなく、127.0.0.1を使用する必要があります。ツールがデータベースホストに対するSSLホスト名検証を要求する場合、データベースホスト名で接続し、ローカルホストエントリを追加するか、適切なSSLモードでクライアントを設定する必要があるかもしれません。トンネルはTCPバイトを移動するだけであり、データベースプロトコルの詳細を書き換えることはありません。

別のパターンは、一時的なWebhookレシーバーです:

ssh -N -R 127.0.0.1:19090:127.0.0.1:9090 [email protected]

このバージョンでは、フォワーディングされたポートは意図的にゲートウェイ自体からのみ使用可能です。その後、ゲートウェイ上のステージングサービスを設定してhttp://127.0.0.1:19090/hookを呼び出すことができます。これは、ポートをネットワーク全体に公開するよりも安全です。

短い公開デモの場合は、ファイアウォールルールを追加した後にのみパブリックバインドを使用します:

ssh -N -R 0.0.0.0:19090:127.0.0.1:3000 [email protected]

次に、ゲートウェイを制限します:

sudo ufw allow from 203.0.113.40 to any port 19090 proto tcp

この制限がないと、ゲートウェイに到達できる誰でもフォワーディングされたサービスを試すことができます。

SSHトンネリングが解決しないこと

SSHフォワーディングは、サービス認証の代わりにはなりません。データベースがパスワードなしでローカル接続を受け入れる場合、トンネルはその弱い信頼境界を意図したよりも遠くまで拡張する可能性があります。ローカル開発アプリにログインページがない場合、リモートフォワーディングはそれをそのまま公開できます。

また、不安定な宛先を信頼性の高いものにすることもありません。踏み台が内部名を解決できない場合、サービスがダウンしている場合、またはセキュリティグループがパスをブロックしている場合、アプリケーションが失敗している間もトンネルは正常に確立される可能性があります。そのため、SSHサーバーからのテストが非常に役立ちます。

最後に、トンネルは忘れられがちです。共有ジャンプホスト上の古いトンネルは、予期しないポートを開いたままにする可能性があります。長時間実行されるものについては、明確な名前、所有者、および再起動ポリシーを持つサービスファイルにコマンドを配置してください。一時的なものについては、作業が完了したら閉じ、ss -ltnpでリスナーが消えたことを確認してください。