Pull to refresh

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

Reading time6 min
Views112K
Задача

Обеспечить доступ из «везде где есть интернет» к некоему ПО. Шифровать траффик между клиентской и серверной частью приложения, которое не умеет работать через 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, реализовано будет с помощью него. Если материал на эту тему интересен — дайте знать.
Tags:
Hubs:
+2
Comments15

Articles

Change theme settings