リバースSSHトンネリングはどのように機能しますか?


350

私がこれを理解しているように、ファイアウォール(デフォルト設定を前提とする)は、以前に対応する発信トラフィックがないすべての着信トラフィックを拒否します。

基づいてssh接続逆転SSHトンネリングが容易に、逆SSHトンネリングは周りの厄介なファイアウォールの制限を取得するために使用することができます。

リモートマシンでシェルコマンドを実行したいと思います。リモートマシンには独自のファイアウォールがあり、追加のファイアウォール(ルーター)の背後にあります。192.168.1.126(または同様のもの)のようなIPアドレスを持っています。私はファイアウォールの内側にいるわけではなく、インターネットから見たリモートマシンのIPアドレス(192.168.1.126アドレスではない)を知っています。さらに、ssh (something)最初にリモートマシンでrootとして実行するように誰かに依頼できます。

誰もが、ファイアウォール(ローカルマシンとリモートマシンのファイアウォール、およびそれらの間の追加のファイアウォール)を回避するためにリバースSSHトンネリングがどのように機能するかをステップごとに説明できますか?

スイッチ(の役割は何か-R-f-L、は-N)?


回答:


403

視覚化を通じてこのようなことを説明するのが大好きです。:-)

SSH接続をチューブと考えてください。大きなチューブ。通常、これらのチューブを介して、リモートコンピューターでシェルを実行します。シェルは仮想端末(tty)で実行されます。しかし、あなたはすでにこの部分を知っています。

トンネルをチューブ内のチューブと考えてください。まだ大きなSSH接続がありますが、-Lまたは-Rオプションを使用すると、その内部に小さなチューブをセットアップできます。

すべてのチューブには始まりと終わりがあります。大きなチューブであるSSH接続は、SSHクライアントで始まり、接続したSSHサーバーで終わります。すべての小さなチューブは、「開始」または「終了」の役割は、あなたが使用したかどうかによって決定されることを除いて、同じエンドポイントを持っている-Lか、-Rそれらを作成するために、(それぞれ)。

(あなたは言っていませんが、ファイアウォールの背後にある「リモート」マシンは、ネットワークアドレス変換(NAT)を使用してインターネットにアクセスできると仮定します。これは重要なことなので、 falseの場合は、この仮定を修正してください。)

トンネルを作成するときに、応答するアドレスとポート、および配信先のアドレスとポートを指定します。この-Lオプションは、トンネルのローカル側(クライアントを実行しているホスト)で応答するようにトンネルに指示します。この-Rオプションは、トンネルにリモート側(SSHサーバー)で応答するように指示します。

sshトンネルの方向

だから...インターネットからファイアウォールの背後にあるマシンにSSHで接続するには、対象のマシンが外部とのSSH接続を開き、-R「エントリ」ポイントが「リモート」側であるトンネルを含める必要があります。彼の接続。

上記の2つのモデルのうち、右側のモデルが必要です。

ファイアウォールで保護されたホストから:

ssh -f -N -T -R22222:localhost:22 yourpublichost.example.com

これは、クライアントに-Rエモートエントリポイントとのトンネルを確立するように指示します。トンネルの遠端のポート22222に接続するものはすべて、実際には「localhostポート22」に到達します。「localhost」はトンネルの出口点(つまり、sshクライアント)から見たものです。

他のオプションは次のとおりです。

  • -f 認証後にsshにバックグラウンドを設定するよう指示するため、トンネルを存続させるためにリモートサーバー上で何かを実行する必要はありません。
  • -NSSH接続が必要であるが、実際にはリモートコマンドを実行したくないという。作成しているのがトンネルのみの場合、このオプションを含めるとリソースが節約されます。
  • -T 疑似tty割り当てを無効にします。これは、対話型シェルを作成しようとしていないため適切です。

パスワードなしのログイン用にDSAまたはRSAキーを設定していない限り、パスワードチャレンジが発生します。

このトンネル/顧客/サーバーだけに設定した使い捨てのアカウント(自分のログインではない)を使用することを強くお勧めします。

ここで、yourpublichostのシェルから、トンネルを介してファイアウォールで保護されたホストへの接続を確立します。

ssh -p 22222 username@localhost

あなたはおそらくこのホストを一度もヒットしたことがないので、ホストキーのチャレンジを取得します。次に、usernameアカウントのパスワードチャレンジを取得します(パスワードなしのログイン用のキーを設定していない場合)。

このホストに定期的にアクセスする場合は、~/.ssh/configファイルに数行を追加することでアクセスを簡素化することもできます。

host remotehostname
    User remoteusername
    Hostname localhost
    Port 22222

調整remotehostnameremoteusernameて合わせます。このremoteusernameフィールドは、リモートサーバー上のユーザー名と一致する必要がありますが、remotehostname任意のホスト名を使用できます。解決可能なものと一致する必要はありません。

非ローカルホスト IPでリバースエンドポイントを公開するには、この投稿をチェックしてください)


2
ssh -Dはどうですか。同じ方法で説明してください。
BigSack 14年

6
SOCKSプロキシは、トンネルとは異なります。それらの使用方法について質問がある場合は、お問い合わせください。
ゴティ14年

12
サーバー、クライアント、ローカルマシン、リモートマシン、ホスト、yourpublichost、localhost、remotehostnameという用語の使用法が緩いため、この説明を追うのは非常に困難です。これらすべての緩い未定義の用語では、誰かがこれをセットアップするために最大8台のコンピューターを必要とすると考えられます。他のすべての面で非常に良い説明に思えるので、私はこれを述べます。用語を減らして定義してください。
Rucent88

4
@ Rucent88、どのような削減が可能かはわかりません。クライアントはサーバーへの接続を確立します。これは、ネットワーキングの世界全体で共通の用語です。ローカルマシンとリモートマシンは自明のようです。ドキュメントを読んだ後、SSHやUNIXの一般的な用語について混乱している場合、ここで質問に答えてくれる人を見つけるのに問題はないでしょう。
ゴティ

9
@ghotiローカルマシンとリモートマシンは相対的であるため、紛らわしいです。職場に座っているとき、私の自宅のコンピューターはリモートであり、自宅に座っているとき、職場のコンピューターはリモートです。トンネリングと言えば、サーバーとクライアントも混乱します。たとえば、ssh -Rを使用して職場から自宅に接続する場合。localhostに接続して、自宅のコンピューターから仕事に接続します。したがって、ソケットの観点から見ると、サーバーはホームコンピューターそのものです。しかし、論理的には仕事用コンピューターに接続しました。紛らわしいです。
カルマリウス

357

私はいくつかのスケッチを描きました

ssh tunnelコマンドが入力されるマシンは、»your host«と呼ばれます

ローカルから始まるsshトンネル


リモートから開始するsshトンネル

前書き

  1. 地元: -L Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side.

    ssh -L sourcePort:forwardToHost:onPort connectToHost意味:にsshで接続しconnectToHost、すべての接続試行を、マシンから到達可能なマシンのローカル sourcePort toポートonPortに転送します。forwardToHostconnectToHost

  2. リモート: -R Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side.

    ssh -R sourcePort:forwardToHost:onPort connectToHost意味:sshでに接続しconnectToHost、すべての接続試行をリモート sourcePortに転送します。これは、ローカルマシンから到達可能なonPortマシン上のポートに転送さforwardToHostれます。

追加オプション

  • -f 認証後にsshにバックグラウンドを設定するよう指示するため、トンネルを存続させるためにリモートサーバー上で何かを実行する必要はありません。
  • -NSSH接続が必要であるが、実際にはリモートコマンドを実行したくないという。作成しているのがトンネルのみの場合、このオプションを含めるとリソースが節約されます。
  • -T 疑似tty割り当てを無効にします。これは、対話型シェルを作成しようとしていないため適切です。

あなたの例

3番目の画像は、このトンネルを表しています。しかし、「ホスト」という青いコンピューターは、誰かがsshトンネルを開始するコンピューター、この場合はファイアウォールで保護されたコンピューターを表します。

だから、あなたのマシンへのsshトンネル接続を開始するように誰かに頼んでください。コマンドは基本的に次のようになります

ssh -R 12345:localhost:22 YOURIP

これでトンネルが開きました。次のコマンドを使用して、トンネル経由でssh経由でファイアウォールで保護されたマシンに接続できるようになりました

ssh -p 12345 localhost

これはlocalhostport 12345であなたの(あなたのマシン)に接続しますが、ポート12345はトンネルを通してファイアウォールのあるコンピューターのローカルホストのポート22(すなわちファイアウォールのあるコンピューター自体)に転送されます。


9
素晴らしい答えです!これをプレゼンテーションで使用します。
イザヤターナー14年

4
ありがとうございました。どういたしまして。ベクトル画像(svgまたはpdf)が必要な場合は、私にメッセージを書いてください。
エリック14年

1
@erik、これらの画像をどのように描きましたか?
パセリエ

31
ああ、マニュアルページにこのような説明があればいいのに!ありがとう!
ルーカスポッタースキー

30
あのね ?テキストの説明を読む必要さえありませんでした。すごい仕事 !
deppfx

21

sshトンネリングは、既に確立されているssh接続を使用して追加のトラフィックを送信することにより機能します。

リモートサーバーに接続する場合、通常は通常のユーザーインタラクション用に1つのチャネル(またはSTDIN / STDOUT / STDERRを個別に検討する場合は3つのチャネル)のみがあります。ローカルまたはリモートのsshプロセスはいつでも、既存の接続で追加のチャネルを開くことができます。これらのチャネルは、トンネルトラフィックを送受信します。トラフィックを送受信するとき、sshプロセスは単に「このトラフィックはチャネルfoobar用です」と言います。

基本的には次のように機能します。

  1. sshにポートXXXXでリッスンを開始し、受信したトラフィックはすべてトンネリングするように指示し、ポートZZZZでYYYYに設定します。
  2. ローカルsshは、ポートXXXXでリッスンを開始します(通常はon 127.0.0.1ですが、変更できます)。
  3. 一部のアプリケーションは、ローカルマシンのポートXXXXへの接続を開きます。
  4. ローカルsshは、リモートsshへのチャネルを開き、「このチャネル上のすべてのトラフィックはYYYY:ZZZZに行きます」と言います。
  5. リモートsshはYYYY:ZZZZに接続し、「OK、チャンネルは開いています」を返信します
  6. これで、ローカルマシンのポートXXXXへの接続に沿って送信されるトラフィックは、sshによってYYYY:ZZZZにプロキシされます。

このプロセスは、フォワードトンネリングとリバーストンネリングの両方でまったく同じです(上記の手順で「ローカル」と「リモート」を入れ替えるだけです)。どちらの側でもトンネルを開始できます。sshを最初に起動するときである必要はありません。sshが既に実行されている間にトンネルを開くことができます(ESCAPE CHARACTERS特にを参照~C)。

役割について-R-f-L、そして-N、あなたは本当にただのmanページを参照してくださいする必要があり、それはあなたに最高の可能な説明を提供します。しかし、私は言及-R-Lます。
-R接続をリッスンするようにリモートsshに指示し、ローカルsshは実際の宛先に接続する必要があります。-L接続をリッスンするようにローカルsshに指示し、そのリモートsshは実際の宛先に接続する必要があります。

注意してください、これは非常に粗雑な説明ですが、何が起こっているかを知るのに十分な情報を提供する必要があります


16

これはSSHマニュアル、特に-L(ローカル)と-R(リモート)の違いで説明されています。


-L

-L [bind_address:]port:host:hostport

ことを指定しますローカル(クライアント)ホスト上の特定のポートがリモート側で指定されたホストとポートに転送されます

これは、オプションで指定されたbind_addressにバインドされたローカル側のポートをリッスンするソケットを割り当てることで機能します。

このポートへの接続が確立されるたびに、接続はセキュアチャネルを介して転送され、リモートマシンからポートへのhosthostport接続が確立さます

次の例では、ポート1234を使用してクライアントサーバー127.0.0.1localhost)からリモートサーバーにIRCセッションをトンネリングしますserver.example.com

$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10

注:-fオプションはsshをバックグラウンドにし、リモートコマンドsleep 10を指定して、トンネリングされるサービスを開始する時間を許可します。

例:

ssh `-N` -L 22000:localhost:11000 remote.server.com
  • -N 接続した後、そこでハングするだけです(シェルプロンプトは表示されません)。

    リモートコマンドを実行しないでください。

  • -L 22000接続はあなたの個人的な、のポート22000に発信しますLの OCALマシン

  • localhost:11000- remote.server.comトンネルのもう一方の端がlocalhostポートであることを確認します11000

ssh -N -L 22000:192.168.1.2:11000 remote.server.com

出典:sshトンネリングの図解ガイド、チュートリアル、ハウツー


-R

-R [bind_address:]port:host:hostport

ことを指定する遠隔(サーバ)ホスト上の特定のポートがローカル側で指定されたホストおよびポートに転送されます

これportは、リモート側でリッスンするソケットを割り当てることにより機能し、このポートへの接続が確立されるたびに、セキュアチャネルを介して接続が転送され、ローカルマシンからポートに接続さhostますhostport

例:

ssh -N -R 22000:localhost:11000 remote.server.com
  • -N 接続した後、そこでハングするだけです(シェルプロンプトは表示されません)。

    リモートコマンドを実行しないでください。

  • -R22000接続はR emoteコンピューターのポート22000 (この場合、remote.server.com)で開始されます。

  • localhost:11000あなたの個人的なローカルコンピュータは、トンネルの反対側がlocalhostポートであることを確認します11000

ssh -N -R 22000:localhost:11000 remote.server.com

出典:sshトンネリングの図解ガイド、チュートリアル、ハウツー


6
耳と口によって、誰が話しているのか、誰が聞いているのかがはっきりとわかります。
-Thufir

1
あなたのイラストが大好きです!
mcantsin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.