Stunnel на сервере и клиенте

Задача

Обеспечить доступ из «везде где есть интернет» к некоему ПО. Шифровать траффик между клиентской и серверной частью приложения, которое не умеет работать через SSL. Так же нужно иметь возможность ограничивать доступ некоторым пользователям при необходимости. По различным причинам основные реализации VPN отпали. В процессе поиска решения наткнулся на Stunnel, который идеально подошел. В данной статье постараюсь детально описать процесс настройки.

Статья по большей части составлена из рабочих заметок в довесок с претензиями на туториал, поэтому прошу спокойно относится к капитанству вида — «Первое, что мы сделаем — обновим систему».

Общее представление схемы работы:
ПО клиент (windows) > Stunnel > Интернет > Stunnel > ПО Сервер (linux)


Система: свежеустановленная ubuntu server 14.04 x64.

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

Приступим

Первое, что мы сделаем — обновим систему:

sudo apt-get update
sudo apt-get upgrade

Настроим и включим ufw:

sudo ufw allow 22/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Установим stunnel:

sudo apt-get install stunnel4

При установке создаются:
— пользователь и группа stunnel4;
— интересные нам каталоги:
  • /var/lib/stunnel4 здесь будет chroot окружение
  • /etc/stunnel любой файл в этом каталоге оканчивающийся на .conf будет считаться конфигом
  • /usr/share/doc/stunnel4/examples с примером конфига внутри


Проведем некоторые подготовительные мероприятия.

Разрешим автозапуск. В файле /etc/default/stunnel4 заменим ENABLED=0 на ENABLED=1:

sudo nano /etc/default/stunnel4

Создадим папки для клиентских сертификатов. certs — разрешенные, crls — запрещенные (отозванные). О самих сертификатах чуть позже.

sudo mkdir /var/lib/stunnel4/certs
sudo mkdir /var/lib/stunnel4/crls

Создадим лог-файл и сменим владельца.

Я не считаю размещение логов в месте отличном от /var/log хорошей идеей, но заставить stunnel писать логи за пределы окружения мне не удалось.

sudo touch /var/lib/stunnel4/stunnel.log
sudo chown stunnel4:stunnel4 /var/lib/stunnel4/stunnel.log

Я буду использовать свой конфиг, но если он вам не подходит можно взять пример в /usr/share/doc/stunnel4/examples

Создадим конфигурационный файл:

sudo nano /etc/stunnel/stunnel.conf

Со следующим содержимым:

; **************************************************************************
; * Global options                                                         *
; **************************************************************************

; Каталог chroot окружения.
chroot = /var/lib/stunnel4/
setuid = stunnel4
setgid = stunnel4

; Создается в окружении
pid = /stunnel4.pid

; Уровень болтливости
debug = 7
; Лог-файл
output = /stunnel.log
; Не использовать syslog
syslog = no


; **************************************************************************
; * Service defaults may also be specified in individual service sections  *
; **************************************************************************

; Сертификат/ключ сервера 
cert = /etc/stunnel/servercert.pem
key = /etc/stunnel/serverkey.pem

; Проверка сертификата. 0 - не проверять, 1 - проверять при наличии, 2 - проверять всегда, ...
verify = 2

; Каталог для разрешенных сертификатов. 
; Находится в окружении. Для каждого сертификата должна быть хэш-ссылка
CApath = /certs

; Каталог для запрещенных (отозванных) сертификатов. 
; Находится в окружении. Для каждого сертификата должна быть хэш-ссылка
CRLpath = /crls

; Не использвать SSLv2
options = NO_SSLv2

; **************************************************************************
; * Service definitions (remove all services for inetd mode)               *
; **************************************************************************


[ssh]
; Принимать соединения на интерфейс:порт или просто порт. Например accept = 192.168.0.1:443
accept = 443
; Отдавать приложению на интерфейс:порт или просто порт. Например connect = 127.0.0.1:22
connect = 22


Ключи и сертификаты

Не большое отступление. В нашем случае stunnel проверяет только корректность пары сертификат/ключ и наличие сертификата в разрешенных или запрещенных. Самоподписанного сертификата более чем достаточно, и с технической стороны (stunnel) и со стороны поставленной задачи. Нет никакого смысла заморачиваться с собственным CA или с присутствием корневого сертификата в списке доверенных на клиенте или сервере.

Нам нужны пары сертификат/ключ для сервера и каждого клиента.

C помощью openssl создадим пару для сервера:

sudo openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout serverkey.pem -out servercert.pem

Отвечаем на вопросы:

Generating a 1024 bit RSA private key
....................++++++
..............................++++++
writing new private key to 'serverkey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:MyProvince
Locality Name (eg, city) []:MyCity
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany
Organizational Unit Name (eg, section) []:IT dep
Common Name (e.g. server FQDN or YOUR name) []:server
Email Address []:

И переместим их по назначению:

sudo mv serverkey.pem /etc/stunnel/
sudo mv servercert.pem /etc/stunnel/

Как и где хранить клиентские сертификаты с ключами (за исключением каталогов certs и crls созданных ранее) решать вам. Я просто создам каталог clients в домашней директории своего пользователя и буду хранить их там на первых порах.

Создадим каталог и перейдем в него:

mkdir /home/myuser/clients
cd /home/myuser/clients

Создадим пару для клиента:

sudo openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout clientkey.pem -out clientcert.pem

Как и при создании сертификата для сервера отвечаем на вопросы. Common Name будет другим например client.

Создадим еще одну пару:

sudo openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout dnclientkey.pem -out dnclientcert.pem


Предположим, что clientcert.pem сертификат клиента которому доступ разрешен, а dnclientcert.pem сертификат клиента которому доступ запрещен. Скопируем сертификаты по нужным директориям.

sudo cp clientcert.pem /var/lib/stunnel4/certs
sudo cp dnclientcert.pem /var/lib/stunnel4/crls

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

nano /home/myuser/certlink.sh

Со следующим содержимым:

#!/bin/sh
#
# usage: certlink.sh filename [filename ...]

for CERTFILE in "$@"; do
  # Убедиться, что файл существует и это сертификат
  test -f "$CERTFILE" || continue
  HASH=$(openssl x509 -noout -hash -in "$CERTFILE")
  test -n "$HASH" || continue

  # использовать для ссылки наименьший итератор
  for ITER in 0 1 2 3 4 5 6 7 8 9; do
    test -f "${HASH}.${ITER}" && continue
    ln -s "$CERTFILE" "${HASH}.${ITER}"
    test -L "${HASH}.${ITER}" && break
  done
done

Возможно будет более целесообразным разместить certlink.sh где нибудь в /usr/bin. Я пока не стал этого делать. Но выбор за вами.
Дадим права:

chmod +x /home/myuser/certlink.sh

Создаем ссылки:

cd /var/lib/stunnel4/certs
sudo /home/myuser/certlink.sh clientcert.pem

cd /var/lib/stunnel4/crls
sudo /home/myuser/certlink.sh dnclientcert.pem


В результате в каталогах у нас должны появится ссылки вида 7469493f.0.

Запустим stunnel:

sudo /etc/init.d/stunnel4 start


Stunnel на клиенте

На клиенте будем использовать версию stunnel аналогичную серверной. На сервере у нас 4.53. Забираем с одного из зеркал.

Если прямая ссылка перестанет работать, найти нужную версию можно так:

  • Идем на stunnel.org в Downloads;
  • В разделе Code Repositories выбираем зеркало и переходим. Например usenix.org.uk;
  • Переходим в archive;
  • Затем в 4.x;
  • Забираем нужную версию.

Скачанный файл stunnel-4.53-installer.exe устанавливать не будем, просто распакуем содержимое в каталог stunnel4. В этот же каталог скопируем сертификат и ключ клиента, и сертификат сервера.

Редактируем файл stunnel.conf. У меня он имеет следующий вид:

debug = 7
; Пара сертификат/ключ клиента
cert = clientcert.pem
key = clientkey.pem
verify = 2
; Сертификат сервера
CAfile = servercert.pem
options = NO_SSLv2

[ssh]
client = yes
accept = 127.0.0.1:22
connect = 192.168.0.1:443

Здесь debug = 7 только на момент отладки, потом можно понизить до 3 или 4. Также есть опции для «тихого режима» и сокрытия значка в трее все есть в man'e.

Запускаем stunnel.exe, и пробуем с помощью putty подключится к 127.0.0.1. Тестируем. Можно попробовать подключится с запрещенным сертификатом.

Полезные материалы



Приведенные здесь инструкции полностью работоспособны. Проверено 26.12.2014 ubuntu 14.04.01, stunnel 4.53.

В данный момент работаю над парсингом логов stunnel с выводом отчетов и автоматизацией создания/управления сертификатами. Так как в последнее время мне интересен golang, реализовано будет с помощью него. Если материал на эту тему интересен — дайте знать.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 15

    +6
    По различным причинам основные реализации VPN отпали.

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

      Тестировал следующие реализации:
      • OpenVPN — требует прав администратора со стороны клиента, что не всегда возможно.
      • IPSec L2TP — есть проблемы с подключением из-за прокси, также сложности с клиентами за общим натом
      • PPTP — не рассматривался


      Как то так.
        0
        OpenVPN — требует прав администратора со стороны клиента, что не всегда возможно.

        Оно требует только при установке, потом просто висит службой в фоне.
          0
          OpenVPN вносит изменения в таблицу маршрутизации при подключении. Без прав администратора, ему это не удается. Как вариант можно добавить пользователя в группу «Network Configuration Operators», в подробности еще одного варианта вдаваться не стал т.к. он требовал внесения изменения в реестр. Ни один из вариантов мне не подошел. Если что то упустил поделитесь, буду благодарен.
            0
            Еще раз говорю — он работает службой в фоне с нужными правами (NT AUTHORITY\SYSTEM или как там его).
              0
              Понял, почитаю. Спасибо.
          0
          Пользуюсь IPSec L2TP через мобильный интернет и WiFi в метро, полёт нормальный. // хотя нет, вру, там даже L2TP нет, просто IPSec
        +2
        а чем ssh-туннель не угодил?
          +1
          «Я не считаю размещение логов в месте отличном от /var/log хорошей идеей, но заставить stunnel писать логи за пределы окружения мне не удалось.»

          Для того и предназначен сислог и возможность у stunnel писать логи в сислог?
            0
            Stunnel по умолчанию пишет в syslog.
            Дело в том, что лог stunnel нужно парсить и на основании этих данных формировать определенные отчеты. Поэтому очень желательно иметь логи в отдельном файле.
              0
              Настройки сислога позволяют корректно по ident писать в отдельный файл. Плюс проблем с ротацией таких логов заметно меньше.
                0
                Не знал, спасибо. Обязательно посмотрю.
            0
            Для этого, насколько помню, достаточно создать в чруте сокет /dev/log, и сказать общесистемному сислогу слушать и этот сокет тоже.

            Вообще, очень много ручной работы, в более вменяемых дистрибутивах и чрут изкаробки и все каталоги на месте и логи ротируются правильно и сислог настраивается автоматически.
              0
              Отличный мануал, спасибо вам большое!
                0
                Добавлю свои пять копеек.
                1. Использование скрипта certlink.sh целесообразно, если нужно создавать хэш только для одного сертификата после добавления его в каталог. Так-то использовать утилиту c_rehash проще, но она перехэширует весь каталог.
                2. Чтобы непривилегированные пользователи (в т. ч. уязвимые процессы других служб) не смогли спереть ключ сервера, можно забрать вообще все права у файла ключа:
                sudo chmod 0 /etc/stunnel/serverkey.pem

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

              Самое читаемое