Содержание
Stunnel это программная обертка, позволяющая спрятать в шифрованный ssl-туннель произвольный трафик.
HTTPS протокол имеет встроенный механизм ssl-туннелирования.
Особенность stunnel в том, что позволяет «обернуть» в ssl-туннель трафик совершенно любого сервиса, который не имеет встроенных средств шифрования (однако и шифрованный трафик тоже можно передать через stunnel для того, что бы замаскировать его, допустим, под обмен по https протоколу). За счет чего же достигается возможность туннелировать сетевой трафик изначально не предполагавший ни шифрования ни туннелирования? А дело в том, что на любом компьютере, где реализован TCP/IP стек протоколов, есть такая (часто неприметная и порой забываемая вовсе) вещь как localhost. Механизм туннелирования заключается в том, что stunnel:
- на клиенте: слушает порт на локальном хосте клиента и передает информацию (шифруя) на определенный порт удаленного сервера,
- на сервере: слушает порт на внешнем адресе и передает информацию (расшифровывая) на определенный порт локального хоста сервера.
При этом клиент свой запрос отправляет не на удаленный сервер, а на тот самый порт localhost-а, на котором слушает stunnel. Сервер же слушает (ждет запроса клиента) не на внешнем порту, а на локальном порту на который транслирует передачу stunnel. Посмотрите на схему (чтобы было понятнее):
Вариант без stunnel (прямое соединение без шифрования) +----------------------+ +----------------------+ | Клиентский компьютер | | Сервер | | |(запрос к ex.t.ser.ver:service_port) (слушает service_port на внешнем адресе ex.t.ser.ver)| | | приложение клиент >--+-->----->------------------------------------------------------------------------------------------------+--> приложение сервер | +----------------------+ +----------------------+
Вариант c stunnel (c шифрованием) +----------------------+ +----------------------+ | Клиентский компьютер | | Сервер | | |(запрос к localhost:s1_port) (слушает service_port на localhost сервера)| | | приложение клиент >--+-->-+ +--->----+--> приложение сервер | | | | | | | | stunnel <------------+----+ (слушает s1_port на localhost) +---<----+--< stunnel | | | < шифрование | (отправляет на s2_port ex.t.ser.ver) (слушает s2_port на ex.t.ser.ver)| | < расшифровка| | +----->-----------+-->----->------------------------------------------------------------------------------------------------+--->---+ | +----------------------+ +----------------------+
Порты s1_port и s2_port - служебные порты stunnel и могут быть выбраны произвольно (как правило s2_port выбирается таким, что бы соединение на него не блокировалось файерволами). С s1_port - никаких ограничений нет т.к. трафик фактически и не покидает клиентского компьютера (передача идет внутри стека TCP/IP протокола). Точно так же и service_port (порт приложения сервера) на сервере можно изменить со стандартного на произвольный (если нужно).
Если возникает вопрос «как же осуществляется обратный трафик?» то нужно понимать, что каждое клиентское приложение в каждом TCP-подключении открывает для передачи произвольный порт (из тех что имеют большие номера, например 50000+) и именно на этот порт stunnel возвращает расшифрованные данные клиента. На клиенте stunnel открывает для передачи на удаленный сервер еще один порт и между ним и портом s2_port собственно и устанавливается шифрованный канал. На сервере же, stunnel выступает в роли клиента и сам открывает произвольный порт (из старших номеров) для получения обратного трафика от приложения-сервера (который он шифрует перед отправкой на клиентский компьютер).
Все эти обратные порты открываются только для связи с другим портом (netstat такие порты отмечает статусом ESTABLISHED) и они не являются слушающими (LISTEN статус в выводе netstat) соединение (исходящие) от такого порта файерволом не блокируется.
И так, с механизмом встраивания stunnel в работу клиент-серверного приложения мы разобрались. Посмотрим теперь как он устанавливается и настраивается.
Установка Stunnel
Несмотря на то что настройки stunnel для сервера и клиента различаются, но устанавливается он и на сервер и на клиент одинаково:
apt-get install stunnel4
Настройка Stunnel
Настройка Stunnel на сервере
stunnel использует все файлы с расширением .conf, которые находит в каталоге /etc/stunnel как конфигурационные. В каждом файле могут быть описаны как и общие параметры настройки так и настройки для отдельных сервисов, причем в одном файле можно описать несколько сервисов.
Создадим новый конфигурационный файл:
sudo nano /etc/stunnel/stunnel.conf
В нем нам нужно указать настройки самого stunell:
# Укажем файл сертификата который будет использоваться для шифрования (его мы создадим чуть позже) cert = /etc/stunnel/stunnel.pem # Дадим директиву не использовать скомпрометированный протокол openSSL V2 options = NO_SSLv2
В принципе, этого вполне достаточно.
Дополнительно можно указать сжатие: бывает полезно кроме шифрования еще и сжать трафик, но это не обязательно если оригинальный трафик и так уже сжат.
compression = zlib
Можно еще указать путь куда будут записываться логи сервиса stunnel
output = /var/log/stunnel.log
Теперь опишем наш сервис по следующему:
[<service1>] # Укажем, что это конфигурация серверной стороны (в принципе это не обязательно - stunnel по умолчанию считает, что работает как сервер) client = no accept = <ex.t.ser.ver>:<s2_port> connect = localhost:<service_port>
В этом шаблоне нужно будет указать реальные порты приложения сервера (<service_port>) и порт на котором будет принимать соединения stunnel для этого сервиса (<s2_port>). Имя хоста или внешний IP адрес сервера (<ex.t.ser.ver>) можно и не указывать (пропустить), тогда stunnel будет слушать этот порт на всех адресах сервера. Пример для сервиса telnet будет выглядеть примерно так (stunnel будет ждать установки соединения с клиентской стороны на порту 8023)
[telnet] accept = 8023 connect = localhost:23
stunnel имеет достаточно большое количество настроек - все их мы не будем перечислять. О них можно узнать из манула на stunnel
man stunnel
Созданный файл конфигурации закрываем и сохраняем.
Кроме настройки конфигурационных файлов, нужно еще разрешить запуск stunnel. Для этого в файле /etc/default/stunnel нужно заменить
ENABLED=0
на
ENABLED=1
Теперь создадим сертификат:
cd /etc/stunnel/ sudo -s openssl genrsa -out key.pem 2048 openssl req -new -x509 -key key.pem -out cert.pem cat key.pem cert.pem >> stunnel.pem rm key.pem cert.pem exit
Созданный сертификат нужно также передать (по защищенным каналам) на клиентскую машину.
Настроенный stunnel запускаем:
service stunnel start
Настройка Stunnel на клиенте
Настройка на клиентской машине не сильно отличается от настройки на серверной машине.
Общие настройки (минимальный вариант):
# Укажем файл сертификата который будет использоваться для шифрования (не забудьте его перенести с сервера на клиента) cert = /etc/stunnel/stunnel.pem # Дадим директиву не использовать скомпрометированный протокол openSSL V2 options = NO_SSLv2
И настройки сервиса по шаблону:
[<service1>] # Укажем, что это конфигурация клиентской стороны client = yes accept = localhost:<s1_port> connect = <ex.t.ser.ver>:<s2_port>
Для telnet такая конфигурация будет выглядеть так:
[<service1>] client = yes accept = localhost:23 connect = aa.bb.cc.dd:8023
где aa.bb.cc.dd - IP адрес или DNS-имя внешнего сервера.
Настроенный stunnel разрешаем (так же как и на сервере, редактируя /etc/default/stunnel) и запускаем:
service stunnel start
Команда telnet соединения с внешним сервером по ssl-туннелированному протоколу будет выглядеть так:
telnet localhost
Соединиться по нешифрованному каналу с telnet сервером можно было бы командой
telnet aa.bb.cc.dd
Но этого делать не стоит, и особенно не стоит telnet сервис выставлять в интернет (крайне вероятно что ваш сервер очень скоро взломают хакеры).
Особенности настроек приложений при работе через stunnel
Нужно понимать, что указание в строке подключения клиента localhost вместо IP адреса или имени сервера может оказать влияние на работу сервиса.
К примеру, вы решили обернуть трафик OpenVPN в stunnel (довольно популярное решение при маскировке openVPN соединения под https трафик, для обмана умных файерволов). Для этого, в конфигурационном файле OpenVPN, строку с указанием адреса и порта сервера
remote аа.bb.cc.dd 1194
заменяем на соединение с localhost:
remote localhost <s1_port>
Но это приведет к тому, что в маршрутизацию клиента (ip route), при установлении соединения с OpenVPN сервером, будет записан маршрут не на внешний сервер, а на localhost (ведь соединение было с localhost, а не с удаленным сервером), что приведет к практически полной неработоспособности сети на клиенте (из за возникшего цикла в правилах маршрутизации).
Что бы исправить эту ситуацию нужно «вручную» прописать правильный маршрут, а неверный маршрут - удалить. Для этого в конфигурационный файл OpenVPN добавляем строки:
route аа.bb.cc.dd 255.255.255.255 net_gateway route-up "/bin/ip route del 127.0.0.1"
здесь аа.bb.cc.dd - IP адрес внешнего сервера.
Ссылки
https://www.digitalocean.com/community/tutorials/how-to-set-up-an-ssl-tunnel-using-stunnel-on-ubuntu
https://ru.wikipedia.org/wiki/Telnet