Как перенаправить TCP-соединение (в частности, клиент MyQSL -> сервер) через туннель SSH с несколькими прыжками?

581
Nathan Lutterman

Я хочу открыть соединение с удаленной базой данных MySQL. Эта база данных находится в частной подсети в другой сети, поэтому я не могу напрямую открыть соединение с ней. Удаленный доступ по SSH также полностью отключен на сервере MySQL.

Мой текущий процесс таков:

Я открываю туннель SSH через общедоступный сервер, HOST_1. Из этого туннеля я открываю SSH-соединение с сервером (HOST_2), который находится в той же подсети, что и сервер MySQL (MYSQL_HOST). Используя сеанс SSH, который я открыл в тот момент (на HOST_2), я использую клиент MySQL, чтобы открыть соединение с MYSQL_HOST.

Вот очень грубая грубая диаграмма того, что в настоящее время сделано:

diagram of current connection

Я хочу использовать MySQL-клиент моего локального компьютера для подключения к 127.0.0.1:3306 и полностью туннелировать соединение от HOST_1 до HOST_2, а затем к MYSQL_HOST, как если бы у меня был сервер MySQL. работает с 127.0.0.1 на первом месте.

Опять же, я не могу открыть SSH-туннель в MYSQL_HOST из HOST_2, поэтому никакого туннелирования оттуда нет. Мне нужно выяснить, как перенаправить клиентское соединение MySQL через туннель SSH на HOST_2, а затем HOST_2 переслать клиентское соединение MySQL на MYSQL_HOST.

Я думал, что мог бы использовать redirили ncдостичь этого. Я не уверен, как, хотя.

Я прочитал пару вопросов, но не все понимаю достаточно, чтобы собрать информацию, чтобы получить ответ, который я ищу:

  1. Туннель SSH через несколько переходов
  2. UDP-трафик через SSH-туннель
  3. https://unix.stackexchange.com/questions/267090/reroute-mysql-connection-through-external-machine

Я знаю, что на этой странице снова есть информация, которая поможет мне, но я не знаю, как ее использовать: http://sshmenu.sourceforge.net/articles/transparent-mulithop.html

Спасибо!

2

2 ответа на вопрос

1
Omnipresence

Этот ответ предполагает, что sshd настроен на переадресацию портов на HOST_1 и HOST_2.

Вы уже нашли большую часть того, что вам нужно (второй вариант ответа Мики Фишер в вашей первой ссылке).

Туннель с локального хоста на хост1 и с хоста 1 на хост2:

ssh -L 9999:localhost:9999 host1 ssh -L 9999:localhost:1234 -N host2 Это откроет туннель от localhost до host1 и еще один туннель от host1 до host2. Однако порт 9999 для host2: 1234 может использоваться любым пользователем на host1. Это может или не может быть проблемой.

Идея состоит в том, чтобы связать воедино переадресацию портов (т.е. вы перенаправляете локальный порт на удаленный порт, который затем перенаправляете на еще более удаленный порт).

Для вашего примера команда будет

ssh -tt -L 3306:localhost:XXXX [user@]HOST_1 ssh -L XXXX:MYSQL_HOST:3306 [user@]HOST_2 где XXXX - любой порт выше 1024, который еще не используется (используйте один и тот же номер для замены обоих экземпляров)

После выполнения вам будет предложено ввести пароль дважды (один раз для HOST_1 и один раз для HOST_2), если только вы не используете ключи SSH для входа без пароля. Туннель будет работать до тех пор, пока вы остаетесь подключенным к HOST_2 через HOST_1.

Вот разбивка:

ssh это локальный клиент SSH, который вы выполняете

-ttпринудительно назначает псевдо-tty (см. Псевдо-терминал не будет выделяться, потому что stdin не является терминалом, для чего это может понадобиться)

-L 3306:localhost:XXXX [user@]HOST_1говорит вашему локальному SSH-клиенту перенаправить 3306 в вашей локальной системе на порт XXXX на «localhost» на другой стороне SSH-соединения. Вам нужно только указать, отличается user@ли пользователь на вашем локальном компьютере от пользователя, к которому вы подключаетесь на HOST_1. В более общем смысле вы можете указать локальный порт, отличный от 3306, но затем укажите вашему клиенту mysql 127.0.0.1:[your выбранный порт].

ssh(второй) Как вы, возможно, знаете, у ssh есть возможность запустить одну команду вместо запуска оболочки. Вы будете использовать это для выполнения другого сеанса SSH на HOST_1, который создаст следующую ссылку в цепочке переадресации портов.

-L XXXX:MYSQL_HOST:3306 [user@]HOST_2Поскольку этот сеанс ssh выполняется на HOST_1, он пересылает XXXX на локальную сторону (HOST_1) (которая пересылается с 3306 на вашем клиенте) на порт 3306 на MYSQL_HOST на удаленной стороне (HOST_2). Вам нужно только указать, отличается user@ли пользователь на HOST_1 от пользователя, к которому вы подключаетесь на HOST_2.

Если требуются дополнительные прыжки, добавьте экземпляры ssh -L XXXX:localhost:XXXX hostXдля каждого прыжка в середине, если XXXX является доступным портом на каждом сервере в пути.

Это потрясающий ответ, большое спасибо, что нашли время, чтобы объяснить вещи так подробно. Я еще не проверял это, поскольку у меня не было возможности. Я отмечаю это как ответ, так как здесь достаточно информации, чтобы я мог понять это. Еще раз спасибо!! Nathan Lutterman 6 лет назад 0
1
Gordon Davisson

Поскольку вы используете прокси-соединение SSH с HOST_2 через HOST_1, вы можете сделать это только с одним -Lпортом переадресации:

ssh -A -o 'ProxyCommand = ssh -q user @ HOST_1 nc% h% p' user @ HOST_2 -L 3306: MYSQL_HOST: 3306

По сути, это делает то, что вы делаете сейчас: открывает ssh-соединение с HOST_2, проксированным через ssh-соединение с HOST_1, а затем перенаправляет соединения с 3306 на локальном хосте через MYSQL_HOST: 3306. Обратите внимание, что MYSQL_HOST увидит соединение, пришедшее с HOST_2, поскольку именно там оно выходит из туннеля и превращается в обычное TCP-соединение.

Кстати, если у вас есть OpenSSH 7.3 или новее как на локальном компьютере, так и на HOST_1, вы можете упростить прокси SSH, используя новую -Jопцию (или ProxyJumpдирективу в вашем файле конфигурации ssh) :

ssh -A -J пользователь @ HOST_1 пользователь @ HOST_2 -L 3306: MYSQL_HOST: 3306

Это также облегчает прохождение через несколько прокси-серверов SSH:

ssh -A -J пользователь @ HOST_1, пользователь @ HOST_3, пользователь @ HOST_3 пользователь @ HOST_4 -L 3306: MYSQL_HOST: 3306