ジャンプホストを介してのみアクセスできるリモートサーバーがいくつかあります。このリモートサーバーで、ローカルにアクセスしたいデータベースをホストするvmsを実行します。各ボックスはLinuxシステムです。私は自分のローカルPC、リモートホストとそのvmsに対してのみsu権限を持っています。
つまり、セットアップは次のようになります。
My local pc --> jumphost --> remotehost --> vm with mysql on 127.0.0.1:3306
通常、私は3回sshを実行してから、mysqlcliを使用します。
次に、ローカルPCからデータベースをホストするボックスへのトンネルを設定する必要があります。
最終的には、python lib ssh-tunnel とそのクラスSSHTunnelForwarderのようなものを使用したいのですが、bashコマンドから始めてこの種のプロキシをセットアップしたいと思います。
Ssh認証はパスワードベースであり、ホップごとに異なるユーザーが必要です。理想的には、ソリューションは〜/ .ssh/configへの変更を必要としないでしょう
私はこれを見つけました post 、そして私はオプション3が私が必要とするものにかなり近いと思います。
それを明確にするための例。ジャンプホストが次のようになっているとしましょう:[email protected]
、私のリモートホストは[email protected]
そしてデータベース付きのVMは[email protected]
私が試みることは:
ssh -L 9998:172.1.1.1:22 -N [email protected]
ローカルPCポート9998からリモートホストのポート22へのトンネル
ここから問題が始まります。sshトンネルの隣に使用するユーザーをどのように指定しますか。誰かが私を正しい方向に導くことができますか?
ssh -L 9999:10.100.1.1:22-N -p 9998 user2@localhost
ローカルPCポート9999から最初のトンネルを経由してリモートホストのポート22にトンネルする
ssh -L 10000:locahost:3306 -N -p 9999 user3@localhost
ローカルPCポート10000からポート9999のトンネルを経由してVMのポート3306にトンネルします。
その後、私が理解している限り、ローカルPCから127.0.0.1:3306でVM上のデータベースにアクセスできるはずです。
私はそれが理にかなっていることを願っています、私はすべての答えに感謝しています。
これのおかげで私はそれを解決することができました post
class TunnelNetwork(object):
def __init__(self, tunnel_info, target_ip, target_port):
self.tunnel_info = tunnel_info
self.target_ip = target_ip
self.target_port = target_port
def start_tunnels(self):
self.tunnels = []
for idx, info in enumerate(self.tunnel_info):
# if we're not the first element, set the bastion to the local port of the previous tunnel
if idx > 0:
info['ssh_address_or_Host'] = ('localhost', self.tunnels[-1].local_bind_port)
# if we are the last element, the target is the real target
if idx == len(self.tunnel_info) - 1:
target = (self.target_ip, self.target_port)
# else, the target is the next bastion
else:
if isinstance(self.tunnel_info[idx+1]['ssh_address_or_Host'], Tuple):
target = self.tunnel_info[idx+1]['ssh_address_or_Host']
else:
target = (self.tunnel_info[idx+1]['ssh_address_or_Host'], 22)
self.tunnels.append(SSHTunnelForwarder(remote_bind_address=target, **info))
try:
self.tunnels[idx].start()
except:
return False
return True
def stop_tunnels(self):
for tunnel in reversed(self.tunnels):
tunnel.stop()
def are_tunnels_active(self):
return self.tunnels and all([t.is_active for t in self.tunnels])
def get_local_connect_port(self):
if self.tunnels:
return self.tunnels[-1].local_bind_port
else:
return None
そしてそれを一緒に使用してください:
tunnel_i = [
{"ssh_address_or_Host": "192.168.11.29",
"ssh_username": "user1",
"ssh_password": "",
},
{"ssh_address_or_Host": "172.1.1.1 ",
"ssh_username": "user2",
"ssh_password": "",
},
{"ssh_address_or_Host": "10.100.1.1",
"ssh_username": "user3",
"ssh_password": "",
}
]
target_ip = "127.0.0.1"
target_port = 3306
tn = TunnelNetwork(tunnel_i, target_ip, target_port)
tn.start_tunnels()
使用している各ホップで、AllowTcpForwardingがOnに設定されていることを確認してください。
Pythonについてはわかりませんが、最新のsshにはProxyJump
ディレクティブがあります。
これは、私の~/.ssh/config
ファイルの1つからの匿名化されたスニペットです。
Host bastion
user sitaram
hostname 1.2.3.4
# external IP of bastion Host
Host inside
user not-sitaram
hostname 172.16.17.18
# IP of "inside" as seen from "bastion" server
proxyjump bastion
この後、私は単にssh inside
(またはscp inside:foo bar
、rsync、gitなど)と言うだけで、「正常に機能する」(TM)! Sshは最初に自動的に要塞に接続し、TCPポートフォワードではなく、STDIN/STDOUTに基づくトンネル)を内部サーバーに確立してから、そのトンネルを介して内部サーバーに接続します。