0

ssh-tunnel

SSH – тоннели

07.10.2022

Туннели SSH — это зашифрованные TCP-соединения между клиентами и серверами SSH. Трафик входит с одной стороны туннеля и прозрачно выходит с другой. Изначально этот термин относился к туннелям на виртуальных сетевых интерфейсах TUN/TAP, однако сейчас так обычно называют проброс портов SSH.

Например, вот так будет выглядеть схема обратного туннеля, в котором обращение к порту 80 SSH-клиента выполняется через SSH-сервер с определенного IP-адреса (1.2.3.4):

Здесь и далее все схемы взяты из оригинала статьи
Здесь и далее все схемы взяты из оригинала статьи

Сценарии использования туннелей*:

  • Предоставление зашифрованных каналов для протоколов, передающих данные «открытым текстом».
  • Открытие бэкдоров в частные сети.
  • Обход межсетевых экранов.

*. Примечание

Перечень дополняется. Не стесняйтесь предлагать примеры или исправления на GitHub.

Проброс портов

Перенаправляет порт из одной системы (локальной или удаленной) в другую.

Проброс локального порта

Проброс локальных портов позволяет перенаправить трафик с SSH-клиента на целевой хост через SSH-сервер. Другими словами, можно получить доступ к удаленным сервисам по зашифрованному соединению так, как будто они локальные. Примеры использования:

  • доступ к удаленному сервису (Redis, Memcached и т. д.) по внутреннему IP-адресу;
  • локальный доступ к ресурсам, размещенным в частной сети;
  • прозрачное проксирование запроса к удаленному сервису.

Проброс удаленного порта

Проброс удаленного порта позволяет направить трафик с SSH-сервера в пункт назначения либо через SSH-клиент, либо через другой удаленный хост. Открывает пользователям в публичных сетях доступ к ресурсам в частных сетях. Примеры использования:

  • открытие доступа к локальному серверу разработки через публичную сеть;
  • предоставление доступа с ограничением по IP-адресу к удаленному ресурсу в частной сети.

Динамический проброс портов

При динамической переадресации портов на SSH-клиенте поднимается SOCKS-прокси для перенаправления TCP-трафика через SSH-сервер на удаленный хост.

Пересылка с системных (privileged) портов

Для пересылки трафика с системных портов (1–1023) необходимо запустить SSH с правами суперпользователя в системе, на которой открывается порт.

sudo ssh -L 80:example.com:80 ssh-server

Флаги командной строки SSH

Ниже приведены несколько полезных флагов при создании туннелей:

-f # переводит процесс ssh в фоновый режим;
-n # предотвращает чтение из STDIN;
-N # не выполнять удаленные команды. Полезно, если нужно только перенаправить порты;
-T # отменяет переназначение терминала.

Вот пример команды для создания SSH-туннеля в фоновом режиме и проброса локального порта через SSH-сервер:

ssh -fnNT -L 127.0.0.1:8080:example.org:80 ssh-server

Для краткости примеры ниже приводятся без флагов командной строки.

Проброс локального порта

Перенаправление соединений с порта локальной системы на порт удаленного хоста:

ssh -L 127.0.0.1:8080:example.org:80 ssh-server

Перенаправляет локальные подключения к 127.0.0.1:8080 на 80-й порт example.org через SSH-сервер. Трафик между локальной системой и SSH-сервером идет по SSH-туннелю. Трафик между SSH-сервером и example.org — нет. С точки зрения example.org трафик идет от SSH-сервера.

ssh -L 8080:example.org:80 ssh-server
ssh -L *:8080:example.org:80 ssh-server

Команды выше открывают доступ к example.org:80 через SSH-туннель для подключений на порт 8080 на всех интерфейсах локальной системы.

ssh -L 192.168.0.1:5432:127.0.0.1:5432 ssh-server

Переадресует соединения с 192.168.0.1:5432 в локальной системе на 127.0.0.1:5432 на SSH-сервере. Обратите внимание, что здесь 127.0.0.1 — localhost с точки зрения SSH-сервера.

Конфигурации SSH

Убедитесь, что на SSH-сервере включена переадресация TCP (по умолчанию так и должно быть). Проверьте запись в файле /etc/ssh/sshd_config:

AllowTcpForwarding yes

При переадресации портов на интерфейсы, отличные от 127.0.0.1, в локальной системе необходимо включить GatewayPorts (в /etc/ssh/ssh_config или в командной строке):

GatewayPorts yes

Сценарии использования

Подходит для случаев, когда требуется защищенное соединение для доступа к удаленному сервису, который работает с незашифрованными данными. Например, Redis и Memcached используют протоколы на основе plaintext-данных.

В случае если защищенный доступ к одному из таких сервисов на удаленном сервере организован по общедоступным сетям, можно настроить туннель от локальной системы до этого сервера.

Проброс удаленного порта

Пробрасывает порт на удаленной системе в другую систему.

ssh -R 8080:localhost:80 ssh-server

Перенаправляет трафик с порта 8080 SSH-сервера для всех интерфейсов на порт localhost:80 на локальном компьютере. Если один из интерфейсов смотрит в Интернет, трафик, адресуемый на порт 8080, будет перенаправляться на локальную систему.

ssh -R 1.2.3.4:8080:localhost:80 ssh-server

Переадресует трафик с порта 8080 SSH-сервера на localhost:80 в локальной системе, при этом доступ ко входу в SSH-туннель со стороны сервера разрешен только с IP-адреса 1.2.3.4 (обратите внимание: директиву GatewayPorts необходимо установить в clientspecified).

ssh -R 8080:example.org:80 ssh-server

Переадресует трафик с порта 8080 SSH-сервера для всех интерфейсов на localhost:80 в локальной системе. Далее трафик из локальной системы направляется на example.org:80. С точки зрения example.org источником трафика выступает локальная система.

Конфигурация SSH-сервера

SSH-сервер конфигурируется в файле /etc/ssh/sshd_config.

По умолчанию переадресуемые порты недоступны для доступа из Интернета. Для переадресации публичного интернет-трафика на локальный компьютер добавьте в sshd_config на удаленном сервере такую строку:

GatewayPorts yes

Также в sshd_config можно указать, каким клиентам разрешен доступ:

GatewayPorts clientspecified

Динамический проброс портов

Перенаправление трафика с нескольких портов на удаленный сервер.

ssh -D 3000 ssh-server

Команда выше поднимает SOCKS-прокси на порту 3000 для всех интерфейсов в локальной системе. Теперь трафик, отправленный через прокси-сервер на SSH-сервер, можно адресовать на любой порт или конечный хост. По умолчанию используется протокол SOCKS5, поддерживающий TCP и UDP.

ssh -D 127.0.0.1:3000 ssh-server

Поднимает SOCKS-прокси на 127.0.0.1:3000 в локальной системе.

При работающем SOCKS-прокси можно настроить браузер на его использование для доступа к ресурсам так, как будто соединения исходят от SSH-сервера. Например, если у SSH-сервера есть доступ к другим серверам в частной сети, с помощью SOCKS-прокси можно заходить на эти серверы локально (словно вы находитесь в той же сети), и не нужно настраивать VPN.

Работу SOCKS-прокси можно проверить командой:

curl -x socks5://127.0.0.1:12345 https://example.org

Конфигурация SSH-клиента

SSH-клиент настраивается в файле /etc/ssh/ssh_config.

Включите GatewayPorts в системе, чтобы открыть доступ другим интерфейсам к SOCKS-прокси:

GatewayPorts yes

Поскольку GatewayPorts конфигурируется на SSH-клиенте, вместо ssh_config для настройки можно использовать параметры командной строки:

ssh -o GatewayPorts=yes -D 3000 ssh-server

Jump-хосты и команды прокси-сервера

Прозрачное подключение к удаленному хосту через промежуточные.

ssh -J user1@jump-host user2@remote-host
ssh -o "ProxyJump user1@jump-host" user2@remote-host

Устанавливает SSH-соединение с jump-хостом и переадресуют трафик на удаленный хост. 

Подключается к удаленному хосту через промежуточный jump-хост. Приведенная выше команда должна сработать сразу, если у jump-хоста уже есть SSH-доступ к удаленному хосту. Если нет, можно использовать agent forwarding для проброса SSH-ключа с локального компьютера на удаленный хост.

ssh -J jump-host1,jump-host2 ssh-server

Можно указать несколько jump-хостов через запятую.

ssh -o ProxyCommand="nc -X 5 -x localhost:3000 %h %p" user@remote-host

Подключение к удаленному серверу через SOCKS5 с использованием netcat. С точки зрения сервера, IP-адрес отправителя принадлежит прокси-хосту. При этом для SSH-соединения используется сквозное шифрование, так что прокси-хост видит только зашифрованный трафик между локальной системой и удаленным хостом.

Конфигурация SSH-клиента

SSH-клиент конфигурируется в файле /etc/ssh/ssh_config.

Для подключения agent forwarding можно добавить локальный SSH-ключ к локальному SSH-агенту с помощью ssh-add:

ssh-add

Надежные SSH-туннели

Перечисленные выше команды работают на разовой основе: вы сразу получаете конкретный результат, и на этом их работа заканчивается. Поэтому, чтобы обеспечить защиту SSH-туннелей от сбоев в сети или ненадежных соединений, придется выполнить дополнительную настройку.

По умолчанию TCP-соединение, используемое для создания SSH-туннеля, может разрываться после некоторого периода бездействия. Чтобы это предотвратить, нужно настроить сервер (/etc/ssh/sshd_config) на отправку heartbeat-сообщений:

ClientAliveInterval 15
ClientAliveCountMax 4

На отсылку таких сообщений также можно настроить клиент (/etc/ssh/ssh_config):

ServerAliveInterval 15
ServerAliveCountMax 4

Использование AutoSSH

Указанные выше настройки могут предотвратить разрывы из-за неактивности, но они не в состоянии восстановить прерванные соединения. Для автоматического перезапуска SSH-туннеля можно воспользоваться утилитой autossh — она создает SSH-туннель и отслеживает его работоспособность.

AutoSSH принимает те же аргументы для настройки переадресации портов, что и SSH:

autossh -R 2222:localhost:22 ssh-server

Эта команда создает туннель, способный восстанавливаться после сетевых сбоев. По умолчанию AutoSSH открывает дополнительные порты на SSH-клиенте/сервере для проверки работоспособности (healthcheck). Если трафик не проходит между healthcheck-портами, AutoSSH перезапускает туннель.

autossh -R 2222:localhost:22 \
  -M 0 \
  -o "ServerAliveInterval 10" -o "ServerAliveCountMax 3" \
  remote-host

Флаг -M 0 отключает healthcheck-порты (за проверку работоспособности в этом случае отвечает SSH-клиент). В примере выше сервер должен посылать сигналы каждые 10 секунд. Если не проходят три подряд сигнала, SSH-клиент завершает работу, а AutoSSH поднимает новый туннель.

Дополнительные примеры и сценарии использования

Прозрачный доступ к удаленному ресурсу в частной сети.

Предположим, в частной сети есть Git-репозиторий, доступ к которому возможен только через выделенный сервер в этой сети. Сервер не подключен к Интернету. Есть прямой доступ к серверу, но нет VPN-доступа к частной сети.

Требуется открыть доступ к Git-репозиторию, как если бы подключение к нему шло напрямую из локальной системы. Если есть SSH-доступ к другому серверу, который доступен как с локального компьютера, так и с выделенного сервера, можно создать SSH-туннель и воспользоваться директивами ProxyCommand.

ssh -L 127.0.0.1:22:127.0.0.1:2222 intermediate-host

Команда выше пробрасывает порт 2222 на промежуточном хосте на порт 22 выделенного сервера. Теперь можно подключиться к SSH-серверу на выделенном сервере, несмотря на то, что он недоступен из Интернета.

ssh -p 2222 user@localhost

Для большего удобства можно добавить несколько директив в локальный ~/.ssh/config:

Host git.private.network
  HostName git.private.network
  ForwardAgent yes
  ProxyCommand ssh private nc %h %p

Host private
  HostName localhost
  Port 2222
  User private-user
  ForwardAgent yes
  ProxyCommand ssh tunnel@intermediate-host nc %h %p

В результате пользователь получает доступ к локальному Git-репозиторию, как если бы находился в частной сети.

Свежие комментарии

Подписка

Лучшие статьи

Рубрики

Популярное

esxi
Previous Story

4 способа сбросить пароль root на хосте
VMWare ESXi

lxc
Next Story

LXC

Latest from Blog

Настройка простого беспроводного репитера на устройстве MikroTik

При развертывании беспроводных сетей достаточно часто возникают ситуации, когда в некоторых местах квартиры или офиса мощность Wi-Fi сигнала недостаточна для уверенной работы. Конечно, наиболее действенным решением является создание централизованно управляемой сети и

Настройка и использование Redis

В этой статье мы расскажем что такое Redis, его преимущества и для каких целей он используется. Redis (REmote DIctionary Server) — сетевое журналируемое хранилище данных типа “ключ” — “значение” с открытым исходным кодом. По сути Redis представляет собой базу данных

Настройка и использование Memcached

В статье мы расскажем, что такое Memcache, зачем он нужен и как он влияет на работу некоторых популярных CMS. Кеширование данных – немаловажный момент в работе любого веб-проекта. С ростом посещаемости увеличиваются требования к

Как настроить логирование и ротацию логов Nginx

Вовремя настроенное журналирование позволяет в дальнейшем избежать неожиданных проблем с веб-сервером. Информация, хранящаяся в логах (или журналах) сервера, помогает быстро оценить ситуацию и устранить ошибки. В этой статье мы рассмотрим возможности логирования

Распределение выполнения запросов внутри приватной сети VPS через HAProxy

Приватную сеть можно использовать для распределения выполнения загрузки и балансировки запросов между несколькими серверами. Рассмотрим организацию такой балансировки на примере HAProxy – бесплатного ПО, предназначенного для распределения нагрузки и организации проксирования TCP-пакетов между несколькими обслуживающими
Go toTop