Задача
Обеспечить доступ из «везде где есть интернет» к некоему ПО. Шифровать траффик между клиентской и серверной частью приложения, которое не умеет работать через 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. Тестируем. Можно попробовать подключится с запрещенным сертификатом.
Полезные материалы
- stunnel(8) manual. Без комментариев;
- Защита сетевых сервисов с помощью stunnel на opennet.ru. Большая, полезная статья. Автор подробно разбирает несколько сценариев применения stunnel. Must read;
- OpenSSL xgu.ru. Много полезной информации об openssl. Скрипт certlink.sh взят из этого источника.
Приведенные здесь инструкции полностью работоспособны. Проверено 26.12.2014 ubuntu 14.04.01, stunnel 4.53.
В данный момент работаю над парсингом логов stunnel с выводом отчетов и автоматизацией создания/управления сертификатами. Так как в последнее время мне интересен golang, реализовано будет с помощью него. Если материал на эту тему интересен — дайте знать.
