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

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

Приветствую!

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

Подписывайтесь на наш телеграм @r4ven_me📱, чтобы не пропустить новые публикации на сайте😉. А если есть вопросы или желание пообщаться по тематике — заглядывайте в Вороний чат @r4ven_me_chat🧐.

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

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

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

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

Где:

  • -q — тихий режим (выводить только ошибки);
  • -f — запуск SSH в фоновом режиме;
  • -N — без выполнения команд (только туннель);
  • -Lпроброс локального порта.

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

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

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

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

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

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

Пример:

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

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

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

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

ssh -q -f -L 127.0.0.1:5432:localhost:5432 test.r4ven.me sleep 60

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

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

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

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

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

  • StrictHostKeyChecking=no — отключает проверку host key (⚠️автоматизация в ущерб безопасности);
  • UserKnownHostsFile=/dev/null — не сохранять host key в ~/.ssh/known_hosts;
  • ExitOnForwardFailure=yes — выход, если проброс порта не удался.

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

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

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

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

ssh -q -f -N -R 127.0.0.1:4443:localhost:5001 ivan@test.r4ven.me

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

  • -q — тихий режим (только ошибки);
  • -f — запуск SSH в фоновом режиме;
  • -N — без выполнения команд (только туннель);
  • -Rобратный проброс (удалённого порта до локального).

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

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

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

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

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

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

ss -tln | grep 4443

Вы увидите:

Local Address:Port
127.0.0.1:4443

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

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

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

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

nvim /etc/ssh/sshd_config

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

⚠️Помните, что это потенциальная дыра в вашей системе!

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

sshd -t

systemctl restart sshd

☝️Если используете фаервол, не забудьте добавить разрешающее правило. Пример для ufw:

ufw allow 4443

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

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

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

ss -tln | grep 4443

Всё как надо:

Local Address:Port
0.0.0.0:4443

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

nc -zv test.r4ven.me 4443

curl test.r4ven.me:4443

❗️Не забудьте закрыть соединение после всех манипуляций на локальной машине:

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

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

Не забывайте про нашу телегу📱и чат💬
Всех благ✌️

That should be it. If not, check the logs 🙂

Подписаться
Уведомить о
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии