У нас есть несколько удаленных серверов, которые доступны только через jumphost. На этих удаленных серверах запускаются виртуальные машины, на которых размещаются базы данных, к которым я хочу подключиться локально. Каждая коробка - это система Linux. У меня есть права только su на моем локальном компьютере, на удаленном хосте и его vms.
Это означает, что наша установка выглядит так:
My local pc --> jumphost --> remotehost --> vm with mysql on 127.0.0.1:3306
Обычно я использую ssh три раза, а затем использую mysql cli.
Теперь мне нужно настроить туннель с моего локального компьютера на ящик с базой данных.
Ulitmatly я хочу использовать что-то вроде библиотеки python ssh-туннель и его класс SSHTunnelForwarder. Но я хочу начать с команд bash для настройки такого прокси.
Аутентификация ssh основана на пароле, и для каждого перехода требуется отдельный пользователь. В идеале решение не потребует изменений в ~ / .ssh / config
Я нашел это Почта, и я думаю, что варианты 3 довольно близки к тому, что мне нужно.
Пример, чтобы прояснить ситуацию. Скажем, jumphost это: user1@192.168.11.29
, мой удаленный хост user2@172.1.1.1
и виртуальная машина с базой данных user3@10.100.1.1
я бы попробовал:
ssh -L 9998:172.1.1.1:22 -N user1@192.168.11.29
туннель от моего локального порта ПК 9998 к порту 22 на удаленном хосте
Здесь начинается моя проблема: как мне указать пользователя, используемого для следующих за ssh туннелей. Может ли кто-нибудь направить меня в правильном направлении?
ssh -L 9999:10.100.1.1:22-N -p 9998 user2@localhost
туннель от моего локального порта ПК 9999 через первый туннель к порту 22 на удаленном хосте
ssh -L 10000:locahost:3306 -N -p 9999 user3@localhost
Туннель от порта 10000 локального ПК через туннель на порт 9999 к порту 3306 на виртуальной машине.
После этого я смогу получить доступ к базе данных на виртуальной машине с 127.0.0.1:3306 с моего локального компьютера, насколько я понимаю.
Я надеюсь, что это имеет смысл, я благодарен за каждый ответ.
Я смог это решить, благодаря этому Почта
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 установлено значение «Вкл» на каждом используемом переходе.
Это должно сделать это:
ssh -J jumphost,remotehost vm -L 3306:localhost:3306
Это будет SSH для vm
, с помощью jumphost
&remotehost
как прокси. Затем он подключает TCP-порт 3306
на vm
с портом 3306
на вашем локальном компьютере.
Я не знаю о питоне, но современный ssh имеет ProxyJump
директива.
Вот фрагмент с некоторой анонимностью из одного из моих ~/.ssh/config
файлы.
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 - к внутреннему серверу, а затем подключается через этот туннель к внутреннему серверу.