SSHを介したデータのトンネリングはとても簡単です。
ssh -D9999 [email protected]
localhost
のポート9999をexample.com
へのトンネルとして設定しますが、もっと具体的なニーズがあります。
localhost
に取り組んでいますHost1
はlocalhost
にアクセス可能ですHost2
はHost1
からの接続のみを受け入れますlocalhost
からHost2
へのトンネルを作成する必要があります事実上、私は「マルチホップ」SSHトンネルを作成したいと思います。これどうやってするの?理想的には、スーパーユーザーにならずにこれを行いたいです。 どれか マシンの。
基本的に3つの可能性があります。
localhost
からHost1
へのトンネル:
ssh -L 9999:Host2:1234 -N Host1
上記のように、Host1
からHost2
への接続は保護されません。
localhost
からHost1
へ、およびHost1
からHost2
へのトンネル:
ssh -L 9999:localhost:9999 Host1 ssh -L 9999:localhost:1234 -N Host2
これはlocalhost
からHost1
へのトンネルとHost1
からHost2
への別のトンネルを開きます。ただし、9999
からHost2:1234
へのポートは、Host1
上の誰でも使用できます。これは問題になるかどうかわからない。
localhost
からHost1
へとlocalhost
からHost2
へのトンネル:
ssh -L 9998:Host2:22 -N Host1
ssh -L 9999:localhost:1234 -N -p 9998 localhost
これにより、localhost
からHost1
へのトンネルが開き、Host2
上のSSHサービスを使用することができます。それから2番目のトンネルが最初のトンネルを通してlocalhost
からHost2
へ開かれます。
Host1
からHost2
への接続を保護する必要がある場合は、通常、オプション2を使用します。オプション3は、Host2
からのみアクセス可能なHost2
上のサービスにアクセスする場合に便利です。
SSH用のProxyCommand
設定ディレクティブの使用を説明する 優れた答えがあります 。
これをあなたの~/.ssh/config
に追加してください(詳細はman 5 ssh_config
を見てください):
Host host2
ProxyCommand ssh Host1 -W %h:%p
そうするとssh Host2
は自動的にHost1
を通り抜けます(X11転送などでも動作します)。
これはホストのクラス全体に対しても機能します。ドメインによって識別されます。
Host *.mycompany.com
ProxyCommand ssh gateway.mycompany.com -W %h:%p
OpenSSH 7.3では、ProxyJump
ディレクティブが導入され、最初の例は次のように単純化されています。
Host host2
ProxyJump Host1
OpenSSH v7.3以降では-J
スイッチとProxyJump
オプションがサポートされています。これにより、1つ以上のコンマ区切りのジャンプホストが可能になります。
ssh -J jumpuser1@jumphost1,jumpuser2@jumphost2,...,jumpuserN@jumphostN user@Host
私たちのプライベートネットワークへのsshゲートウェイは1つあります。私が外にいて、プライベートネットワーク内のマシンにリモートシェルを置きたい場合は、ゲートウェイにSSH接続し、そこからプライベートマシンに接続する必要があります。
この手順を自動化するために、次のスクリプトを使います。
#!/bin/bash
ssh -f -L some_port:private_machine:22 user@gateway "sleep 10" && ssh -p some_port private_user@localhost
何が起こっている:
上記を読み、すべてをまとめてから、次のPerlスクリプトを作成しました(/ usr/binにmsshとして保存し、実行可能にします)。
#!/usr/bin/Perl
$iport = 13021;
$first = 1;
foreach (@ARGV) {
if (/^-/) {
$args .= " $_";
}
elsif (/^((.+)@)?([^:]+):?(\d+)?$/) {
$user = $1;
$Host = $3;
$port = $4 || 22;
if ($first) {
$cmd = "ssh ${user}${Host} -p $port -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no";
$args = '';
$first = 0;
}
else {
$cmd .= " -L $iport:$Host:$port";
Push @cmds, "$cmd -f sleep 10 $args";
$cmd = "ssh ${user}localhost -p $iport -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no";
$args = '';
$iport ++;
}
}
}
Push @cmds, "$cmd $args";
foreach (@cmds) {
print "$_\n";
system($_);
}
使用法:
HOSTAとHOSTBを介してHOSTCにアクセスするには(同じユーザー):
mssh HOSTA HOSTB HOSTC
HOSTAとHOSTBを介してHOSTCにアクセスし、デフォルト以外のSSHポート番号と異なるユーザーを使用するには
mssh user1@HOSTA:1234 user2@HOSTB:1222 user3@HOSTC:78231
HOSTAおよびHOSTBを介してHOSTCにアクセスし、X転送を使用するには、以下のようにします。
mssh HOSTA HOSTB HOSTC -X
HOSTAおよびHOSTBを介してHOSTCのポート8080にアクセスするには、以下のようにします。
mssh HOSTA HOSTB -L8080:HOSTC:8080
ProxyCommandを使用するため、この回答はkynanと似ています。しかし、IMOを使うほうが便利です。
あなたのホップマシンにnetcatがインストールされているなら、あなたは〜/ .ssh/configにこの断片を追加することができます
Host *+*
ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /') nc $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /')
それから
ssh -D9999 Host1+Host2 -l username
あなたが尋ねたことをするでしょう。
私はこのトリックを読んだ元の場所を探してここに来ました。見つけたら、リンクを投稿します。
ssh -L 9999:Host2:80 -R 9999:localhost:9999 Host1
-L 9999:ホスト2:80
手段はlocalhost:9999にバインドし、localhost:9999に送信されたパケットはすべてHost2:80に転送します。
-R 9999:ローカルホスト:9999
Host1:9999が受信したパケットがlocalhost:9999に転送されることを意味します。
Ithinkあなたがやりたいことをやりました
ssh -D 9999 -J Host1 Host2
両方のパスワードの入力を求められたら、Host2へのSOCKSプロキシにlocalhost:9999を使用できます。それは私があなたが最初に示した例に考えることができる最も近いです。
あなたはlocalhost
からHost2
上のサービスにアクセスするためにポート転送を使うことができるはずです。良いガイドはこちら にあります 。抜粋:
ポート転送には、ローカル転送とリモート転送の2種類があります。それらはそれぞれ発信トンネルと着信トンネルとも呼ばれます。ローカルポート転送は、ローカルポートに着信するトラフィックを指定されたリモートポートに転送します。
たとえば、次のコマンドを発行したとします。
ssh2 -L 1234:localhost:23 username@Host
クライアントのポート1234に届くすべてのトラフィックは、サーバー(ホスト)のポート23に転送されます。接続が確立されると、localhostはsshdserverによって解決されます。したがってこの場合、localhostはサーバー(Host)自体を指します。
リモートポート転送は逆のことを行います。リモートポートへのトラフィックを指定されたローカルポートに転送します。
たとえば、次のコマンドを発行したとします。
ssh2 -R 1234:localhost:23 username@Host
サーバー(ホスト)のポート1234に届くすべてのトラフィックは、クライアント(ローカルホスト)のポート23に転送されます。
キャストでは、例のlocalhost
をHost2
に、Host
をHost1
に置き換えます。
この答えでは、具体的な例を見ていきます。コンピュータのホスト名、ユーザー名、パスワードを自分のものに置き換えるだけです。
次のようなネットワークトポロジがあるとしましょう。
our local computer <---> server 1 <---> server 2
具体的にするために、次のコンピュータのホスト名、ユーザー名、およびパスワードがあるとします。
LocalPC <---> hostname: mit.edu <---> hec.edu
username: bob username: john
password: dylan123 password: doe456
目標:LocalPC
の接続がポート9991
から開始されるたびに9991
を経由してmit.edu
を経由するように、LocalPC
のポートhec.edu
で待機するSOCKSプロキシを設定します。
ユースケースの例:hec.edu
には、セキュリティ上の理由から http://127.0.0.1:8001 でのみアクセス可能なHTTPサーバーがあります。 LocalPC
でウェブブラウザを開いて http://127.0.0.1:8001 にアクセスしたいと思います。
LocalPC
に~/.ssh/config
を追加します。
Host HEC
HostName hec.edu
User john
ProxyCommand ssh [email protected] -W %h:%p
それからLocalPC
の端末で、以下を実行してください。
ssh -D9991 HEC
mit.edu
のbob
のパスワード(つまりdylan123
)を尋ね、次にhec.edu
のjohn
のパスワード(つまりdoe456
)を尋ねます。
その時点で、SOCKSプロキシはLocalPC
の9991
ポートで実行されています。
たとえば、SOCKSプロキシを使用してLocalPC
のWebページにアクセスしたい場合は、Firefoxで次のことができます。
いくつかの発言:
~/.ssh/config
では、HEC
が接続名です。あなたはそれをあなたが望むものに変更することができます。-D9991
は、ポート9991
にSOCKS4プロキシを設定するようにssh
に指示します。両方のマシンにSSHで接続できる場合は、sshのProxyCommandディレクティブを見てください。これにより、localhostからHost2に直接移動できます(公開鍵を使用している場合は1つの簡単なコマンドで)。それから、あなたはHost2であなたがやりたいことは何でもすることができます。
受け入れられた回答に記載されている3つのオプションは、私にはまったく機能しませんでした。私は両方のホストに対する権限があまりないので、DevOpsチームは認証に関してMFAを実行する際にかなり厳しいルールを持っているようです。どういうわけか、上記のコマンドは認証ではうまく機能しません。
ただし、コンテキストは上記の回答と本当に似ています。実稼働サーバーに直接sshすることはできず、ジャンプサーバーを使用して1ホップする必要があります。
私はラップトップですべてのコマンドを実行しようとする代わりに、次のようにコマンドを実行します各マシンで
ssh -v -L 6969:localhost:2222 -N your-protected.dest.server
を実行します。パスワードの入力を求められたら、入力します。ssh -v -L 6969:localhost:6969 -N your-jump-server.Host.name
を実行します。これにより、ラップトップのポート6969上のすべてのリクエストがジャンプサーバーに転送されます。次に、前の手順で構成したので、ジャンプサーバーはポート6969の要求を保護された宛先サーバーのポート2222に再度転送します。何らかのメッセージを出力した後、コマンドが「ハング」するのが見えるはずです-それは、それらが機能していることを意味します!例外が1つあります。Could not request local forwarding.
のようなエラーメッセージが表示されない場合、それでもまだ動作しません:(.
上記のすべての方法に失敗した人であれば、おそらくこれを試すことができます。
私の場合は
localhost$ ssh -D 9999 Host1
Host1$ ssh -L 8890:localhost:8890 Host2
Host2:8890
はJupyter Notebookで実行されています。
それから私はFirefoxがSOCKSホストとしてlocalhost:9999
を使うように設定しました。
それで今私はノートブックを私のマシンのHost2
でFirefoxによってアクセス可能なlocalhost:8890
上で走らせました。
ベストアンサー のオプション2は、現在のユーザーとは異なるsshユーザーでも使用できます。user @ Host
export local_Host_port=30000
export Host1_user=xyz
export Host1=mac-Host
export Host1_port=30000
export Host2=192.168.56.115
export Host2_user=ysg
export Host2_port=13306
# Tunnel from localhost to Host1 and from Host1 to Host2
# you could chain those as well to Host3 ... hostn
ssh -tt -L $local_Host_port:localhost:$Host1_port $Host1_user@$Host1 \
ssh -tt -L $Host1_port:localhost:$Host2_port $Host2_user@$Host2