SSH — Проброс портов: прямые и обратные туннели
Приветствую!

Сегодня разберемся с пробросом портов через SSH 🔐: как с помощью прямых и обратных (реверс) туннелей организовать доступ к локальным и удалённым сервисам.

Прямой проброс порта

Например, нам нужно на локальной машине подключиться к БД💽, доступной, только на localhost интерфейсе удаленного сервера🖥.

Открыть SSH-туннель можно такой командой:

BASH
ssh -q -f -N -L 127.0.0.1:5432:localhost:5432 ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

Где:

Сперва идёт адрес:порт локального хоста, затем адрес:порт удаленного.

Данная команда откроет туннель в фоновом режиме и будет работать перманентно.
Теперь можно подключаться к БД по адресу 127 0.0.1:5432

Если это ваша цель, то задача решена👌.

Но что, если вам необходимо открыть туннель только на время выполнения некоторых манипуляций? Например, при настройке автоматизации с помощью сценариев оболочки📝. Очевидно, в таком случае по завершении работы туннель необходимо закрыть🔒.

К сожалению у SSH нет встроенного функционала для предоставления PID ‘а фонового процесса😢.

Поэтому закрыть туннель можно топорным способом, через pkill 🎯, передав в качестве аргумента полную команду открытия туннеля😒.

Пример:

BASH
pkill -f "ssh -q -f -N -L 127.0.0.1:5432:localhost:5432 ivan@test.r4ven.me"

# или

pgrep -f "ssh -q -f -N -L 127.0.0.1:5432:localhost:5432 ivan@test.r4ven.me" | xargs kill
Нажмите, чтобы развернуть и увидеть больше

Данный способ хоть и рабочий, но не совсем элегантный. Да и небезопасен: если допустить ошибку в аргументе, можно случайно прибить другой рабочий процесс🤷♂

Поиск альтернативного решения занял долгое какое-то время⏳

И вот его пример:

BASH
ssh -q -f -L 127.0.0.1:5432:localhost:5432 test.r4ven.me sleep 60
Нажмите, чтобы развернуть и увидеть больше

Суть его в том, что мы открываем туннель на 60 сек. В течение этого времени необходимо запустить нужную вам команду🐧.

Даже, если выполнение вашей прикладной команды займет больше минуты, соединение не прервется ДО её завершения😌. Другими словами, туннель корректно закроется автоматически👍.

Ниже приведу вариант команды, который я использовал в одном из скриптов:

BASH
ssh -q -f -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ExitOnForwardFailure=yes -L 127.0.0.1:5432:localhost:5432 test.r4ven.me -p 2222 -l ivan -i ~/.ssh/id_ed25519_test sleep 60
Нажмите, чтобы развернуть и увидеть больше

Дополнительные опции:

Возможно пригодится кому для своих shell 🐚 скриптов🙃.

Обратный проброс порта

Теперь погорим про реверс, они же обратные, туннели🌐.

Например нужно направить данные с порта 4443 удаленной машины на порт 5001 локальной:

BASH
ssh -q -f -N -R 127.0.0.1:4443:localhost:5001 ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

Напомню, что:

Сперва идёт адрес:порт удалённого хоста, затем адрес:порт локального.

Если что, то закрыть соединение можно такой топорной командой:

BASH
pkill -ef 'ssh -q -f -N -R 127.0.0.1:4443:localhost:5001 ivan@test.r4ven.me'
Нажмите, чтобы развернуть и увидеть больше

Как вы заметили, мы пробросили порт удаленной машины, ожидающий подключений на локальном интерфейсе. Для проброса не localhost интерфейса явно укажите его. Или пробросьте все интерфейсы:

BASH
ssh -q -f -N -R 0.0.0.0:4443:localhost:5001 ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

С высокой вероятностью, если на удаленной машине выполнить:

BASH
ss -tln | grep 4443
Нажмите, чтобы развернуть и увидеть больше

Вы увидите:

BASH
Local Address:Port
127.0.0.1:4443
Нажмите, чтобы развернуть и увидеть больше

Удаленный порт все равно слушает локальный интерфейс🤔

Дело тут в сецуре шел, который не был бы сецуре, если не имел бы сецурных параметров по умолчанию😎.

В целях безопасности обратные пробросы портов на не локальном интерфейсе отключены. За это отвечает параметр GatewayPorts в конфгие SSH🔒.

Чтобы разрешить обратные пробросы открываем конфиг sshd:

BASH
nvim /etc/ssh/sshd_config
Нажмите, чтобы развернуть и увидеть больше

И устанавливаем параметр GatewayPorts в значение yes.

После чего перезапускаем демон sshd:

BASH
sshd -t

systemctl restart sshd
Нажмите, чтобы развернуть и увидеть больше

Переоткрываем туннель:

BASH
pkill -ef 'ssh -q -f -N -R 0.0.0.0:4443:localhost:5001 ivan@test.r4ven.me'

ssh -q -f -N -R 0.0.0.0:4443:localhost:5001 ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

И вновь проверяем порт на удаленной машине:

BASH
ss -tln | grep 4443
Нажмите, чтобы развернуть и увидеть больше

Всё как надо:

BASH
Local Address:Port
0.0.0.0:4443
Нажмите, чтобы развернуть и увидеть больше

Теперь при подключении с любого клиента вы будете перенаправлены на вашу локальную систему:

BASH
nc -zv test.r4ven.me 4443

curl test.r4ven.me:4443
Нажмите, чтобы развернуть и увидеть больше

Хорошего дня!👋

Авторские права

Автор: Иван Чёрный

Ссылка: https://r4ven.me/networking/ssh-probros-portov-pryamye-i-obratnye-tunneli/

Лицензия: CC BY-NC-SA 4.0

Использование материалов блога разрешается при условии: указания авторства/источника, некоммерческого использования и сохранения лицензии.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша