SSH туннели и проброс портов

4 min read

При администрировании серверов часто возникают следующие задачи:

  1. Получить доступ к локальному порту на сервере с рабочей машины
  2. Обеспечить доступ к локальному порту рабочей машины с сервера

Обе эти задачи решаются с помощью туннелирования, но иногда требуется организовать такой туннель быстро и без создания сложной дополнительной инфраструктуры. Решить такую задачу можно с помощью SSH.

Доступ к внутреннему порту сервера

Попробуем подключиться к порту, к которому нет доступа снаружи, но есть доступ с сервера (например, MongoDB, которая слушает порт 27017 на интерфейсе localhost сервера). Для этого используется параметр -L.

ssh -L 9999:localhost:27017 [email protected]

После аутентификации, у нас на рабочей машине появляется порт 9999, который перенаправлен на порт 27017 локального интерфейса сервера.

Теперь можно подключиться к MongoDB напрямую, как будто она запущена у вас на компьютере. 

mongo localhost:9999 -u user -p password

Туннель прервётся, если вы закроете SSH соединение. Кстати, если оно вам не требуется, а нужен только туннель – можно добавить параметр -N.

ssh -L 9999:localhost:27017 [email protected] -N

Можно также открывать доступ не к локальному порту сервера, а к удаленному порту другой машины, которая доступна с сервера.

ssh -L 9999:anotherIP:80 [email protected] -N

В данном примере, вы можете делать запросы на порт 9999, связанный с 80 портом машины anotherIP.

Доступ с сервера на локальный порт

Теперь представим ситуацию, что нужно с сервера обратиться к какому-нибудь сервису, запущенному на локальном компьютере. Например, вам регулярно присылают HTTP запросы по 80 порту на сервер. Вы можете прокинуть локальный веб-сервер со своей рабочей машины (скажем с 3000 порта) на сервер так, что запросы будут идти напрямую к вам. За это отвечает параметр -R.

ssh -R 80:localhost:3000 [email protected]

После этой команды на сервере откроется 80 порт, запросы на который будут прокидываться вам на 3000.

По умолчанию 80 порт откроется на всех интерфейсах. Если вы желаете выбрать конкретный (скажем 192.168.0.1), его можно указать следующим образом

ssh -R 192.168.0.1:80:localhost:3000 [email protected]

Цепочка туннелей через несколько узлов

Если нужно пробросить на свою машину локальный порт с сервера №2, доступ к которому по SSH есть только с сервера №1, можно построить цепочку из SSH туннелей

server1# ssh -L 9999:localhost:27017 [email protected] client# ssh -L 9999:localhost:9999 [email protected]

Можно воспользоваться однострочной командой. 

ssh -L 9999:localhost:9999 [email protected] ssh -L 9999:localhost:27017 -N [email protected]

А в случае, если у вас есть SSH ключи для доступа к серверу №2, вы можете построить защищенный туннель так, что ваш трафик не будет виден на сервере №1.

ssh -L 9998:server2:22 -N [email protected] ssh -L 9999:localhost:27017 -N -p 9998 [email protected]

В данном примере вы пробрасываете себе на порт 9998 порт с сервера №2, обращаясь к нему через сервер №1. А затем пробрасываете порт 27017 с сервера №2 на локальный 9999. В данной конфигурации вам уже не нужен сервер №1, так как порт SSH уже у вас на локальном 9998

SOCKS прокси

С помощью параметра -D можно создать на локальной машине сокет для прослушивания динамического порта.

ssh -D localhost:8123 [email protected]

Теперь достаточно добавить хост localhost и порт 8123 в браузер для использования в качестве прокси.