Создание туннелей. Подробное описание SSH и примеры использования туннелей. Secure Shell — безопасная передача данных

На сервере homeserver запустите autossh со следующими аргументами с тем, чтобы создать постоянный туннель SSH, действующий в направлении сервера relayserver .

Homeserver~$ autossh -M 10900 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -R 1.1.1.1:10022:localhost:22 [email protected]

Параметр "-M 10900" указывает порт на сервере relayserver , для которого будет осуществляться мониторинг и который будет использоваться для обмена тестовыми данными при контроле сессии SSH. Этот порт не должен на сервере relayserver использоваться какой-либо другой программой.

Параметр "-fN" перенаправляется в команду ssh , что позволит туннелю SSH работать в фоновом режиме.

Параметр "-o XXXX" сообщает команде ssh следующее:

  • Использовать ключ аутентификации, а не парольную аутентификацию.
  • Автоматически принимать (неизвестные) ключи хоста SSH
  • Каждые 60 секунд обмениваться сообщениями keep-alive.
  • Отправлять до трех сообщений keep-alive без получения каких-либо ответов.

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

Если вы хотите, чтобы туннель SSH автоматически поднимался при загрузке системы, вы можете в /etc/rc.local добавить указанную выше команду autossh .

Заключение

В этой статье было рассказано о том, как можно использовать обратный туннель SSH для доступа к серверу Linux, который находится за брандмауэром или шлюзом NAT, защищающего сеть от внешнего мира. Было продемонстрировано, как это сделать для случая домашней сети с помощью общедоступного виртуального частного сервера VPS. Вы должны быть внимательны при использовании этого приема для корпоративных сетей. Такой туннель может рассматриваться как нарушение корпоративной политики, поскольку он позволяет обойти корпоративные брандмауэры и может открыть корпоративные сети для внешних атак. Существует большая вероятность, что этот подход может использоваться неправильно или с заведомо плохими целями. Так всегда помнить, что прежде всего вы сами ответственны за все настройки, которые вы осуществляете.

Иногда у тех, кто пользуется сетевым протоколом 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.

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

Posted by: admin октября 17th, 2017

Как работает SSH-туннелирование



SSH туннель или SSH Port Forwarding, как его называет man(1) ssh – это опциональный функционал протокола, который работает поверх всем знакомой обычной SSH сессии. SSH туннель позволяет послать TCP пакет с одной стороны SSH соединения на другую его сторону и произвести трансляцию IP заголовка по заранее определенному правилу в процессе передачи.

Понять, как работает SSH туннель очень просто: если представить его в виде point-to-point соединения. Так же как и в PPP, любой пакет, попавший в один конец соединения, будет передан и получен на другом конце туннеля. Дальше, в зависимости от адреса получателя заданного в IP заголовке, пакет будет либо обработан принимающей стороной туннеля (если пакет предназначается непосредственно ей), либо смаршрутизирован дальше в сеть (если адресатом является другой узел сети).

Основное отличие SSH туннеля от PPP соединения в том, что в SSH туннель можно завернуть только TCP трафик. (Примечание: есть несколько хаков, как можно передать UDP через TCP-сокет внутри SSH туннеля, но это решение выходит за рамки данной статьи).

Второе отличие состоит в том, что в point-to-point соединении входящий трафик может быть инициирован с любой стороны, тогда как для SSH туннеля необходимо явно задать «точку входа» для трафика. «Точка входа» – это параметр вида <адрес>:<порт>, указывающий какой сокет открыть для входа в туннель (с локальной или удалённой стороны SSH сессии).

Кроме точки входа дополнительно нужно указать правило вида <адрес>:<порт>, по которому должен быть переписан заголовок (точнее, адрес и порт назначения) TCP пакета в процессе передачи. Точка входа может задаваться с любого конца туннеля. За этот параметр отвечают ключи –L (local) и –R (remote). Под local и remote подразумеваются стороны туннеля с точки зрения стороны-оригинатора, то есть того хоста, который устанавливает SSH сессию.

Пока выглядит немного запутанно, поэтому давайте разберём на конкретном примере.

Прямой туннель SSH - обеспечиваем доступ к серверу за NAT

Алекс работает системным администратором в маленькой компании Qwerty Cakes, занимающейся производством яблочных пирогов. Вся сеть компании находится в одном броадкаст домене 192.168.0.0/24. Для доступа в интернет используется программный маршрутизатор на базе Linux, адрес которого 192.168.0.1 со стороны сети компании и 1.1.1.1 со стороны сети Интернет. На маршрутизаторе поднят и работает демон OpenSSD, который доступен по сокету 1.1.1.1:22. Внутри сети на сервере с адресом 192.168.0.2 установлен внутренний корпоративный портал, на котором до завтрашнего утра Алексу нужно сделать изменения через Web интерфейс. Однако Алекс не хочет задерживаться на работе допоздна, он хочет получить доступ к порталу из дома со своего домашнего компьютера с адресом 2.2.2.2.

Алекс приходит домой и после ужина устанавливает следующее соединение с маршрутизатором компании:

Что произошло? Алекс установил SSH сессию между адресами 2.2.2.2 и 1.1.1.1, при этом открыв локальную «точку входа» в туннель 127.0.0.1:8080 на своем домашнем компьютере:

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

ssh 3153 alex 4u IPv4 9862 0t0 TCP 27.0.0.1:8080 (LISTEN)

Любой TCP пакет, который попадёт в сокет 127.0.0.1:8080 со стороны компьютера Алекса, будет отправлен по point-to-point соединению внутри сессии SSH, при этом адрес назначения в TCP заголовке будет перезаписан с 127.0.0.1 на 192.168.0.2, а порт с 8080 на 80.

Теперь Алексу, чтобы попасть на портал своей компании, нужно всего лишь набрать в браузере:

Как проходят сетевые пакеты внутри SSH-туннеля

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

1. TCP пакет с адресом источника 127.0.0.1 и адресом и портом назначения 127.0.0.1:8080 попал в сокет 127.0.0.1:8080, открытый процессом ssh;

2. Процесс ssh получил пакет, в соответствии с правилом трансляции переписал адрес и порт назначения на 192.168.0.2:80 и отправил его внутри SSH сессии удалённой стороне 1.1.1.1;

3. Процесс sshd на маршрутизаторе 1.1.1.1 получил пакет и, просмотрев адрес назначения, отправил его хосту 192.168.0.2, переписав при этом адрес источника с 127.0.0.1 на адрес собственного интерфейса 192.168.0.1, для того чтобы получатель, который ничего не знает про существование SSH туннеля, вернул пакет роутеру, а не отправил в свой же localhost 127.0.0.1.

alex@Alex-PC:~$ ssh -L

127.0.0.1:8080:192.0.0.2:80 [email protected]


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


Если сервис доступен по адресу 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 сервере. Всё просто.

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

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-сервер на Windows.

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

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

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

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

Очень часто, когда речь заходит об удаленном доступе к сетям с низким уровнем безопасности, первое что приходит на ум - это VPN, однако ради административных соединений поднимать VPN не всегда целесообразно, особенно если речь идет об аутсорсинге или "приходящем админе". Кроме того, не всегда условия связи позволяют поднять устойчивое VPN-соединение, особенно если приходится использовать мобильные сети.

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

Строго говоря, SSH-туннели не являются полноценными туннелями и это название следует рассматривать как сложившееся в профессиональной среде устойчивое наименование. Официальное название технологии - SSH Port Forwarding - это опциональная возможность протокола SSH, которая позволяет передать TCP-пакет с одной стороны SSH-соединения на другую и произвести в процессе передачи трансляцию IP-заголовка по заранее определенному правилу.

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

Рассмотрим работу SSH-туннеля более подробно. В качестве примера возьмем классический случай обеспечения доступа к некоторому удаленному серверу по протоколу RDP.

Допустим, что в удаленной сети существует целевой сервер с адресом 192.168.0.105, но доступа к нему из внешней сети нет, единственное устройство к которому мы можем подключиться - это маршрутизатор с адресом 192.168.0.1 с которым мы можем установить SSH-соединение.

Остановимся на очень важном моменте: все параметры SSH-туннеля устанавливает инициатор подключения, он же SSH-клиент , вторым концом туннеля всегда является сервер, к которому мы подключаемся, он же SSH-сервер . В данном контексте следует понимать клиент и сервер сугубо как стороны соединения, например, в роли SSH-клиента может выступать VPS-сервер, а в роли SSH-сервера ноутбук админа.

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

Рассмотрим схему выше. Мы установили SSH-туннель с локальной машины к удаленному маршрутизатору, указав локальную точку входа 127.0.0.1:3389 и правило трансляции 192.168.0.105:3389 . Еще раз обращаем ваше внимание, что правило трансляции не указывает на точку выхода, а определяет узел, которому будут посланы пакеты по выходу из туннеля. Если вы укажете недействительный адрес, либо узел не будет принимать соединения, то SSH-туннель установится, но доступа к целевому узлу не будет.

Согласно указанной точке входа служба SSH создаст локальный TCP-сокет, который будет ожидать подключений на порт 3389. Поэтому в окне RDP-подключения указываем в качестве назначения localhost или 127.0.0.1 , RDP-клиент открывает динамический порт и отсылает пакет с адресом назначения 127.0.0.1:3389 и адресом источника 127.0.0.1:61256 , о реальном назначении получателя пакета ему ничего не известно.

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

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

Разобравшись в общих чертах как работают SSH-туннели перейдем к практическим вариантам их использования, в качестве платформы мы будем рассматривать Linux-системы семейства Debian/Ubuntu, но все нижеизложенное с небольшими поправками будет справедливо для любой UNIX-подобной системы.

SSH-туннель с локальной точкой входа

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

Мы будем рассматривать все тот-же вариант, RDP-подключение к удаленному серверу, оранжевым пунктиром на схеме обозначено безопасное SSH-соединение, синими стрелками - обычное TCP-подключение.

В самом простом варианте мы просто устанавливаем соединение с клиентского ПК к маршрутизатору в удаленной сети, указывая в правиле трансляции целевой узел:

Ssh -L 127.0.0.1:3389:192.168.0.105:3389 [email protected]

Ключ -L указывает на то, что точка входа расположена локально, затем через двоеточие указываются адрес и порт точки входа и адрес, порт правила трансляции. Точкой выхода является узел, к которому мы подключаемся, т.е. rt.example.com .

Если в вашей сети также присутствует маршрутизатор (или иной Linux-сервер), то можно сделать точкой входа его, что позволит подключаться к удаленному серверу любому RDP-клиенту из локальной сети. В теории для этого следует поднять такой туннель:

Ssh -L 192.168.31.100:3389:192.168.0.105:3389 [email protected]

В таком случае служба SSH должна будет открыть TCP-сокет на интерфейсе 192.168.31.100, но на практике этого не произойдет. Это связано с особенностями реализации OpenSSH, который является стандартом для подавляющего большинства UNIX-подобных систем.

По умолчанию OpenSSH открывает точку входа только на локальном интерфейсе . В этом несложно убедиться:

Для того, чтобы предоставить доступ к TCP-сокету с внешних интерфейсов следует использовать ключ -g , либо добавить в конфигурационный файл /etc/ssh/sshd_config опцию:

GatewayPorts yes

Однако после этого сокет будет принимать соединения с любого сетевого интерфейса инициатора:

Это значит, что порт 3389 будет открыт на всех сетевых интерфейсах, поэтому если точка входа является пограничным устройством, то следует ограничить доступ к сокету, например, средствами iptables. Для примера заблокируем доступ из внешней сети (интерфейс eth0):

Iptables -A INPUT -i eth0 -p tcp --dport 3389 -j DROP

Таким образом рабочий туннель следует поднимать командой:

Ssh -L -g 3389:192.168.0.105:3389 [email protected]

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

Также мы советуем использовать по возможности ключ -g , а не добавление опции в конфигурационный файл, так как в последнем случае вы рискуете, забыв об этой настройке, открыть наружу доступ к незащищенным службам удаленной сети.

SSH-туннель с удаленной точкой входа

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

В первом варианте удаленный сервер сам устанавливает подключение с маршрутизатором локальной сети. Это можно сделать простой командой:

Ssh -R 3389:127.0.0.1:3389 [email protected]

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

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

GatewayPorts yes

на стороне SSH-сервера.

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

Iptables -P INPUT DROP
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i eth1 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT

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

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

Ssh -R 3389:192.168.0.105:3389 [email protected]

Снова обратим ваше внимание, что точка входа у нас располагается на противоположной стороне туннеля, поэтому трансляция указывается для стороны инициатора туннеля, т.е. в данном случае SSH-клиент устанавливает два соединения: одно SSH с rt.example.com, а второе RDP c 192.168.0.105, тогда как при туннеле с локальной точкой входа инициатор устанавливает единственное соединение с SSH-сервером.

Двойной SSH-туннель

Достаточно часто возникают ситуации, когда требуется соединить два узла не имеющих выделенных IP-адресов. В этом случае обычно используется TeamViewer или аналогичное стороннее ПО, но если у вас есть доступный сервер с выделенным IP-адресом, то можно поступить проще.

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

Туннель с локальной точкой входа на ПК админа:

Ssh -L 3389:127.0.0.1:3390 [email protected]

И туннель с удаленной точкой входа на RDP-сервере:

Ssh -R 3390:127.0.0.1:3389 [email protected]

Мы специально указали на удаленном сервере нестандартный порт для большей наглядности и теперь давайте посмотрим, как все это работает. Начнем с RDP-сервера, он поднимает туннель с удаленной точкой входа, открывая на промежуточном сервере TCP-сокет, который будет принимать подключения на порт 3390, в качестве трансляции укажем сам RDP-сервер - 127.0.0.1:3389, т.е. все пришедшие на вход этого туннеля пакеты будут направлены на локальный порт 3389.

Туннель с локальной точкой входа на ПК админа открывает локальный сокет на порт 3389, куда будет подключаться RDP-клиент, в качестве трансляции мы указываем точку входа второго туннеля - 127.0.0.1:3390.

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

Динамический SSH-туннель

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

Такой вид туннеля особенно удобен, если требуется разовый выход в интернет с другого узла. Простой пример: мой хороший знакомый привез из Штатов два операторских контрактных iPhone и попросил их разблокировать. Сложностей данная операция не таит, если условия контракта не были нарушены, то достаточно зайти на сайт оператора и заполнить заявку на разблокировку. Но проблема оказалась в том, что у оператора T-Mobile доступ к данному разделу сайта был доступен только для жителей США, а соединения с публичных прокси и VPN отвергались как небезопасные.

Динамический SSH-туннель позволил быстро решить эту проблему используя VPS в Штатах. Чтобы создать такой туннель введите команду:

Ssh -D 1080 [email protected]

Где 1080 - порт на котором будет доступен наш SOCKS-прокси. Остается только настроить браузер на использование локального прокси-сервера.

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

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

Несколько слов о безопасности

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

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

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

Ssh -N -L -g 3389:192.168.0.105:3389 [email protected]

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

SSH-туннели в Windows

На протяжении всей статьи мы рассматривали SSH-туннели на примере Linux-систем и у пользователей Windows могло сложиться впечатление, что им данные возможности недоступны. Но это не так, под Windows существует множество SSH-клиентов, которые поддерживают создание тоннелей. Мы будем рассматривать наиболее популярного из них - PuTTY . Также под Windows можно запустить и SSH-сервер, но это требует определенной квалификации и не всегда можно добиться стабильной работы, поэтому этот вариант мы рассматривать не будем.

Откроем PuTTY и в левой части дерева перейдем в Connection - SSH -Tunnels :

Перед нами откроется следующее окно, основные настройки туннеля сосредоточены внизу, и мы выделили их красной рамкой. Source port - предназначен для указания порта точки входа, которая всегда располагается на локальном интерфейсе (127.0.0.1). Destination - трансляция, т.е. куда будут отправлены пакеты с точки выхода. Радиопереключатели Local - Remote - Dynamic задают тип туннеля и аналогичны ключам -L , -R и -D .

После того, как вы заполнили все необходимые поля можно добавить туннель кнопкой Add . Чтобы разрешить внешним узлам доступ к локальному сокету точки входа установите галочку Local ports accept connections from other hosts . В данном случае следует также ограничить доступ к открытым портам средствами брандмауэра Windows или стороннего сетевого фильтра.

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

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

  • Теги:

Please enable JavaScript to view the

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

Рассмотрим создание и настройку по нескольким вариантам.

И так, у нас имеется сервер, назовём его host-1 . К нему у нас есть полный доступ только по SSH — но нам необходимо открыть Tomcat , работающий на порту 8082 — к которому нас никак пропустить не могут.

Рассматривать вариант будем с настройкой Windows и Putty .

Открываем SSH -соединение к нужному серверу, логинимся.

Указываем такие параметры:

Source port: любой неиспользуемый порт в вашей системе;
Destination port: 127.0.0.1:8082

Жмём Add , потом Apply .

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

Теперь остаётся в браузере открыть страницу http://localhost:3002 — и попадаем на страницу Tomcat на сервере host-1 .

Если туннель не работает — проверьте на сервере, включена ли пересылка пакетов. В файле /etc/ssh/sshd_config найдите и раскоментируйте строку:

AllowTcpForwarding yes

И перезапустие SSHd:

# service sshd restart Stopping sshd: [ OK ] Starting sshd: [ OK ]

Ещё один пример — у нас есть тот же внешний сервер, с которого есть нормальный доступ к любым ресурсам в Сети. А вот с рабочего места у нас доступ к и закрыт.

Выполняем похожие действия, но с небольшими отличиями. Настройки в Putty :

Source port — оставляем прежний, но вместо Local — выбираем Dynamic . Нажимаем Add , Apply .

Переходим к настройкам браузера:

Обратите внимание, что тип прокси тут не HTTP — а SOCKS .

Наслаждаемся доступом к любимым сайтам.

И более интересный случай.

Имеем прежний host-1 . Кроме него — второй сервер, назовём его host-2 . Кроме этого — у нас есть машина с Windows , которой необходимо предоставить доступ к ресурсу TeamCity на сервере host-1 на порту 8111. При этом — доступ с Windows -машины у нас есть только к серверу host-2 , и только на 22-ой порт.

Для начала — поднимаем туннель между host-1 и host-2 . Выполняем на host-1 :

$ ssh -f -N -R host-2:8082:localhost:8111 username@host-2

Так мы открываем туннель, который локально (на host-1 ) смотрит на порт 8111 , а с другой стороны — машина host-2 , на которой открывается порт 8082 , и ждёт входящих соединений. При получении пакетов на порт 8082 (при чём — только по интерфейсу lo0 ! это важно) — он будет их перенаправлять на машину host-1 порт 8111 .

Что касается интерфейса lo0 . При установлении SSH -туннеля, даже при указании внешнего IP машины — соединение поднимается только с localhost , т.е. 127.0.0.1 .

Посмотрим на host-2 :

$ netstat -anp | grep 8082 tcp 0 0 127.0.0.1:8082 0.0.0.0:* LISTEN -

Что бы изменить это — необходимо отредактировать файл конфигурации демона sshd — /etc/ssh/sshd_config и изменить параметр:

#GatewayPorts no

Но сейчас мы этого делать не будем, это просто заметка.

Продолжим. Переходим к настройке Putty на нашей Windows -машине. Тут всё просто — пользуемся примером 1 из этой статьи, только меняем порт на нужный (в скриншоте, кстати, он и есть). Подключаемся Putty к хосту host-2 , настраиваем tunnel . В браузере меняем настройки proxy — и получаем необходимое, указываем адрес http://localhost:3002:

SSH довольно чувствителен к потерям пакетов, поэтому туннели могут часто обрываться.

Что бы избежать этого — можно либо поиграться с параметрами в файле настроек sshd — /etc/ssh/sshd_config:

#TCPKeepAlive yes #ServerAliveInterval #ServerAliveCountMax

Либо — воспользоваться утилитой autossh.



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

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

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