SSH Туннелирование - VPN для бедных гиков. Как получить доступ к серверу Linux за NAT через обратный туннель SSH

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

Терминология

Для упрощения понимания материала в статье использована терминология, которой я строго придерживаюсь и которая имеет чёткий смысл.

Клиент — компьютер-источник запросов. Например, браузер или ssh-клиент.
Сервер — компьютер-обработчик запросов. Например, десктоп в локальной сети.
Базовая схема — схема взаимодействия, в которой участвуют лишь Клиент и Сервер.
Расширенная схема — расширение базовой схемы, когда Клиент и Сервер опосредованы Прокси.
Прокси — компьютер-посредник между Клиентом и Сервером в расширенной схеме.
Прямой туннель — туннель, в котором направление инициирования SSH-сесии и запросов совпадают.
Обратный туннель — направление инициирования SSH-сессии и клиентских запросов противоположны.
Source port (исходный порт) — порт на одном из концов туннеля, куда приходит запрос от Клиента.
Может быть для PuTTY локальным «Local» (на том же конце туннеля, что и PuTTY) и удалённым «Remote» (на противоположном конце).
Destination (адрес назначения) — IP-адрес и порт компьютера, для которого предназначены пакеты, выходящие из туннеля. В расшриренной схеме это всегда сам Сервер.

SSH-туннели создаются для решения 2-х независимых задач:

  1. Обеспечение конфиденциальности данных, передаваемых по защищённому каналу
  2. Создание связующего мостика (или нескольких мостиков) между Клиентом и Сервером через промежуточные компьютеры, так как Клиент может не иметь прямого доступа к Серверу. В этом случае конфиденциальность является второстепенной или вовсе не требуется.

SSH-туннели могут быть организованы как в режиме перенаправленя отдельных TCP-портов (Port forwarding), так и в режиме настоящих VPN-туннелей через виртуальные интерфейсы, когда передаваться может трафик любых протоколов и с любых портов. В данной статье мы рассмотрим первый режим.

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

Таким образом, SSH-канал в этом режме со всей его инфраструктурой напоминает виртуальный шлюз с входным и выходным интерфейсами, но только по конкретной паре TCP-портов:

Стрелкой указано направление инициирования SSH-сессии. В данном случае инициатором соединения выступает Клиент с установленным на нём PuTTY.

Приведённая выше схема является базовой, в которой взаимодействуют лишь 2 участника Клиент и Сервер. На практике же между Клиентом и Сервером может быть несколько промежуточных хостов. И до попадания на вход конкретного туннеля и после выхода из него пакеты могут передаваться по незащищённым каналам.

Для установления связи по SSH-протоколу необходима учётная запись на SSH-сервере, которая может быть любой, в том числе без каких бы то ни было прав и даже без шелла, если вы открываете на прослушивание непривелигированные порты от 1024 и выше. В противном случае необходим рутовый доступ и значение директивы PermitRootLogin равное yes или without-password .

Анализ связности и доступности участников взаимодействия

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

Для этого мы должны ответить на вопрос, где находятся SSH-серверы и доступны ли они с помощью SSH-клиентов с других хостов.

Рассмотрим эти шаги на базе расширенной схемы, состоящей из Клиента, промежуточного Прокси-сервера и Сервера. На практике такие схемы встречаются чаще всего.

Если соединять стрелками машины, доступные по SSH-протоколу, то возможны следующие варианты:

В частности, мы соединяем стрелкой Клиента с Прокси, если Прокси доступен с Клиента на 22-м порту. Перебрав попарно всех участников взаимодействия, получим схему связности. Например:

Стрелки схемы связности показывают, откуда может быть инициирован туннель на машину с SSH-сервером.

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

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

Комбинация обеих схем помогает ответить на вопрос о том, имеется ли принципиальная возможность установления соединения Клиента с Сервером, а если её нет, то что надо добавить, чтобы её получить.

В дальнейшем мы воспользуемся этими схемами для построения канала связи.

Приведённая выше схема очень распространена: Клиент и Сервер (чаще всего на базе Windows) находятся в разных локальных сетях за NAT, имеют выход в интернет и «видят» удалённый Прокси-сервер, тогда как с Прокси они недоступны ни по SSH ни по другим протоколам. На Прокси, как правило, установлена *nix-подобная операционная система, в которой SSH-сервер есть по умолчанию.

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

Алгоритм построения канала связи с помощью SSH-туннелей

Разберём алгоритм построения канала связи с помощью SSH-туннеля на примере схемы, приведённой выше, где Клиент и Сервер находятся в разных локальных сетях за NAT-ами, и могут быть связаны только через Интернет с помощью некоторого Прокси-сервера.

1) Составление схемы SSH-связности

SSH-сервер у нас имеется только на Прокси, поэтому мы можем инициировать 2 туннеля: с Клиента и с Сервера:

Это схема с двумя односвязными звеньями.

2) Составление схемы доступности

Клиент и Сервер находятся за NAT, поэтому недоступны извне с Прокси, но Прокси пингуется как с Клиента, так и с Сервера

3) Выбор звена для создания туннеля

Для обеспечения связи между Клиентом и Сервером достаточно одного туннеля — либо Клиент-Прокси, либо Прокси-Клиент, так как на оставшемся участке пакеты можно передать по незащищённому каналу.

Туннель Клиент-Прокси выглядит предпочтительнее, поскольку в таком случае все операции по организации связи мы смогли бы произвести с Клиента, и с него же по условиям задачи требуется работать с Сервером.

Пакеты, поступающие на вход туннеля на компьютере Клиента, передаются на Прокси и затем должны перенаправляться на адрес назначения (Destination), которым является Сервер. Однако согласно схеме доступности, Сервер недоступен с Прокси через интернет:

Поэтому для передачи пакетов не обойтись без создания второго туннеля между Прокси и Сервером:

А вот первый туннель, на который мы возлагали надежды, будет в такой схеме избыточен — мы можем направлять пакеты с Клиента на Прокси через незащищённую среду напрямую без использования туннеля:

Туннель Клиент-Прокси можно оставить лишь в том случае, если это важно с точки зрения конфиденциальности (по нему что-то передаётся открытым текстом и т.п.).

4) Выбор типа туннеля Прокси-Сервер: прямой или обратный

На самом деле тип туннеля уже предопределён. Запросы клиента поступают на порт источника (Source Port), который находится на Прокси, а туннель инициируется с Сервера. Это значит, что направление инициирования туннеля и запросов клиента будут противоположны. Следовательно туннель будет обратным (опция -R).

5) Прописывание параметров подключения и создания туннеля

Таким образом, вырисовывается следующий алгоритм построения канала связи

  1. Составить схему SSH-связности, исходя из расположения SSH-серверов
  2. Составить схему доступности.
  3. Выбрать звено: Клиент-Прокси или Прокси-Сервер (для расширенной схемы)
  4. Выбрать направление инициирования туннеля, если звено полносвязное.
  5. Выбрать тип туннеля, отталкиваясь от направления запросов клиента: прямой или обратный
  6. Написать формулы проброса портов в PuTTY (Source port, Destination и дополнительные опции) для каждого туннеля

Понимая описанные выше принципы, легко выставить правильные настройки как на вкладке SSH-Tunnels в PuTTY, так и в командной строке OpenSSH-клиента. В частности, справедливы следующие аксиомы:

Source port — это порт туннеля, на который поступают запросы Клиента.
Если направление инициирования туннеля и запросов Клиента совпадают (прямой туннель), то порт находится на том же конце, что и PuTTY и является для PuTTY локальным (опция -L, Local).
В противном случае Source port находится на противоположной стороне обратного туннеля и для PuTTY является удалённым (опция -R, Remote)
В 99% случаев Source port открывается на прослушивание на петлевом интерфейсе той машины, на которую приходят запросы от Клиента, и поэтому обычно опускается. В PuTTY для IP-адреса источника запросов даже не предусмотрено отдельного места — только Source port.

Destination — это IP-адрес и порт компьютера, на который передаются данные на выходе из туннеля. Если PuTTY находится на Destination, то это, очевидно, будет localhost.
В отличие от петлевого IP-адреса на входе туннеля, данные на выходе из туннеля могут передаваться куда угодно, в том числе на хосты с другими IP-адресами.

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

Приведу, также, синтаксис командной строки OpenSSH клиента в терминах PuTTY, если вы захотите инициировать туннель с какой-нибудь *nix-системы по базовой схеме:

ssh [-g] [-p port] : user@Сервер

и по расширенной схеме:

ssh [-g] [-p port] : user@Прокси

Здесь под понимается порт с ключами, например: -L 5000 (прямой туннель), -R 5000 (обратный туннель) или -D 5000 (динамический проброс порта; в этом случае опускается)
[-p port] — соединиться с Сервером или Прокси на порт, отличный от 22.
[-g] — опция, разрешающая подключение к локальному (Local) или динамическому (Dynamic) порту не только с localhost, но и с внешних адресов.

Для разрешения аналогичной возможности подключения к удалённому (Remote) порту с внешних адресов необходимо прописать в конфигурационном файле SSH-сервера /etc/ssh/sshd_config опцию:

GatewayPorts clientspecified

благодаря которой включение этой возможности производится по запросу клиента, либо

GatewayPorts yes

когда эта опция включена всегда.

Базовая схема

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

По этой схеме возможны 2 вида туннелей — прямой и обратный, в зависимости от того, с какой стороны выполняется инициирование SSH-сессии. Согласно этому, PuTTY всегда находится на том конце туннеля, где стрелка начинается.

Расширенная схема

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

В принципе, все четыре варианта расширенной схемы равноправны, если абстрагироваться от конкретной реализации SSH-клиента. Но коль скоро мы рассматриваем в данной статье работу через PuTTY, то инициировать туннели мы можем только с машин на базе Windows, т.е. чаще всего либо с Клиента, либо с Сервера.

Ситуации, в которых SSH-сессия с помощью PuTTY инициируется с промежуточного сервера, довольно редки, так как прокси-серверы обычно представляют собой машины без графической оболочки под управлением *nix-подобных ОС, и вместо PuTTY там будет OpenSSH.

Для полноты картины ниже рассмотрен и синтаксис OpenSSH клиента в терминах PuTTY, если вдруг вам понадобится инициировать туннель с помощью OpenSSH.

Практические примеры применения SSH-туннелей

1. Прямой туннель по базовой схеме

Рассмотрим защиту открытого протокола от перехвата на примере POP3.

Вместо того, чтобы получать почту на локальном компьютере напрямую через интернет и подвергать себя риску утраты пароля, передаваемого в открытом виде, мы получаем её через туннель с почтовым сервером на порт 110. Почтовый клиент в данном случае должен быть настроен на получение писем с адреса localhost:5000

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

Клиент# ssh -L 5000:Сервер:110 user@Сервер

Схема связности и доступности для системы с Сервером за NAT:

Это тот случай, когда вам по локальной сети нужно зайти с одного компьютера (Клиент) на другой (Сервер), но прямого соединения с ним не предусмотрено. Однако, с Сервера доступ к Клиенту имеется. Для этого SSH-сессия инициируется с Сервера, то есть с компьютера, к которому мы хотим подключиться. В результате создаётся обратный туннель.

Для поднятия обратного туннеля на Клиент необходимо установить SSH-сервер и указать, с какого удалённого порта (Remote Source port) на какой локальный для PuTTY будет выполняться проброс.

Эквивалентная команда для OpenSSH клиента:

Сервер# ssh -R 5000:localhost:3389 user@Клиент

Схема связности и доступности для системы с Клиентом за NAT:

Такая схема позволяет безопасно подключаться к интернету через непроверенные источники, например Wi-Fi точки доступа в кафе и ресторанах. Весь трафик идёт через точку доступа в зашифрованном виде с удалённого Сервера.

Как известно, браузер направляет запросы к сайтам в интернет с произвольных портов WAN-интерфейса компьютера. В PuTTY такой режим предусмотрен в в виде опции Dynamic. Все запросы браузера через туннель направляются с некоторого исходного порта 5000 на компьютере с SSH-клиентом, а на другом конце назначаются динамически. Поэтому конечный порт не прописывается.

Поскольку браузеры не умеют работать через SSH-туннели напрямую, в настройках подключения через прокси-сервер нужно выбрать подключение через SOCKS (v5) на адрес localhost:5000 и удалить localhost или 127.0.0.1 из поля «Не использовать прокси для:», если он там прописан автоматически.

Эквивалентная команда для OpenSSH клиента:

Клиент# ssh -D 5000 user@Сервер

Добавляя опцию -g, которая эквивалентна опции PuTTY «Local ports accept connections from other hosts», можно разрешить другим компьютерам подключаться к Клиенту на указанный порт и превратить его, таким образом, в точку доступа.

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

Это значит, что инициировать туннель мы можем только с Сервера. Очевидно, что на Клиенте должен быть развёрнут SSH-сервер. Для Клиентов на базе Windows хорошим выбором будет Bitvise SSH-сервер на 443 порту. FreeSSHd сервер с обратными туннелями у меня не заработал.

Итак, чтобы схема работала, нужно сделать из Сервера Socks proxy на 5000-м порту, создав туннель с самим собой:

Сервер# ssh -D 5000 user@Сервер

А после этого установить обратный туннель с Клиентом, в котором запросы на порт XXXX перенаправляются на 5000 порт нашего Socks proxy:

Сервер# ssh -R XXXX:localhost:5000 user@Клиент

Особенность такой схемы в том, что обратные туннели по цепочке можно пробрасывать и далее на другие компьютеры, не имеющие доступа в интернет.

Эта идея лежит в основе аналогичной схемы из данной статьи , но в ней туннель инициируется в обратном направлении выражением следующего вида:

Прокси# ssh -D 5000 -R XXXX:localhost:5000 user@Сервер

А уже затем к Серверу с помощью обратного туннеля подключается компьютер, не имеющий доступа в интернет:

Сервер# ssh -R YYYY:localhost:XXXX user@Компьютер

Однако в данном случае интернет-запрос на порт Сервера XXXX по обратному туннелю перенаправляется на компьютер, играющий роль Прокси-сервера, а затем возвращается на Cервер, чтобы быть обслуженным на нём же:

Очевидно, что в таком способе используется лишняя петля, состоящая из Туннелей 2 и 3, которую мы исключили выше, организовав раздачу интернета непосредственно с самого Сервера.

5. Прямой туннель на промежуточный SSH-сервер

В даном случае туннель создаётся с промежуточным Прокси-сервером, а уже с него выполняется подключение к конечному удалённому Серверу.

Такая схема выручает тогда, когда с локального компьютера нет прямого доступа в интернет, но есть доступ к некоторому серверу внутри локальной сети, который подключен к интернет. Пример схемы связности и доступности для случая, когда Клиент и Прокси находятся за NAT, а Сервер доступен из Интернета:



В другом случае Сервер находится в удалённой локальной сети и недоступен из интернета напрямую, но к нему можно подключиться через промежуточный Прокси в той же локальной сети. Возможная схема связности и доступности для случая, когда Прокси является шлюзом, а Клиент разсположен за NAT в собственной LAN:



В обоих случаях Клиенту нужно подключиться на адрес localhost:5000.

Эквивалентная команда для OpenSSH клиента:

Клиент# ssh -L 5000:Сервер:3389 user@Прокси

Эта схема уже подробно рассматривалась в самом начале:

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

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

GatewayPorts clientspecified

После этого Сервер должен стать доступным с Клиента по RDP на адрес Прокси:5000

Эквивалентная команда для OpenSSH клиента:

Сервер# ssh -R 5000:localhost:3389 user@Прокси

В данной статье будет описано как строить SSH–туннели с помощью PuTTY.

1. Локальный проброс порта

Рассмотрим следующую ситуацию. Мы находимся внутри корпоративной сети, у нашего компьютера адрес 192.168.0.2, доступ во внешний мир полностью закрыт (то есть никакого NAT–а, proxy и т.п.). Влиять на политику ограничения доступа у нас возможности нет, но зато есть SSH–доступ на один из серверов с маршрутизируемым IP–адресом, который доступен из Интернет. Внутренний адрес этого сервера, пусть будет для примера 192.168.0.3. Структура сети изображена на рисунке:

Предположим, что нам очень нужно подключиться, к примеру, по SSH на некоторый удалённый сервер с IP–адресом 212.212.212.212 где–то далеко в Интернет. Для этого запускаем PuTTY, создаём SSH–подключение к серверу 192.168.0.3 (далее по тексту SSH–сессия 1), идём в пункт Tunnels:

и указываем, что локальный порт 2222 нашего компьютера должен быть поставлен в соответствие порту 22 на сервере с IP–адресом 212.212.212.212. Далее жмём кнопку «Open», авторизуемся на сервере 192.168.0.3. Затем создаём ещё одно подключение (далее по тексту SSH–сессия 2), но уже на localhost, порт 2222 и жмём кнопку «Open»:

В результате SSH–сессия 2 будет туннелироваться (т.е. будет установлена внутри ранее установленной SSH–сессии 1). Для удалённого сервера 212.212.212.212 всё будет выглядеть так, как будто к нему подключается 111.111.111.111:

2. Удалённый проброс порта

В этом случае подключение внутри SSH–туннеля устанавливается в другую сторону - от удалённого сервера на наш локальный компьютер. Может быть полезно, если требуется открыть доступ к локальным сервисам нашего компьютера. Рассмотрим ту же сеть, что и в пункте 1, но для простоты предположим, что теперь у нас есть NAT:

Здесь уже у нас есть возможность подключаться через SSH напрямую к 212.212.212.212 благодаря наличию NAT–а. А вот 212.212.212.212 подключиться на 192.168.0.2 без специальных ухищрений, понятное дело, не сможет, т.к. 192.168.0.2 не подключён к Интернет непосредственно. Предположим, что пользователю, сидящему под X–ами на 212.212.212.212 нужно через remote desktop попасть на наш компьютер 192.168.0.2. Для этого в SSH–сеансе подключения с 192.168.0.2 на 212.212.212.212 нужно изменить настройки в разделе Tunnels следующим образом:

#lsof -i -nP | grep 3333 sshd 18598 avz 11u IPv4 592868957 TCP 127.0.0.1:3333 (LISTEN)

То есть sshd ожидает подключений на TCP–порт 3333, которые затем по SSH–туннелю будут перенаправлены на 192.168.0.2 порт 3389. И юзер сидящий за 212.212.212.212 сможет с помощью rdesktop увидеть наш рабочий стол:

3. Socks–proxy

В этом случае мы можем использовать сервер с SSH–демоном как промежуточный (proxy). Схема сети как в случае #1 (без NAT и штатных прокси):

Чтобы заставить PuTTY исполнять роль socks–прокси, нужно параметры SSH–сессии с 192.168.0.2 на 192.168.0.3 изменить следующим образом:

C:\>netstat -ano | find "1080" TCP 127.0.0.1:1080 0.0.0.0:0 LISTENING 2392 C:\>tasklist | find /i "2392" putty.exe 2392 Console 0 5420 КБ

То есть putty, выполняющийся с PID–ом 2392, начинает слушать порт 1080, ожидая подключений. Далее бёрем любое приложение, умеющее работать с SOCKS–прокси, например Firefox, и указываем ему использовать наш прокси:

Теперь все запросы от браузера будут проходить через сервер 192.168.0.3. В логах веб–сайтов, по которым мы таким образом будем ходить, будет отображаться внешний IP–адрес нашего сервера - 111.111.111.111.

P.S. Из help–файла Putty 0.58:

Question A.10.3: What does «PuTTY» mean?

It"s the name of a popular SSH and Telnet client. Any other meaning is in the eye of the beholder. It"s been rumoured that «PuTTY» is the antonym of «getty», or that it’s the stuff that makes your Windows useful… :)

Please enable JavaScript

© 2009–2019, сайт - При использовании материалов сайта желательно указывать источник. Спасибо!

Помимо своей основной функции, протокол SSH предоставляет администратору массу полезных инструментов, в этой статье речь пойдёт о создании VPN-туннеля с помощью SSH .
SSH-туннелирование - самый простой и быстрый способ получить туннель к Linux-серверу, т.к. пакет OpenSSH на нём, скорее всего, уже установлен, к тому же, полученный туннель не будет иметь проблем с NAT.

Такой туннель является простым, но не является надёжным, т.к. использует TCP-соединение и не содержит встроенных механизмов для восстановления соединения после разрыва.
SSH-туннель лучше использовать для тестирования (например, если вам нужно передавать UDP-пакеты на удалённый сервер, проброс портов по SSH в этом случае не поможет), а для постоянных туннелей использовать протоколы, специально разработанные для этого, такие как OpenVPN, PPTP, L2TP, IPSec, GRE и т.д. (Все примеры команд в статье верны для CentOS 6)

Установка и настройка

Устанавливаем пакет OpenSSH из репозиториев, если он всё ещё не установлен:

yum install openssh openssh-server openssh-clients

Для того, чтобы сервер разрешал использование туннелей, нужно включить в файле настроек OpenSSH-сервера (обычно /etc/ssh/sshd_config) опцию PermitTunnel и перезапустить OpenSSH-сервер (service sshd restart).

PermitTunnel yes

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

Host ...
или
Match ...

Опцию PermitTunnel нужно добавлять до описанных разделов.

Использование SSH-туннелей

Для всех примеров будет использоваться OpenSSH-сервер доступный по адресу 192.168.1.100.

Простой SSH-туннель

Для создания самого простого SSH-туннеля можно выполнить команду

sudo ssh -w 7:7 -l root 192.168.1.100

За создание туннеля отвечает опция

W <номер_локального_интерфейса>:<номер_удалённого_интерфейса>

Вместо номера локального и/или удалённого интерфейса можно использовать значение «any», тогда будет создан следующий по порядку незанятый TUN-интерфейс.

После прохождения аутентификации sudo и SSH на локальном и на удалённом хостах должен появиться отключенный интерфейс tun7.

Для использования туннеля нужно включить интерфейсы и настроить на них IP-адреса из одной подсети, например, так:

# на локальном хосте
# на удалённом хосте

Теперь с локального хоста будет доступ на удалённый хост по адресу 10.255.255.1 через шифрованный туннель (при условии того, что файрволы локального и удалённого хостов пропустят эти соединения).

Большим недостатком данной схемы является необходимость доступа к удалённому серверу по SSH с правами суперпользователя (т.к. для создания TUN-интерфейса требуются права суперпользователя), при этом многие системные администраторы предпочитают запрещать root-доступ по SSH для большей безопасности. Устранение этого недостатка описано в следующем пункте.

SSH-туннель с правами непривилегированного пользователя

Для того, чтобы создать SSH-туннель с правами непривилегированного пользователя, нужно предварительно создать TUN-интерфейс, принадлежащий этому пользователю (для создание TUN-интерфейса в любом случае понадобятся права суперпользователя на удалённом хосте).
Для создания TUN-интерфейса в более старых дистрибутивах Linux используется инструмент tunctl (должен быть доступен из репозиториев дистрибутива), в более новых дистрибутивах этот функционал включен в пакет iproute2. Для определения того, каким способом нужно создавать TUN-интерфейс на вашем хосте, выполните команду

Если команда выдаст ошибку

Object "tuntap" is unknown, try "ip help".

Значит нужно использовать инструмент tunctl, предварительно установив его (yum install tunctl), в противном случае, команда должна выдать список TUN/TAP-интерфейсов на хосте.

Переходим к настройке .

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

useradd ssh_tunnel

Создаём TUN-интерфейс, принадлежащий этому пользователю

С помощью tunctl:

tunctl -n -t tun7 -u ssh_tunnel -g ssh_tunnel

С помощью iproute2:

ip tuntap add dev tun7 mode tun user ssh_tunnel group ssh_tunnel

Подключение SSH-туннеля выполняется аналогично предыдущему примеру:

# на локальном хосте
sudo ssh -w 7:7 -l ssh_tunnel 192.168.1.100
ifconfig tun7 up 10.255.255.2 pointopoint 10.255.255.1
# на удалённом хосте
ifconfig tun7 up 10.255.255.1 pointopoint 10.255.255.2

Создание пользователя только для SSH-туннелирования

В данном пункте будет рассмотрен запрет использования консоли непривилегированным пользователем в то время, как SSH-туннелирование для этого пользователя будет разрешено. Установить для пользователя оболочку «/bin/false» или «/sbin/nologin» не получится, т.к. в этом случае пользователь вообще не сможет установить SSH-соединение.

Для ввода описанных ограничений нужно добавить в конец файла настроек OpenSSH-сервера (/etc/ssh/sshd_config) указанные ниже строки и перезагрузить OpenSSH-сервер (service sshd restart)

Match User ssh_tunnel
X11Forwarding no
AllowTcpForwarding yes
AllowAgentForwarding no
GatewayPorts no
ForceCommand echo "This account can only be used for tunneling"; cat

Ограничение в этом примере вводится для созданного ранее пользователя ssh_tunnel. Параметр ForceCommand заставляет пользователя автоматически выполнять команду «echo "This account can only be used for tunneling"; cat» сразу после подключения. Это не даст пользователю использовать консоль нормальным образом, т.к., если убить процесс cat нажатием Ctrl+C, SSH-соединение будет разорвано.

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

Что такое SSH туннелирование, для чего оно необходимо

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

А создать SSH туннели вам поможет технология VPN. Суть ее в том, что VPN позволяет создавать частные защищенные сети поверх уже существующих.

Именно таким образом вы и сможете внедрить в сетевой протокол туннель. Но вам для этого понадобится специальная утилита, каких хватает на данный момент в Интернете. Одна из лучших в своем роде — это SSH Tunnel Easy. С ее обзора мы и начнем.

SSH Tunnel Easy

К сожалению, в сети вы не найдете множества обзоров и мануалов по настройке этой программы. Дело в том, что она популярна за рубежом и продается там где-то за 30-50 долларов. Но в Рунете уже давным-давно есть множество «кряков», так что вы обязательно скачаете к себе на компьютер SSH Tunnel Easy.

Особенность SSH Tunnel Easy в том, что эта программа полностью решает проблему пользователя — создает SSH туннель. То есть вам не придется метаться от одного приложения к другому, так как все необходимые функции уже имеются в SSH Tunnel Easy. Программа позволяет настраивать не просто передачу данных, но автоматическую загрузку файлов через несколько каналов. В ином случае, вам бы вместо SSH Tunnel Easy пришлось бы устанавливать множество программ, которые все равно не смогли бы реализовать то, что дает рассматриваемое приложение.

SSH Tunnel Easy решает проблему с параллельными подключениями. Дело в том, что когда к серверу пытаются подключиться одновременно по нескольким параллельным каналам с запросом для передачи данных, SSH хост часто не выдерживает и виснет. SSH Tunnel Easy предотвращает зависание сервера, так как создает под каждый канал загрузки отдельный сетевой протокол. Такое хитрое решение позволит вам создать обратный и прямой туннели, которые будут разделены на несколько ветвей, в результате чего не будет долгих провисаний и сбоев в работе!

Организация туннеля и VPN при помощи OpenSSH

Если вы не хотите искать легких путей, тогда можете воспользоваться стандартной программой OpenSSH для организация туннеля загрузок по сетевому протоколу SSH. Этот способ хорошо подойдет тем, у кого установлена операционная система Ubuntu или Linux. Для начала вам необходимо инсталлировать OpenSSH. Для этого в консоле введите следующую команду: sudo aptitude install openssh-server.

Дело в том, что любой туннель, обратный, прямой и даже многоканальный, можно создать при помощи стандартных возможностей OpenSSH. Но для этого нужно разбираться в возможностях этого приложения и уметь настраивать его конфигурации. Для создания туннеля, вам нужно как минимум дать добро на туннелирование внутри файла config, который определяет настройки SSH протокола. Чтобы разрешить туннелирование, введите следующую строку в файл: PermitTunnel point-to-point. После этого вам нужно будет перезагрузить программу-сервер OpenSSH. Для этого введите следующую команду: service ssh restart.

Сразу учтите, что есть одно большое но в подобной организации туннеля. И заключается оно в том, что для подключения туннеля, вы обязаны будете зайти на хост через аккаунт суперадминистратора. А как известно, это грубое нарушение правил безопасности SSH протокола. И хоть в настройках по умолчанию root-пользователь активирован, это совсем не безопасно. Если пароль будет украден, то вы лишитесь всего — сайт буквально ограбят и выпотрошат. Потому либо делайте очень сложный шифрованный пароль, либо активируйте аутентификацию посредством публичных ключей.

После того, как вы зайдете в root-пользователя, вы сможете создать туннель посредством командной строки. Вам нужно будет прописать команду через sudo или при помощи root-a. А прописать нужно будет действие вида -w локальный_туннель:обратный_туннель. Вместо локального и обратного туннеля укажите цифры. Можно прописать два нуля — тогда будет создан туннель tun0 и для сервера, и для клиента.

Следующим шагом нужно настроить два туннеля, чтобы они могли передавать данные между собой. Вот пример настройки туннелей: для серверного туннеля — ifconfig tun0 10.0.0.1/30 pointopoint 10.0.0.2, и для клиентского — ifconfig tun0 10.0.0.2/30 pointopoint 10.0.0.1.

Но на этом еще не все. Чтобы создать автоматическую загрузку данных через туннель, его нужно указать в настройках, как шлюз по умолчанию. Но в таком случае потеряется путь к DNS и серверу. Потому текущие шлюзы нужно прописать в таблице маршрутизации через команду route add -host XX.XX.XX.XX gw ЧЧ.ЧЧ.ЧЧ.ЧЧ (ХХ — это IP DNS в одной строке, и IP сервера в другой; а ЧЧ — это в обоих командах IP текущего шлюза, который нужно удалить).

Теперь удаляем текущий шлюз и добавляем новый. Удаляем при помощи строки route del default. А прописываем новый при помощи аналогичной функции: route add default gw 10.0.0.1 (в вашем случае IP может быть другим, смотря что указывали при создании туннеля).

После определения таких настроек, все, что идет не по стандартным каналам, автоматически перенаправляется на защищенный сетевой протокол по туннелю. То есть таким образом был создан автоматический туннель, пропускающий через себя все данные и трафик. Но остается еще одна проблема — на сервер трафик попадает, но дальше с ним ничего не происходит. А все потом, что необходимо настроить трансляцию сетевых адресов NAT для SSH клиента. Чтобы это реализовать нужно добавить новое правило: iptables -t nat -A POSTROUTING -s 10.0.0.2 -j MASQUERADE. Теперь осталось всего лишь включить ip-форвардинг через ядро и настроить его активацию каждый раз при запуске. После этого туннелирование можно считать успешным! Как видите, с OpenSSH все гораздо сложнее, но тем не менее, если постараться, то все реально.

Open VPN

Конечно, конкуренция среди программ сделала свое дело — создать VPN канал теперь можно многими средствами. Одно из таких — это Open VPN. Его также можно использовать на Linux. Итак, для того, чтобы инсталлировать Open VPN, вам потребуется зайти в терминал и ввести следующую строку: apt-get install openvpn openvpn-docs, после чего приложение загрузится и установится. Возможно, у вас будет запрошен пароль администратора.

Open VPN можно настроить по-разному, в зависимости от общей сложности задачи. К примеру, если вам нужно туннелирование между двумя компьютерами, то настройка будет очень простой, а вот если компьютеров много, то и с конфигурациями придется помучиться.

Итак, чтобы создать простой туннель между двумя компьютерами, вам нужно будет сгенерировать специальный ключ. Делается это при помощи запроса: openvpn —genkey —secret static.key. Созданный ключ нужно перенести как на сервер, так и на клиент в сгенерированную при инсталляции папку openvpn, размещенную в каталоге Etc. Внутри этой папки вам предстоит создать файл с конфигурациями, который назовете по-разному для сервера и клиента. На сервере сгененрируйте server.conf, а для клиента пропишите client.conf. Стандартные настройки файла конфигураций вы сможете найти на сайте приложения Open VPN.

После добавления специальных конфигураций, которые вы скопируете на официальном сайте Open VPN, вам нужно будет лишь запустить приложение и на сервере, и на компьютере, проверить ping по каналу и активировать постоянный автозапуск приложения после активации системы при помощи кода: chkconfig openvpn on. После этого вы уже сможете обмениваться данными между сервером и клиентом.

С одной стороны, Open VPN — это весьма удобное приложение, которое позволяет быстро сгенерировать туннель между серверами, но с другой — у вас не получится так же легко создать VPN для соединения множества клиентов с хостом. Для этого реально нужно будет прыгнуть выше головы и утонуть в настройках — настолько это сложно. Так что лучше для решения подобных задач используйте другие утилиты.

Какие еще есть способы создания прямого и обратного туннеля через SSH

Описанные методы решения данного вопроса — это не весь перечень средств, которые есть у программиста по умолчанию. Через все тот же Linux можно создать туннель несколькими способами. И сейчас мы разберем очень простой метод, как подключить компьютер к удаленному серверу, а также как настроить подключение другого компьютеру, подключенному в SSHD.

Итак, допустим вам нужно подключиться к интернет-сервису, размещенному по адресу 10.10.2.1:80. При этом хост работает через определенный домен, к примеру, site.ru. Все, что вам нужно сделать — это пробросить туннель через сервер к нужному IP-адресу. И делается это при помощи команду -f, -N и -L. Первая объясняет протоколу, что нужно будет уйти в background после активации соединения, вторая отменяет все последующие команды, третья перенаправляет соединения на определенный хост к нужному нам IP-адресу. И вот как будет звучать команда: ssh -f -N [email protected] -L 8080:10.10.2.1:80.

Как видите, это достаточно простое решение. Какой метод выберите вы — это зависит от поставленных задач и ваших навыков!

От редактора AnswIT:

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

alex@Alex-PC:~$ ssh -L 127.0.0.1:8080:192.0.0.1:80 [email protected]

Если сервис доступен по адресу localhost (например, локальный SQL сервер), то и к нему
можно получить доступ:

alex@Alex-PC:~$ ssh -L
127.0.0.1:13306:127.0.0.1:3306 [email protected]

Конструкции вида -L 127.0.0.1:80:127.0.0.1:80 могут выглядеть, на первый взгляд, довольно странными. Но в них нет ничего сложного, если помнить, что решение о
маршрутизации пакета принимается на удалённой стороне туннеля. Нужно помнить основное правило: вторая пара
<адрес>:<порт> обрабатывается удалённой стороной туннеля
.
Поэтому пакет с адресом назначения 127.0.0.1 в правиле трансляции будет обработан второй стороной SSH сессии, и никак иначе.

Как вы уже, наверное, догадались, точку входа в туннель можно создавать не только на loopback интерфейсе. Если туннель нужно сделать доступным не только для локального хоста, но и для других участников сети, то в качестве адреса сокета можно указать реальный адрес интерфейса.

alex@Alex-PC:~$ ssh -L
10.0.0.5:8080:192.0.0.2:80 [email protected]

Компьютер Алекса Alex-PC имеет два сетевых интерфейса с адресами 2.2.2.2 и 10.0.0.5. В процессе установления сессии ssh откроет сокет 10.0.0.5:8080 на компьютере Alex-PC. Теперь Алекс может получить доступ к порталу 192.168.0.2:80 со своего ноутбука с адресом 10.0.0.4 и со всей
своей домашней сети 10.0.0.0/24.

Обратный SSH-туннель — выставить свои ресурсы в интернет

Как я уже говорил, точку входа в туннель можно открывать не только со стороны оригинатора ssh сессии, но и с удалённой стороны, то есть с той, к которой мы устанавливаем ssh сессию. Для этого вместо параметра -L используется параметр -R. Для чего это нужно?
Например, для того, чтобы можно было опубликовать локальный сервис для удалённого доступа.

На ноутбуке Алекса запущен Web сервер apache доступный
по адресу 127.0.0.1 с тестовой копией портала компании. Алексу нужно дать доступ к Web серверу своим
коллегам для проведения тестирования интерфейса. Вообще, для подобных целей Алексу неплохо было бы реализовать более надёжную тестовую песочницу. Но так как наш Алекс не более чем виртуальный персонаж этой статьи, он для
демонстрации работы SSH туннеля устанавливает
сессию между своим ноутбуком и маршрутизатором Linux. А с помощью параметра -R открывает порт 8080 на
внутреннем интерфейсе маршрутизатора с адресом 192.168.0.1, который ссылается на сокет 127.0.0.1:80 его тестового Web сервера.

Как видите, на маршрутизаторе процесс sshd открыл локальный сокет 8080

alex@Router:~$
sudo lsof -nPi | grep 8080

sshd
17233 alex 9u IPv4
95930 0t0 TCP 192.168.0.1:8080 (LISTEN)

Давайте посмотрим, что произойдёт с TCP пакетом, отправленным с компьютера 192.168.0.200 в сторону тестового портала, опубликованного на 192.168.0.1:8080:
1. TCP пакет с адресом источника 192.168.0.200 и адресом и портом назначения 192.168.0.1:8080 попадёт в сокет 192.168.0.1:8080, открытый процессом sshd;

2. Процесс sshd, получив пакет, в соответствии с правилом трансляции перепишет адрес и порт назначения с 192.168.0.1:8080 на 127.0.0.1:80 и отправит его внутри SSH сессии стороне-оригинатору 2.2.2.2;

3. Процесс ssh на ноутбуке Алекса, получив пакет и просмотрев адрес его назначения, перепишет адрес отправителя с 192.168.0.200 на адрес своего loopback, и отправит его в локальный сокет 127.0.0.1:80, открытый процессом apache.

Как видите, правила трансляции очень простые. Хост, который открывает сокет для туннеля, занимается трансляцией адреса и порта назначения согласно правилу трансляции. Хост с противоположной стороны туннеля производит подмену адреса и порта источника согласно своей таблице маршрутизации. Таблица маршрутизации необходима, во-первых, для того чтобы отправить пакет в нужную сторону, а, во вторых, для того чтобы произвести
подмену адреса источника на адрес интерфейса, с которого будет отправлен пакет.
Одно важное замечание, которое я оставил на конец статьи.
Если при открытии точки входа в туннель используется localhost вместо адреса реального интерфейса, то его можно опустить, сократив, таким образом, команду с

alex@Alex-PC:~$ ssh -L 127.0.0.1:8080:192.0.0.1:80 [email protected]

alex@Alex-PC:~ssh -L
8080:192.0.0.1:80 [email protected]

Эта важная особенность синтаксиса пригодится нам в следующем примере.

Двойное туннелирование

Давайте посмотрим на чуть более сложный пример. Пользователю SQL-Tester, находящемуся за NAT, нужно получить доступ к базе данных на SQL сервере, который тоже находится за NAT. SQL-Tester не может установить
соединение напрямую к серверу, так как в NAT серверной сети нет соответствующих трансляций. Однако от обоих хостов можно установить SSH сессию с промежуточным
сервером 3.3.3.3.

С SQL сервера устанавливаем SSH соединение с сервером 3.3.3.3 и открываем на loopback интерфейсе сервера
3.3.3.3 порт 13306, ссылающийся на локальный сервис SQL, запущенный на локальном сокете 127.0.0.1:3306 SQL сервера:

dbuser@SQL-server:~$ ssh -R 13306:127.0.0.1:3306
[email protected]

Теперь с клиентского хоста SQL-Tester устанавливаем соединение с 3.3.3.3 и открываем порт 3306 на loopback интерфейсе клиента, который, в свою очередь, ссылается на 127.0.0.1:13306 на сервере
3.3.3.3, который… ссылается на 127.0.0.1:3306 на SQL сервере. Всё просто J

tester@SQL-Tester:~$ ssh -L
3306:127.0.0.1:13306 [email protected]

Динамический туннель — SSH как Socks-прокси

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

Создаём сокет динамического туннеля 127.0.0.1:5555 на хосте client внутри сессии SSH к серверу 2.2.2.2

user@client:~$ ssh -D 5555 [email protected]

Проверяем, что порт открыт

user@client:~$ sudo lsof -nPi | grep 5555

ssh
7284 user 7u
IPv4 0x74fcb9e03a5ef5b1 0t0 TCP 127.0.0.1:5555 (LISTEN)

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

Теперь весь трафик браузера будет идти через SOCKS прокси внутри шифрованного соединения SSH
между хостами 1.1.1.1 и 2.2.2.2.

Как использовать SSH в Microsoft Windows?

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

С некоторых пор, имеется возможность использовать Windows не только в качестве клиента SSH. Есть возможность .

В каких случаях использовать SSH-туннели?

Конечно же, для создания постоянных туннелей на боевых серверах нужно использовать специальное программное обеспечение. Но для быстрого решения задачи по пробросу портов, траблшутинга, получения быстрого удалённого доступа да и вообще решения конкретной задачи “здесь и сейчас” зачастую хорошим подспорьем будет использование SSH туннелей.

С их помощью можно выстраивать целые сети, туннели внутри туннелей, комбинировать типы туннелей. Это может позволять быстро получать доступ туда, куда, казалось бы попасть невозможно.



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: