AllInfo
Main: Info Blog Temp Mail


unix 2019-07-23 16-45-21

Защита сетевых сервисов с помощью stunnel (stunnel tunnel ssl crypt freebsd linux pop3 http mysql auth cert)


From: Андрей Бешков <http://onix.opennet.ru>;
Date: Sun, 23 Feb 2008 17:02:14 +0000 (UTC)
Subject: Защита сетевых сервисов с помощью stunnel

Оригинал: http://onix.opennet.ru/content/view/34/26/
http://onix.opennet.ru/content/view/38/26/
http://onix.opennet.ru/content/view/39/26/

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

Благодаря инициативе компании Netscape стандартом де факто для задач
шифрования веб-коммуникаций стал SSL (Security Socket Layer).
Первоначально он применялся для защиты данных, передаваемых с помощью
HTTP. Годы активного использования в сфере веб-коммерции доказали
стабильность и надежность этого решения. Таким образом, возникла
защищенная версия протокола HTTP, в дальнейшем получившая название
HTTPS. Вслед за этим появились протоколы IMAPS, POP3S, SMTPS, NNTPS,
LDAPS. Они призваны со временем заменить своих небезопасных предков.

По идее, использование SSL вместо стандартного API для работы с
сетевыми сокетами должно быть довольно простым и прозрачным для
приложения. На первый взгляд, нужно всего лишь заменить в исходном
коде защищаемого приложения вызовы стандартных функций на их
SSL-аналоги и произвести перекомпиляцию. Но не тут то было, при работе
в многопоточной и многопользовательской среде приходится добавлять в
свое приложение довольно много кода поддержки SSL. На данный момент в
сети существует несколько библиотек, реализующих функции SSL. Самой
популярной из них является OpenSSL, распространяемая по открытой
лицензии.

Как я говорил ранее, переделка обычной программы в SSL-версию - уже
нетривиальный процесс, но на этом трудности не заканчиваются. К
сожалению, настройка и установка на сервере программного обеспечения,
реализующего защищенные версии протоколов, упомянутых выше, часто тоже
довольно непроста. Кроме этого, иногда встречаются ситуации, когда
производитель того или иного серверного или клиентского обеспечения,
работающего с небезопасными протоколами, канул в Лету, не успев
создать защищенных версий своих программ и оборудования. За право
пользования этими разработками когда-то были заплачены лицензионные
отчисления и, соответственно, отказаться от работы с ними экономически
невыгодно. Иногда это сделать вообще невозможно по причине того, что
ни одно из решений, предлагаемых сторонними поставщиками, не реализует
нужные функции. Но чаще всего складывается ситуация, когда безопасные
приложения от нового поставщика не удается встроить в устаревшее
оборудование и программные среды, до сих пор используемые во многих
производственных процессах и служащие нам верой и правдой.

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

Программа работает на следующих операционных системах:


* FreeBSD
* NetBSD
* OpenBSD
* GNU/Linux
* AmigaOS
* BeOS
* IBM AIX
* Mac OS X
* OpenVMS
* HP NonStop(TM) Kernel
* HP-UX
* Plan 9
* QNX
* SCO OpenServer
* SGI IRIX
* Solaris
* Tru64, он же Digital Unix, он же DEC OSF/1
* Windows 95/98/ME/NT/2000/XP


Итак, рассмотрим пример превращения небезопасных сервисов pop3, imap,
smtp в их безопасные аналоги IMAPS, POP3S, SMTPS. Представим, что у
нас есть сервер, функционирующий под управлением FreeBSD 4.10. Он
называется freebsd410.unreal.net и доступен нашему клиенту по адресу
10.10.21.134. Кроме всего прочего, на нем работают программы dkimap,
postfix, cucipop, которые и реализуют ту самую "святую троицу"
протоколов. Все они принимают входящие соединения на любом сетевом
интерфейсе. Postfix работает как резидентный демон, а остальные демоны
запускаются с помощью inetd, как только кто-нибудь попытается
присоединиться к нужным портам. Соответственно, в /etc/inetdd.conf
присутствуют следующие строки:

pop3 stream tcp nowait root /usr/local/libexec/cucipop cucipop -Y
imap stream tcp nowait root /usr/local/libexec/dkimap4 dkimap


Таким образом, картина, показываемая командой:

# netstat -na | grep LISTEN


выглядит следующим образом:

tcp4 0 0 *.25 *.*
LISTEN
tcp4 0 0 *.143 *.*
LISTEN
tcp4 0 0 *.110 *.*
LISTEN


Демоны ждут входящих соединений на портах 25, 110, 143. Что означают
эти номера, можно узнать, пролистав файл /etc/services. Кстати, стоит
убедиться, что в этом же файле есть записи, описывающие наши будущие
защищенные сервисы:

imaps 993/tcp # imap4 protocol over TLS/SSL
imaps 993/udp
pop3s 95/tcp spop3 # pop3 protocol over TLS/SSL
pop3s 995/udp spop3
smtps 465/tcp # smtp protocol over TLS/SSL (was ssmtp)
smtps 465/udp


При отправке сообщений почтовый клиент, умеющий работать с SSL,
шифрует пакеты и передает их демону stunnel. Тот в свою очередь
расшифровывает их и отдает демонам imap, pop3, smtp. А почтовые демоны
в ответ на запросы отдают данные в открытом виде stunnel, который
шифрует их и передает клиенту. При этом ни клиент, ни демоны не
догадываются о том, что общаются друг с другом через посредника.

Итак, приступаем к установке stunnel на сервер. Предварительно в
систему должен быть проинсталлирован OpenSSL, так как для правильного
функционирования stunnel требуются криптоалгоритмы, реализуемые именно
этой библиотекой. Для FreeBSD проводить инсталляцию удобнее всего из
портов.

# cd /usr/ports/security/stunnel
# make all install


По окончании сборки будет автоматически создан поль-зователь stunnel,
входящий в одноименную группу. Затем произойдет установка, и нам будет
доступен stunnel версии 4.04. Сразу же после этого система начнет
создавать секретный ключ и сертификат. Вы можете воспользоваться этим
способом и начать отвечать на задаваемые вопросы или просто нажимать
Enter и впоследствии самостоятельно создать нужные файлы. Я
предпочитаю второй способ. Создаем директорию, где у нас будут
храниться сертификаты и ключи.

# mkdir /usr/local/etc/stunnel/certs
# cd /usr/local/etc/stunnel/certs


Самостоятельно создаем ключи и сертификаты со сроком действия 1 год. В
связи с тем, что stunnel не умеет работать с ключами, защищенными
паролями, используем опцию -nodes.

# openssl req -new -x509 -days 365 -nodes -out mailserver.cert -keyout mailserver.key
Generating a 1024 bit RSA private key
................++++++
......................++++++
writing new private key to 'mailserver.key'
-----
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]:Rostov region
Locality Name (eg, city) []:Rostov-on-Don
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Tigrisha
home
Organizational Unit Name (eg, section) []:Test Lab
Common Name (eg, YOUR name) []:freebsd410.unreal.net
Email Address []:


Обратите внимание, что для заполнения поля Common Name или CN было
использовано DNS-имя сервера. Это обязательно нужно делать, иначе
почтовый клиент будет постоянно возмущаться несовпадением фактического
имени сервера и того, что записано в недрах сертификата. Также
необходимо убедиться, что на клиентском компьютере правильно работает
разрешение имени freebsd410. unreal.net. Покончив с предыдущим
пунктом, устанавливаем правильные права доступа к файлам.

# chmod 600 ./mailserver.cert ./mailserver.key


Создаем директорию, куда демон перейдет в chroot, и устанавливаем на
нее нужные права:

# mkdir /var/tmp/stunnel
# chown stunnel:stunnel /var/tmp/stunnel
# chmod 700 /var/tmp/stunnel


При запуске без параметров stunnel будет использовать файл
конфигурации /usr/local/etc/stunnel/stunnel.conf. Записываем в него
следующие строки:

# Ключи и сертификаты
cert = /usr/local/etc/stunnel/certs/mailserver.cert
key = /usr/local/etc/stunnel/certs/mailserver.key
# Директория, внутри которой будет работать демон
chroot = /var/tmp/stunnel
# Файл pid. pid = /stunnel.pid
# Имя пользователя и группа, с чьими правами будет работать демон
setuid = stunnel
setgid = stunnel
# Уровень подробности отладочных сообщений
debug = 7
# Имя файла протоколирования
output = /var/log/stunnel.log
# Описание наших сервисов
[pop3s]
accept = 10.10.21.134:995
connect = 110
[imaps]
accept = 993
connect = 143
[ssmtp]
accept = 465
connect = 127.0.0.1:25


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

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

Запускаем stunnel и смотрим, что демон пишет в /var/log/stunnel.log.
Должны увидеть что-то подобное:

2004.12.04 19:09:15 LOG5[2405:134598656]: stunnel 4.04 on
i386-portbld-freebsd4.10 PTHREAD+LIBWRAP with OpenSSL 0.9.7d 17 Mar 2004
2004.12.04 19:09:15 LOG7[2405:134598656]: Snagged 64 random bytes from /root/.rnd
2004.12.04 19:09:15 LOG7[2405:134598656]: Wrote 1024 new random bytes to /root/.rnd
2004.12.04 19:09:15 LOG7[2405:134598656]: RAND_status claims sufficient entropy for the PRNG
2004.12.04 19:09:15 LOG6[2405:134598656]: PRNG seeded successfully
2004.12.04 19:09:15 LOG7[2405:134598656]: Certificate: /usr/local/etc/stunnel/certs/mailserver.cert
2004.12.04 19:09:15 LOG7[2405:134598656]: Key file: /usr/local/etc/stunnel/certs/mailserver.key
2004.12.04 19:09:15 LOG5[2405:134598656]: FD_SETSIZE=1024, file ulimit=957 -> 467 clients allowed
2004.12.04 19:09:15 LOG7[2405:134598656]: FD 6 in non-blocking mode
2004.12.04 19:09:15 LOG7[2405:134598656]: SO_REUSEADDR option set on accept socket
2004.12.04 19:09:15 LOG7[2405:134598656]: pop3s bound to 10.10.21.134:995
2004.12.04 19:09:15 LOG7[2405:134598656]: FD 7 in non-blocking mode
2004.12.04 19:09:15 LOG7[2405:134598656]: SO_REUSEADDR option set on accept socket
2004.12.04 19:09:15 LOG7[2405:134598656]: imaps bound to 0.0.0.0:993
2004.12.04 19:09:15 LOG7[2405:134598656]: FD 8 in non-blocking mode
2004.12.04 19:09:15 LOG7[2405:134598656]: SO_REUSEADDR option set on accept socket
2004.12.04 19:09:15 LOG7[2405:134598656]: ssmtp bound to 0.0.0.0:465
2004.12.04 19:09:15 LOG7[2405:134598656]: FD 9 in non-blocking mode
2004.12.04 19:09:15 LOG7[2405:134598656]: FD 10 in non-blocking mode
2004.12.04 19:09:15 LOG7[2406:134598656]: Created pid file /stunnel.pid


Теперь нужно снова посмотреть, что нам скажет команда:

# netstat -na | grep LISTEN
tcp4 0 0 *.465 *.* LISTEN
tcp4 0 0 *.993 *.* LISTEN
tcp4 0 0 *.995 *.* LISTEN
tcp4 0 0 *.25 *.* LISTEN
tcp4 0 0 *.143 *.* LISTEN
tcp4 0 0 *.110 *.* LISTEN


Как видите, список портов, ожидающих входящие соединения, существенно
увеличился.

Самое время настроить почтовый клиент. В качестве подопытного кролика
будет использоваться Microsoft Outlook Express 6. Первым делом будут
не самолеты, о которых подумали поклонники советской эстрады, а
копирование сертификата с почтового сервера и импортирование его в
почтовый клиент. С первым заданием, я думаю, вы и сами справитесь.
Подойдет любой способ, лишь бы файл mailserver.cert оказался на
Windows-машине. В Outlook Express задействуем меню "Сервис ->
Параметры", затем выбираем вкладку "Безопасность", незамедлительно
жмем на кнопки "Сертификаты" и "Импортировать".

После этого в списке доверенных центров сертификации должно появиться
имя нашего сервера.

На этом возню с сертификатом можно считать законченной. Переходим к
настройке учетной записи. Тут тоже нет ничего сложного: нужно всего
лишь сделать все так, как изображено на следующих снимках.

После этого вся принимаемая и отправляемая почта будет шифроваться с
помощью SSL, а в файле /var/log/stunnel.log будут появляться подобные
надписи:

2004.12.04 22:40:01 LOG7[2406:134598656]: pop3s accepted FD=11 from 10.10.21.162:32872
2004.12.04 22:40:01 LOG7[2406:134598656]: FD 11 in non-blocking mode
2004.12.04 22:40:01 LOG7[2406:134600704]: pop3s started
2004.12.04 22:40:01 LOG5[2406:134600704]: pop3s connected from 10.10.21.162:32872
2004.12.04 22:40:02 LOG7[2406:134600704]: Relying on OpenSSL RSA Blinding.
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): before/accept initialization
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 read client hello A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 write server hello A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 write certificate A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 write server done A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 flush data
2004.12.04 22:40:02 LOG7[2406:134600704]: waitforsocket: FD=11, DIR=read
2004.12.04 22:40:02 LOG7[2406:134600704]: waitforsocket: ok
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 read client key exchange A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 read finished A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 write change cipher spec A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 write finished A
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept): SSLv3 flush data
2004.12.04 22:40:02 LOG7[2406:134600704]: 3 items in the session cache
2004.12.04 22:40:02 LOG7[2406:134600704]: 0 client connects (SSL_connect())
2004.12.04 22:40:02 LOG7[2406:134600704]: 0 client connects that finished
2004.12.04 22:40:02 LOG7[2406:134600704]: 0 client renegotiatations requested
2004.12.04 22:40:02 LOG7[2406:134600704]: 9 server connects (SSL_accept())
2004.12.04 22:40:02 LOG7[2406:134600704]: 9 server connects that finished
2004.12.04 22:40:02 LOG7[2406:134600704]: 0 server renegotiatiations requested
2004.12.04 22:40:02 LOG7[2406:134600704]: 1 session cache hits
2004.12.04 22:40:02 LOG7[2406:134600704]: 1 session cache misses
2004.12.04 22:40:02 LOG7[2406:134600704]: 5 session cache timeouts
2004.12.04 22:40:02 LOG6[2406:134600704]: Negotiated ciphers: AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1
2004.12.04 22:40:02 LOG7[2406:134600704]: FD 12 in non-blocking mode
2004.12.04 22:40:02 LOG7[2406:134600704]: pop3s connecting 127.0.0.1:110
2004.12.04 22:40:02 LOG7[2406:134600704]: Remote FD=12 initialized
2004.12.04 22:40:02 LOG7[2406:134600704]: Socket closed on read
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL alert (write): warning: close notify
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL write shutdown (output buffer empty)
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL alert (read): warning: close notify
2004.12.04 22:40:02 LOG7[2406:134600704]: SSL closed on SSL_read
2004.12.04 22:40:02 LOG7[2406:134600704]: Socket write shutdown (output buffer empty)
2004.12.04 22:40:02 LOG5[2406:134600704]: Connection closed: 12678 bytes sent to SSL, 10178 bytes sent to socket
2004.12.04 22:40:02 LOG7[2406:134600704]: pop3s finished (0 left)


Для того чтобы забирать письма с сервера, в данном примере
использовался POP3S, но смею вас уверить, что IMAPS будет также
надежно выполнять эту задачу. Вдоволь наигравшись с Outlook Express, я
принялся тестировать все почтовые клиенты, что были под рукой. Поэтому
могу смело заявить: как и ожидалось, Mozilla Thunderbird 0.6 и Ximian
Evolution 2.0.2 работают с SSL вполне стабильно и быстро. Единственное
нарекание стоит адресовать Kmail 1.7.1, который при использовании
защищенных протоколов стал шевелиться в несколько раз медленнее, чем
обычно. В частности, на получение тестового письма из 500 байт у него
в среднем уходило примерно 45 секунд.

The Bat, любимый многими на постсоветских просторах, тоже отлично
работает в наших условиях. Тесты, описанные ниже, проводились на
версии 3.0.1.33. Впрочем, думаю, что с большинством версий The Bat это
тоже будет работать. Итак, для того чтобы включить ночного вампира в
нашу связку, нужно установить все так же, как изображено на следующем
снимке. Удивляться тому, что вместо SSL приходится выбирать TLS, не
стоит. Главное, что такой подход работает.

При первой попытке соединения с сервером получаем следующее
предупреждение. За исключением опечаток все в нем выглядит неплохо.

Первым делом жмем "Просмотреть сертификат". И убеждаемся в том, что
он действительно принадлежит нам.

С помощью кнопки "Добавить к доверенным" завершаем процедуру. Отныне
все операции с почтой будут шифроваться с помощью этого
SSL-сертификата. Ради интереса загляните в список доверенных
сертификатов. На экране должно появиться что-то вроде следующего
снимка.

Итак, мы добились того, что данные нормально передаются по сети в
защищенном виде. Теперь осталось сделать так, чтобы никто, кроме
stunnel, не смог воспользоваться старыми версиями наших сервисов. Для
этого нужно, чтобы стандартные демоны SMTP, POP3, IMAP принимали
соединения только от 127.0.0.1. Соответственно, клиенты смогут
работать с сервером только через stunnel. В случае c postfix все
довольно просто: необходимо всего лишь установить переменную
inet_interfaces = localhost в файле main.cf и перезапустить его. А вот
с cucipop и dkimap4 есть два варианта решения проблемы. Первый -
запретить входящие соединения с помощью межсетевого экрана. Второй -
использовать tcp wrapper. О первом способе написано достаточно много
статей, поэтому давайте посмотрим, как работать с tcp wrapper. При
обнаружении нового входящего соединения inetd вызывает демона tcpd.

Тот в свою очередь просматривает файл /etc/host.allow и в зависимости
от адреса вызывающей стороны принимает решение о том, что делать с
соединением. Если соединение проходит через этот контроль, то его
передают демону, который будет в дальнейшем его обслуживать. В отличие
от межсетевого экрана, который для принятия решений оперирует адресами
и номерами портов, tcpd работает с адресами клиентов и именами
вызываемых демонов. По умолчанию в /etc/hosts.allow описано разрешение
принимать данные от любых хостов. Это нам не подходит, а значит, надо
удалить или закомментировать строку ALL : ALL : allow и добавить в
файл вот это:

cucipop : localhost 127.0.0.1 : allow
dkimap : localhost 127.0.0.1 : allow


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

tcp4 0 0 *.465 *.* LISTEN
tcp4 0 0 *.993 *.* LISTEN
tcp4 0 0 10.10.21.134.995 *.* LISTEN
tcp4 0 0 127.0.0.1.25 *.* LISTEN
tcp4 0 0 *.143 *.* LISTEN
tcp4 0 0 *.110 *.* LISTEN


После некоторого количества тестов можно понижать уровень подробности
отладочных сообщений, описываемый переменной debug в файле
/usr/local/etc/stunnel/stunnel.conf. Приемлемым значением будет цифра 3.

Кстати, если нужно, чтобы stunnel автоматически запускался после
перезагрузки машины, не забудьте переименовать
/usr/local/etc/rc.d/stunnel.sh.sample в
/usr/local/etc/rc.d/stunnel.sh. В случае, когда у нас есть клиент,
способный самостоятельно работать с SSL, все выглядит довольно просто.
А вот что делать, если такового нет? Этот и многие другие вопросы мы
обсудим в следующей статье.


===============
Часть 2

В первой части статьи мы говорили о том, как защищать сервисы с
помощью программы stunnel. SSL-шифрование данных выполняется
посредством OpenSSL. Как обычно, все, о чем шла речь, работало под
управлением FreeBSD 4.10. Чтобы проверить, как эта конструкция будет
жить на пятой ветке, я перенес тестовое окружение на FreeBSD 5.3. Так
что теперь мы будем работать на этой платформе. Процедура установки и
настройки практически ничем не отличается от того, что было описано в
первой части статьи, если, конечно, следовать официально
рекомендованному пути и ставить все из портов.

Продолжим рассмотрение новых способов применения stunnel. На
предложение шифровать http-трафик с помощью stunnel большинство
читателей, cкорее всего, посмотрит на меня с некоторой долей удивления
во взгляде, а кое кто, возможно, даже покрутит пальцем у виска. А ведь
они частично правы. Зачем использовать внешнюю утилиту, если для этой
задачи у нас есть отлично работающий Apache и mod_ssl? Но все же не
Apache единым жив администратор. Во многих организациях используется
Samba. Для облегчения жизни вместе с ней поставляется программа SWAT,
которая позволяет управлять демонами, принтерами, правами и учетными
записями пользователей с помощью веб-интерфейса. Беда в том, что в
качестве веб-сервера, отображающего интерфейс управления, используется
не Apache, а собственная разработка. С точки зрения экономии ресурсов
такое решение вполне оправданно, ведь Apache даже в самом обглоданном
состоянии все равно будет содержать в себе больше возможностей, чем
нам необходимо для выполнения задачи. На первый взгляд все очень
хорошо, но, к сожалению, реализация веб-сервера SWAT не поддерживает
никакого шифрования. А это значит, что пароли, имена, явки, адреса
конспиративных квартир и прочие секреты передаются по сети с помощью
стандартного HTTP. Переносить интерфейс на Apache лениво, да и
трудозатраты себя не оправдают, а взять на себя миссию переписывать
SWAT для поддержки SSL рискнет тоже не каждый. Невооруженным глазом
видно, что в нашем положении применение stunnel - это как раз то, что
доктор прописал.

Сразу после инсталляции SWAT вписываем директивы вызова в
/etc/services следующим образом:

swat 901/tcp # Samba web configuration tool


Ну а в /etc/inetd.conf будет такая строка:

swat stream tcp nowait/400 root /usr/local/sbin/swat swat


Это значит, что SWAT принимает входящие соединения на порт 901. Из
этой точки мы можем пойти несколькими путями. Повесить stunnel на порт
902 и соответственно на нем принимать SSL-соединения. Затем
расшифровывать данные и отдавать их на порт 901.

Тут снова есть варианты - запускать stunnel как отдельный демон или из
inetd. Если не стоит задача жесткой экономии ресурсов, то, по моему
мнению, наилучшим решением будет запуск stunnel в качестве
самостоятельного демона. Так будет проще и надежнее. Ну а в следующих
версиях программы возможность запуска stunnel из-под inetd, скорее
всего, будет полностью удалена, потому что ей мало кто пользуется.
Для приема соединений на порту 902 и передачи расшифрованных данных на
порт 901 нужно дописать в конфигурационный файл
/usr/local/etc/stunnel/stunnel.conf вот такие строки:

[swats]
accept = 902
connect = 901


Второй способ состоит в том, чтобы прикрепить swat к порту 901 на
локальной петле 127.0.0.1, а stunnel на порт 901 внешних интерфейсов.
Примеры методики, которой нужно придерживаться, приводились в
предыдущей статье. Дальнейшая механика полностью повторяет способ
номер один.

Третий способ выглядит оригинальнее. Вешаем stunnel на порт 901 и при
появлении входящих соединений самостоятельно, то есть без помощи
inetd, запускаем SWAT.

[swats]
accept = 901
exec = /usr/local/bin/swat
execargs = swat


С воплощением в жизнь этого способа могут возникнуть проблемы.
Во-первых, потому что мы работаем от имени пользователя stunnel, а
значит, и SWAT будет запущен с такими же правами. Это можно обойти с
помощью sudo. А вот вторая неувязка немного сложнее: после запуска
сервер stunnel уходит в chroot и значит не сможет работать с файлами,
находящимися за пределами /var/tmp/stunnel/. Это можно будет победить
переназначением chroot для stunnel в директорию, где живет Samba.

На этом можно завершить рассмотрение приемов обращения с stunnel,
который работает в качестве одиночного демона и общается только с
SSL-клиентами.

Теперь хотелось бы продемонстрировать методику работы для случая,
когда ни клиент, ни сервер не умеют работать с SSL. В качестве примера
будут выбраны сервер MySQL, работающий под управлением FreeBSD, и
стандартный консольный клиент MySQL под управлением Linux. Впрочем,
клиент необязательно должен быть консольным, в его качестве может
выступать любая программа, умеющая дружить с сервером MySQL через
сеть. Схема взаимодействия будет выглядеть примерно так (см. рис. 1).

На рабочей станции MySQL-клиент общается с клиентом stunnel, ждушим
входящих соединений на порту 127.0.0.1:3307. Stunnel-клиент шифрует
полученные данные и отдает их через сеть демону stunnel, работающему
на сервере баз данных. Тот, в свою очередь, расшифровывает пакеты и
передает их MySQL-серверу. Обратная цепочка работает с точностью до
наоборот.

Для простоты восприятия материала вместо создания нового
SSL-сертификата будем использовать тот, что создали в первой статье.
Сетевой адрес сервера базы данных 10.10.21.29, а рабочая станция
соответственно имеет адрес 10.10.21.75.

Как я уже говорил, рабочая станция у нас функционирует под ALT Linux.
К сожалению, в официальном репозитарии пакетов Sysyphus хранится
stunnel весьма просроченной версии. К тому же в личной переписке
человек, ответственный за сборку пакета, упомянул, что не планирует
обновлять его в ближайшее время. Поэтому придется проводить
самостоятельную компиляцию из исходников. Берем пакет с официального
сайта http://stunnel.org, распаковываем, настраиваем и собираем.

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

# tar zxvf stunnel-4.05.tar.gz
# cd stunnel-4.05
# ./configure
# make all
# make install


Создаем пользователя, от имени которого будет работать stunnel.

# adduser stunnel


И, конечно же, проверяем, что из этого вышло.

# id stunnel
uid=502(stunnel) gid=503(stunnel) groups=503(stunnel)


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

# mkdir /var/tmp/stunnel
# mkdir /usr/local/etc/stunnel/certs/


Затем копируем с сервера в папку клиента /usr/local/etc/stunnel/certs/
сертификат и ключ.

# chown stunnel:stunnel /var/tmp/stunnel/usr/local/etc/stunnel/certs/
# chmod -R 700 /var/tmp/stunnel/usr/local/etc/stunnel/certs/


Создаем файл /usr/local/etc/stunnel/mysql-client.conf следующего
содержания:

cert = /usr/local/etc/stunnel/certs/mailserver.cert
key = /usr/local/etc/stunnel/certs/mailserver.key
chroot = /var/tmp/stunnel/
pid = /stunnel.pid
setuid = stunnel
setgid = stunnel
debug = 7
output = /var/log/stunnel.log
client = yes
[mysqls]
accept = 127.0.0.1:3307
connect = 10.10.21.29:3307


А на сервере соответственно создаем
/usr/local/etc/stunnel/mysql-client.conf и вписываем в него вот это:

cert = /usr/local/etc/stunnel/certs/mailserver.cert
key = /usr/local/etc/stunnel/certs/mailserver.key
chroot = /var/tmp/stunnel
pid = /stunnel.pid
setuid = stunnel
setgid = stunnel
debug = 7
output = /var/log/stunnel.log
[mysqls]
accept = 10.10.21.29:3307
connect = 3306


Запускаем stunnel с обеих сторон:

# stunnel /usr/local/etc/stunnel/mysql-client.conf
# stunnel /usr/local/etc/stunnel/mysql-server.conf


Не забываем с помощью:

netstat -na | grep LISTEN


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

На рабочей станции пытаемся соединиться с MySQL-сервером. И, скорее
всего, получаем ошибку.

# mysql -h 127.0.0.1 -P 3307 -u root -p
ERROR 1130: Host 'localhost.unreal.net' is not allowed to connect to
this MySQL server


Дело в том, что демон stunnel после расшифровки отдает данные серверу
MySQL от имени сетевого интерфейса 127.0.0.1. Соответственно, MySQL
считает, что мы присоединяемся к нему с localhost. К сожалению, под
FreeBSD избавиться от этого никак нельзя. Для Linux выход из ситуации
есть, но о нем мы поговорим в следующей статье. Для того чтобы как-то
обойти эту неприятность, добавьте пользователя Этот адрес e-mail
защищен от спам-ботов. Чтобы увидеть его, у Вас должен быть включен
Java-Script в таблицу users и не забудьте обновить текущие привилегии

# mysql
> use mysq;
> INSERT INTO user VALUES
('localhost.unreal.net','root','Rw8304MH','Y','Y','Y','Y','Y','Y','Y',
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','',''
,'','',0,0,0);
> flush privileges;
> quit;


После этого соединение клиента MySQL с сервером должно пройти как по
маслу.

В принципе работа stunnel под Linux почти ничем не отличается от
работы под FreeBSD. Единственная загвоздка будет в том, что вместо
inetd придется использовать xinetd. Думаю, что читатель, работающий с
Linux, без труда сможет самостоятельно разобраться с этими мелкими
несходствами.

Казалось бы, мы описали все возможные применения stunnel, но на самом
деле это не так. В следующей статье поговорим о том как с помощью
stunnel проводить проверку клиентских сертификатов и о том, какие
выгоды это нам сулит.

===============
Часть 3.

Сегодня мы займемся изучением тонкостей работы механизма
аутентификации stunnel с помощью SSL-сертификатов. Плюс заодно
разберемся, для чего может пригодиться Windows-версия этой программы.
Представим, что у нас есть сервер, на котором работает Windows 2000
Advanced Server. Хотелось бы уметь удаленно управлять сервером с двух
UNIX-машин. В качестве таковых выступают рабочая станция на основе
FreeBSD 5.3 и ноутбук c ALT Linux Master 2.4. Соответственно, машины
имеют имена win2000.unreal.net, altlinux.unreal.net, freebsd53.
unreal.net и адреса 10.10.21.46, 10.10.21.29, 10.10.21.30.

Для решения поставленной задачи можно использовать несколько программ.
К примеру, Citrix ICA Client, Radmin, Rdesktop, VNC. Устанавливать и
настраивать на сервере Citrix или Terminal Server ради одного человека
смысла нет. Radmin для UNIX в природе не существует, значит, опять
пришлось бы возиться с каким-либо эмулятором. Решив не плодить
сущностей без надобности, я воспользовался последним вариантом в виде
VNC, так как бесплатен и существует для всех указанных платформ.

Реализаций протокола VNC на свете довольно много. Наиболее известны из
них RealVNC, TightVNC, t-VNC и еще несколько клонов. Некоторые, как
TightVNC и t-VNC, направлены на минимизацию сетевого трафика, другие
же, такие как RealVNC, - на использование шифрования. К сожалению, под
Windows RealVNC не бесплатна, поэтому пришлось использовать
стандартную свободную реализацию TightVNC без шифрования. Для защиты
передаваемых данных, как вы уже, наверно, догадались, будет
использоваться stunnel.

Займемся установкой нужных пакетов на Windows-сервер. Скачиваем с
сайта TightVNC: http://tightvnc.com свежий релиз программы. На
момент написания статьи была актуальна версия 1.2.9. Инсталляция
достаточно тривиальна: большую часть времени можно просто нажимать
кнопку "Далее". Затем нужно убедиться, что был выбран следующий
набор компонентов.

Разрешаем стартовать серверу VNC автоматически как системному сервису.
После этого получаем предупреждение об отсутствии пароля и на
следующем экране вводим его.

По умолчанию VNC ждет соединений на порту 5800 для стандартных
клиентов и 5900 для тех, кто использует в качестве клиента браузер.
Нажав кнопку "Advanced", получаем следующий диалог, с помощью
которого разрешаем входящие соединения только с интерфейса локальной
петли.

Таким образом, получается, что на внешнем интерфейсе входящие
соединения на порты 5800 и 5900 будет получать stunnel и после
расшифровки передавать их на соответствующий порт локальной петли.
Теперь уже можно проверить работу VNC c помощью клиента,
установленного на локальной машине. Не забываем, что присоединяться
надо по адресу 127.0.0.1. Если все работает, переходим к установке
stunnel. Сделать это можно двумя путями: либо компилировать пакет из
исходных текстов, либо взять уже готовый по адресу:
http://stunnel.org/download/binaries.html. Там же не забываем
взять реализацию OpenSSL для Windows. Полный пакет OpenSSL нам не
нужен, необходимы лишь библиотеки libeay32.dll и libssl32.dll, скачать
их можно на той же странице. Нормальным инсталлятором stunnel так до
сих пор и не обзавелся, поэтому приходится делать все вручную. Кладем
stunnel-4.05.exe в C:\Stunnel и добавляем туда же весь OpenSSL или
скачанные dll. Затем создаем директорию C:\Stunnel\certs. На этом
процедуру установки для Windows можно считать законченной. Осталось
лишь настроить stunnel, но об этом позже.

Установку stunnel и OpenSSL для FreeBSD и Linux мы обсуждали в
первой и второй частях этой статьи, поэтому останавливаться на
данном вопросе не будем. Теперь нужно поставить VNC. Для FreeBSD
устанавливаем tightVNC стандартным способом из портов. К сожалению, в
репозитарии пакетов ALT Linux пакет tightVNC отсутствует, поэтому
ставим стандартный VNC, они все равно совместимы между собой.
Пришло время создать SSL-сертификаты, с помощью которых мы будем
проводить взаимную аутентификацию клиентов и сервера. Это можно
сделать на любой из используемых нами платформ. Но все же стоит
отметить, что под Windows выполнять подобные действия неудобно из-за
бедности функционала, портированного OpenSSL.

Для остальных обсуждаемых в этой статье систем процедура практически
одинакова, все отличия обычно состоят в именах директорий,
используемых во время работы. FreeBSD хранит исполняемый файл openssl
в /usr/local/bin/openssl, а ALT Linux - в /usr/bin/openssl. Плюс к
этому вспомогательный скрипт CA.pl, представляющий для нас особую
важность, в первом случае лежит в директории /usr/local/openssl/misc,
а во втором - внутри /var/lib/ssl/misc. Впрочем, не стоит переживать:
я обязательно подробно опишу всю процедуру генерации сертификатов для
обеих систем.

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

Для начала исправляем файл openssl.cnf, дабы не набирать
нижеприведенные данные каждый раз заново при создании сертификата.

countryName_default = RU
stateOrProvinceName_default = Rostov region
localityName = Rostov-on-Don
0.organizationName_default = Tigrisha Home
emailAddress = e-mail


Во FreeBSD openssl.cnf находится в /usr/local/openssl/, а под ALT
Linux соответственно в /var/lib/ssl/.

Начнем с FreeBSD. Переходим в любую удобную директорию и выполняем
команды:

# openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout win2000key.pem -out win2000cert.pem
# openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout altlinuxkey.pem -out altlinuxcert.pem
# openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout freebsdkey.pem -out freebsdcert.pem


Большинство полей в сертификате совпадают с нашими значениями по
умолчанию, во время генерации сертификатов нам просто нужно нажимать
"Enter". Единственное, что нужно менять, - это поле CN (Common
name). Заполнять его нужно в соответствии с полным доменным именем
компьютера, для которого предназначается сертификат.

Таким образом, мы создали пару сертификат-ключ для всех наших машин.
Теперь ключ лежит в файле с суффиксом key, а сертификат соответственно
в файле с суффиксом cert. В ALT Linux все вышеприведенные команды
будут иметь тот же эффект. Хотя для этой системы есть и другой способ.
Чтобы изучить его, переходим в /var/lib/ssl/certs/ и выполняем
команды:

# make win2000.pem
# make altlinux.pem
# make freebsd.pem


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

Для того чтобы системы, соединенные с помощью stunnel, могли провести
аутентификацию, они должны доверять публичным сертификатам друг друга.
Соответственно клиенты должны доверять сертификату сервера и наоборот.
Давайте изготовим файл с доверенными сертификатами для машины win2000.

Для этого объединяем сертификаты altlinuxcert.pem и freebsdcert.pem в
файл trusted.pem.

# cat altlinuxcert.pem freebsdcert.pem > trusted.pem


Переносим файлы win2000key.pem, win2000cert.pem и trusted.pem на
Windows-машину и кладем в директорию C:\Stunnel\certs\.
Таким же образом на FreeBSD копируем файлы freebsd-key.pem и
freebsdcert.pem, а на Linux, соответственно, altlinuxkey.pem
altlinuxcert.pem. Для клиентов в качестве файла с сертификатом доверия
выступает win2000cert.pem, поэтому обязательно отправляем его на обе
машины и для единообразия переименовываем в trusted.pem. Также не
забываем на клиентских машинах положить файлы ключа и сертификатов в
/usr/local/etc/stunnel/certs/.

Стоит обратить внимание на то, что vnc может работать либо
самостоятельно, либо как подключаемый модуль веб-браузера. В первом
случае нужно проводить аутентификацию и шифровать трафик, а во втором
случае будет доступно только шифрование, потому что непонятно, как
клиентский браузер сможет предъявить свой сертификат серверу. Отсюда
делаем вывод, что на машине с Windows должно работать два независимых
демона stunnel. Один с авторизацией, другой - без.

Теперь пришло время создать конфигурационные файлы. Для Windows
содержимое vnc_server.cnf выглядит так:

cert = C:\stunnel\certs\win2000cert.pem
key = C:\stunnel\certs\win2000key.pem
CAFile = C:\stunnel\certs\trusted.pem
CRLfile = C:\stunnel\certs\crl.pem
debug = 7
output = C:\stunnel\stunnel.log
verify = 3
[vnc]
accept = 10.10.21.46:5800
connect = 127.0.0.1:5800


Конфигурация второго экземпляра stunnel, хранящаяся в vnc_server1.cnf,
соответственно такова:

[vnc-https]
cert = C:\stunnel\certs\win2000cert.pem
key = C:\stunnel\certs\win2000key.pem
debug = 7
output = C:\stunnel\stunnel.log
accept = 10.10.21.46:5900
connect = 127.0.0.1:5900


Теперь посмотрим, на что похожа конфигурация для FreeBSD.

cert = /usr/local/etc/stunnel/certs/freebsdcert.pem
key = /usr/local/etc/stunnel/certs/freebsdkey.pem
CAFile = /usr/local/etc/stunnel/certs/trusted.pem
CRLfile = /usr/local/etc/stunnel/certs/crl.pem
chroot = /var/tmp/stunnel/
pid = /stunnel.pid
setuid = stunnel
setgid = stunnel
debug = 7
output = /var/log/stunnel.log
client = yes
verify = 3
[vnc]
accept = 127.0.0.1:5800
connect = 10.10.21.46:5800


Конфигурационный файл для ALT Linux выглядит так:

cert = /usr/local/etc/stunnel/certs/altlinuxcert.pem
key = /usr/local/etc/stunnel/certs/altlinuxkey.pem
CAFile = /usr/local/etc/stunnel/certs/trusted.pem
CRLfile = /usr/local/etc/stunnel/certs/crl.pem
chroot = /var/tmp/stunnel/
pid = /stunnel.pid
setuid = stunnel
setgid = stunnel
debug = 7
output = /var/log/stunnel.log
client = yes
verify = 3
[vnc]
accept = 127.0.0.1:5800
connect = 10.10.21.46:5800


На этом можно остановиться. Перед запуском стоит обсудить особенности
конфигурационных файлов, с которыми мы еще не сталкивались. CAFile -
указывает, в каком файле хранятся доверенные сертификаты. CRLfile -
описывает имя файла, где должны находиться отозванные сертификаты.

Такая возможность полезна, к примеру, если сертификат клиента
каким-либо образом попал к злоумышленнику, и теперь нам нужно
заблокировать его. И, наконец, самая важная опция - verify. Она
определяет, каким образом при начале соединения будут проверяться
сертификаты клиента и сервера. Значением переменной должно быть число
от 0 до 3. Давайте посмотрим, что значит каждое из них.

* 0 - наличие и подлинность сертификатов не проверяется. Это
значение по умолчанию, оно также эквивалентно слову "no".


* 1 - подлинность сертификата проверяется только при наличии
такового. В случае если сертификат не проходит проверку, то
соединение будет разорвано. В то же время при отсутствии
сертификата соединение будет разрешено.


* 2 - проверяется наличие и подлинность сертификата. Если сертификат
отсутствует или в результате проверки считается фальшивым,
соединение разрывается.


* 3 - для создания соединения требуется обязательное наличие
сертификата и его присутствие в списке доверенных.


Итак, разобравшись с опциями, запускаем stunnel на всех машинах и
смотрим, что появляется в файлах stunnel.log под Windows.

2005.02.28 19:10:33 LOG5[776:724]: stunnel 4.05 on x86-pc-mingw32-gnu WIN32 with OpenSSL 0.9.7e 25 Oct 2004
2005.02.28 19:10:33 LOG7[776:1108]: RAND_status claims sufficient entropy for the PRNG
2005.02.28 19:10:33 LOG6[776:1108]: PRNG seeded successfully
2005.02.28 19:10:33 LOG7[776:1108]: Certificate: C:\stunnel\certs\win2000cert.pem
2005.02.28 19:10:33 LOG7[776:1108]: Key file: C:\stunnel\certs\win2000key.pem
2005.02.28 19:10:33 LOG7[776:1108]: Loaded verify certificates from C:\stunnel\certs\trusted.pem
2005.02.28 19:10:33 LOG5[776:1108]: WIN32 platform: 30000 clients allowed
2005.02.28 19:10:33 LOG7[776:1108]: FD 156 in non-blocking mode
2005.02.28 19:10:33 LOG7[776:1108]: SO_REUSEADDR option set on accept socket
2005.02.28 19:10:33 LOG7[776:1108]: vnc bound to 10.10.21.46:5800
2005.02.28 19:10:33 LOG7[776:1108]: vnc-https bound to 10.10.21.46:5900
2005.02.28 19:10:33 LOG7[776:1108]: FD 189 in non-blocking mode
2005.02.28 19:10:33 LOG7[776:1108]: SO_REUSEADDR option set on accept socket
2005.02.28 19:10:33 LOG7[776:1108]: vnc-https bound to 10.10.21.46:5900


Ну а для Linux записи в файле протокола должны выглядеть примерно так:

2005.02.28 10:26:08 LOG5[10323:16384]: stunnel 4.05 on i686-pc-linux-gnu PTHREAD with OpenSSL 0.9.7d 17 Mar 2004
2005.02.28 10:26:08 LOG7[10323:16384]: Snagged 64 random bytes from /root/.rnd
2005.02.28 10:26:08 LOG7[10323:16384]: Wrote 1024 new random bytes to /root/.rnd
2005.02.28 10:26:08 LOG7[10323:16384]: RAND_status claims sufficient entropy for the PRNG
2005.02.28 10:26:08 LOG6[10323:16384]: PRNG seeded successfully
2005.02.28 10:26:08 LOG7[10323:16384]: Certificate: /usr/local/etc/stunnel/certs/altlinuxcert.pem
2005.02.28 10:26:08 LOG7[10323:16384]: Key file: /usr/local/etc/stunnel/certs/altlinuxkey.pem
2005.02.28 10:26:08 LOG7[10323:16384]: Loaded verify certificates from /usr/local/etc/stunnel/certs/trusted.pem
2005.02.28 10:26:08 LOG5[10323:16384]: FD_SETSIZE=1024, file ulimit=1024 -> 500 clients allowed
2005.02.28 10:26:08 LOG7[10323:16384]: FD 6 in non-blocking mode
2005.02.28 10:26:08 LOG7[10323:16384]: SO_REUSEADDR option set on accept socket
2005.02.28 10:26:08 LOG7[10323:16384]: vnc bound to 10.10.21.75:3307


Думаю, всем понятно, что в протоколах системы FreeBSD будет написано
примерно то же, что хранится в протоколах системы Linux. Особое
внимание стоит обратить на сообщения о считывании файлов сертификатов.

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

Все должно пройти как по маслу. А в файлах протоколов соответственно
появится что-то вроде:

2005.02.26 21:48:00 LOG7[7492:16384]: vnc accepted FD=11 from 10.10.21.29:51902
2005.02.26 21:48:00 LOG7[7492:16384]: FD 11 in non-blocking mode
2005.02.26 21:48:00 LOG7[8003:32770]: vnc started
2005.02.26 21:48:00 LOG5[8003:32770]: vnc connected from 10.10.21.29:51902
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): before/accept initialization
2005.02.26 21:48:00 LOG7[8003:32770]: waitforsocket: FD=11, DIR=read
2005.02.26 21:48:00 LOG7[8003:32770]: waitforsocket: ok
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 read client hello A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 write server hello A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 write certificate A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 write certificate request A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 flush data
2005.02.26 21:48:00 LOG7[8003:32770]: waitforsocket: FD=11, DIR=read
2005.02.26 21:48:00 LOG7[8003:32770]: waitforsocket: ok
2005.02.26 21:48:00 LOG5[8003:32770]: VERIFY OK: depth=0, /C=RU/ST=Rostov region/O=Tigrisha
Home/OU=Test Lab/CN=win2000.unreal.net
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 read client certificate A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 read client key exchange A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 read certificate verify A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 read finished A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 write change cipher spec A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 write finished A
2005.02.26 21:48:00 LOG7[8003:32770]: SSL state (accept): SSLv3 flush data
2005.02.26 21:48:00 LOG7[8003:32770]: 2 items in the session cache
2005.02.26 21:48:00 LOG7[8003:32770]: 0 client connects (SSL_connect())
2005.02.26 21:48:00 LOG7[8003:32770]: 0 client connects that finished
2005.02.26 21:48:00 LOG7[8003:32770]: 0 client renegotiatations requested
2005.02.26 21:48:00 LOG7[8003:32770]: 2 server connects (SSL_accept())
2005.02.26 21:48:00 LOG7[8003:32770]: 2 server connects that finished
2005.02.26 21:48:00 LOG7[8003:32770]: 0 server renegotiatiations requested
2005.02.26 21:48:00 LOG7[8003:32770]: 0 session cache hits
2005.02.26 21:48:00 LOG7[8003:32770]: 0 session cache misses
2005.02.26 21:48:00 LOG7[8003:32770]: 0 session cache timeouts
2005.02.26 21:48:00 LOG6[8003:32770]: Negotiated ciphers: AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1
2005.02.26 21:48:00 LOG7[8003:32770]: FD 14 in non-blocking mode
2005.02.26 21:48:00 LOG7[8003:32770]: vnc connecting 127.0.0.1:5800
2005.02.26 21:48:00 LOG7[8003:32770]: remote connect #1: EINPROGRESS: retrying
2005.02.26 21:48:00 LOG7[8003:32770]: waitforsocket: FD=14, DIR=write
2005.02.26 21:48:00 LOG7[8003:32770]: waitforsocket: ok
2005.02.26 21:48:00 LOG7[8003:32770]: Remote FD=14 initialized
2005.02.26 21:49:09 LOG7[8003:32770]: Socket closed on read
2005.02.26 21:49:09 LOG7[8003:32770]: SSL write shutdown (output buffer empty)
2005.02.26 21:49:09 LOG7[8003:32770]: SSL alert (write): warning: close notify
2005.02.26 21:49:09 LOG7[8003:32770]: SSL_shutdown retrying
2005.02.26 21:49:09 LOG7[8003:32770]: SSL alert (read): warning: close notify
2005.02.26 21:49:09 LOG7[8003:32770]: SSL closed on SSL_read
2005.02.26 21:49:09 LOG7[8003:32770]: Socket write shutdown (output buffer empty)
2005.02.26 21:49:09 LOG5[8003:32770]: Connection closed: 229164 bytes sent to SSL,
188234 bytes sent to socket
2005.02.26 21:49:09 LOG7[8003:32770]: vnc finished (0 left)


Особое внимание стоит обратить на строчку со следующими символами:

VERIFY OK: depth=0, /C=RU/ST=Rostov region/O=Tigrisha Home/OU=Test
Lab/CN=win2000.unreal.net


Четко видно, как сертификат сервера был опознан клиентом.
Соответственно, в протоколах сервера можно увидеть:

VERIFY OK: depth=0, /C=RU/ST=Rostov region/O=Tigrisha Home/OU=Test
Lab/CN=freebsd53.unreal.net


Стоит отметить, что в случае, если файл crl.pem не будет содержать
сертификатов, stunnel не запустится. Все, что мы получим, - это вот
такое сообщение об ошибке:

2005.03.12 10:52:12 LOG3[5934:16384]: Error loading CRLs from
/usr/local/etc/stunnel/certs/crl.pem


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

Разобравшись с авторизацией, давайте посмотрим на еще один способ
создания сертификатов клиента и сервера. В составе пакета OpenSSL
версий выше 0.9.6 поставляется утилита CA.pl, с помощью которой
генерирование сертификатов превращается из нелегкого труда по
запоминанию длинных команд в забаву. На этот раз мы поступим в
соответствии со всеми правилами. Сначала создадим корневой сертификат
для unreal.net, а потом с помощью него заверим все клиентские
сертификаты.

# /var/lib/ssl/misc/CA.pl -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 1024 bit RSA private key
.....++++++
.......................................++++++
writing new private key to './demoCA/private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
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]:Rostov region
Locality Name (eg, city) []:Rostov-on-Don
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Tigrisha
home
Organizational Unit Name (eg, section) []:Test Lab
Common Name (eg, your name or your server's hostname) []:unreal.net
Email Address []:


В результате этих действий в файле cakey.pem появится секретный ключ,
а в cacert.pem наш корневой сертификат. Затем создаем запрос на новый
клиентский сертификат для машины altlinux.unreal.net.

# /var/lib/ssl/misc/CA.pl -newreq
Generating a 1024 bit RSA private key
......................................................................
.++++++
........................................++++++
writing new private key to 'newreq.pem'

Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
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]:Rostov region
Locality Name (eg, city) []:Rostov-on-Don
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Tigrisha
home
Organizational Unit Name (eg, section) []:Test Lab
Common Name (eg, your name or your server's hostname)
[]:altlinux.unreal.net
Email Address []:


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

# /var/lib/ssl/misc/CA.pl -sign
Using configuration from /var/lib/ssl/openssl.cnf
18596:error:0E06D06C:configuration file routines:NCONF_get_string:no
value:conf_lib.c:329:group=CA_default name=unique_subject
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Feb 8 18:39:33 2005 GMT
Not After : Feb 8 18:39:33 2006 GMT
Subject:
countryName = RU
stateOrProvinceName = Rostov region
localityName = Rostov-on-Don
organizationName = Tigrisha home
organizationalUnitName = Test Lab
commonName = altlinux.unreal.net
emailAddress = e-mail
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:

BF:01:B4:1C:AA:2C:46:8E:0B:B6:9D:70:BA:AA:D3:86:DC:8F:8A:09
X509v3 Authority Key Identifier:

keyid:F8:66:F7:4E:F9:3F:7A:C7:83:BC:0C:84:40:AD:2F:3F:FC:5A:9C:AC
DirName:/C=RU/ST=Rostov
region/L=Rostov-on-Don/O=Tigrisha home/OU=Test
Lab/CN=unreal.net/emailAddress=e-mail
serial:00
Certificate is to be certified until Feb 8 18:39:33 2006 GMT (365
days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem


После всех этих мытарств сертификат клиента находится в файле
newcert.pem. Повторяем эти шаги для остальных клиентов. При этом не
стоит забывать, что в файлы newcert.pem и newreq.pem перезаписываются
при каждом запуске CA.pl c ключами -sign и -newreq, отсюда следует,
что после завершения цикла генерации ключа и сертификата лучше
переименовывать эти файлы так, чтобы своим именем они отражали
принадлежность тому или иному клиенту. К примеру, для клиента
altlinux.unreal.net файлы должны называться altlinuxcert.pem и
altlinuxkey.pem.

Еще одно обстоятельство, о котором стоит помнить, - из файла
newreq.pem после заверения сертификата лучше всего удалять запрос на
сертификацию. Он начинается строкой -------BEGIN CERTIFICATE
REQUEST--------- и заканчивается, соответственно ----END CERTIFICATE
REQUEST----- Если этого не сделать, то некоторые версии stunnel
завершаются с ошибкой при попытке работы с таким файлом.

Итак, мы создали все необходимые сертификаты и поместили их в
trusted.pem. Конечно, не стоит забывать, что файл trusted.pem должен
быть разным для клиентов и сервера. В остальном этот способ полностью
совпадает с тем, что мы протестировали выше.

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

Поэтому давайте рассмотрим другой способ управления сертификатами. В
этом случае мы будем помещать каждый сертификат в отдельный файл.
Затем доверенные сертификаты кладем в директорию trusted, а отозванные
- в папку crl. На клиентах и сервере создаем обе папки внутри
директории certs. Затем вносим следующие изменения в конфигурационные
файлы. Вместо строк CAFile и CRLfile вписываем следующее:

Для ALT Linux:

CRLpath = /usr/local/etc/stunnel/certs/trusted/
CApath = /usr/local/etc/stunnel/certs/crl/


Для FreeBSD вносим те же изменения, что и для ALT Linux.

Для Windows:

CRLpath = C:\stunnel\certs\crl\
CApath = C:\stunnel\certs\trusted\


Если опираться в своих действиях на официальную документацию к
stunnel, то, сложив все доверенные сертификаты в папку trusted, можно
было бы попытаться запустить демонов на сервере и клиентах и
радоваться полученному результату. Но не тут то было - запуск пройдет
гладко, а вот аутентификация функционировать не будет. По крайней
мере, у меня таким способом вообще ничего не заработало. Все дело в
том, что для совместимости со специфическими особенностями stunnel
имена файлов доверенных сертификатов должны быть в особом формате. А
точнее имя файла должно соответствовать хэшу, вычисленному по
содержимому сертификата. Чтобы узнать хэш того или иного файла под ALT
Linux, нужно выполнить следующую команду:

# /var/lib/ssl/misc/c_hash /
/usr/local/etc/stunnel/certs/trusted/*.pem
b71698b3.0 => /usr/local/etc/stunnel/certs/trusted/win2000cert.pem


Таким образом, становится понятно, что файл сертификата
win2000cert.pem нужно переименовать в b71698b3.0. После того как вы
проведете подобные действия на остальных машинах, можно запускать
stunnel. Стоит отметить, что во FreeBSD утилита c_hash будет
находиться в директории /usr/local/openssl/misc. Также необходимо
обратить внимание на тот факт, что для Windows в стандартной поставке
openssl программа c_hash отсутствует. Поэтому хэши ключей нужно будет
вычислять на Linux или FreeBSD. Единственное различие будет в том, что
в файл протокола при старте записываются следующие сообщения,
касающиеся доверенных сертификатов.

2005.03.14 11:19:03 LOG7[7068:16384]: Verify directory set to /usr/local/etc/stunnel/certs/trusted/
2005.03.14 11:19:03 LOG5[7068:16384]: Peer certificate location /usr/local/etc/stunnel/certs/trusted/


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

3.143.17.175 / 2024-12-22_20-58-07 UTC.