Настройка apache + modssl для работы через https


Комментарий редакции: В статье использованы материалы документа
http://strict.spb.ru/ssl.html (http://www.opennet.ru/base/sec/ssl_freebsd.txt.html)

Прелюдия

В ходе работы, возникла потребность предоставить сотрудникам организации
web-интерфейс для работы с почтой. Через некоторое время эта задача была
выполнена, web-интерфейс установлен, сотрудники с почтой работали,
однако мне не нравилось то, что работал интерфейс через обычный http
протокол. Вот я и подумал, что не кисло было бы сделать это через https,
дабы пароли не гуляли плайн текстом в сети.

В этой статье я расскажу как это сделать на базе FreeBSD с
использованием английского и русского апачей.


Немного теории
--------------

SSL, Secure Socket Layer. Криптография очень обширная тема, которая
составляет буквально тома материалов. Далее будет отображен несколько
упрощенный взгляд на то, как реализован SSL и какую роль сертификаты
играют в рассматриваемом нами случае. В силу того, что информация
намеренно упрощена, возможны небольшие неточности.

Обычный веб-траффик идет через Интернет незашифрованным. Таким образом,
любой, кто имеет доступ к нужным инструментам, может наблюдать за нужным
ему трафиком.

Очевидно, что это может привести к проблемам, особенно в тех случаях,
когда необходимы безопасность и приватность, например при работе с
кредитками или в банковских транзакциях.

Протокол SSL используется для шифрования трафика между веб-сервером и
веб-клиентом.

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

Если SSL использует криптографию с открытым ключом, для того чтобы
шифровать поток данных идущих через Интернет, зачем же тогда нужен
сертификат? Технический ответ на этот вопрос, такой, что сертификат на
самом деле не нужен . Данные зашифрованы и вряд ли могут быть
дешифрованы третьей стороной. Однако сертификаты играют важную роль в
коммуникационном процессе. Сертификат, подписанный доверенным СА
(Certificate Authority), дает гарантию, что владелец сертификата, тот за
кого он себя выдает. Без подписанного сертификата ваши данные будут
зашифрованы, однако, сервер, с которым вы контактируете может быть не
тем о котором вы думаете. Без сертификатов такие нарушения могут быть
часты.


Используем
FreeBSD 5.2.1
opensll 0.9.7d
apache13-modsll/ru-apache13-modsll


Конфигурим opensll
------------------

Инсталяцию выполняем из портов. По дифолту opensll инсталится в /usr/
local/opensll. После инсталяции именно туда нам и нужно. Открываем
opensll.cnf и начинаем править

[ CA_default ]
dir = . # Это каталог для работы с ssl
certs = $dir/ssl.crt # Это где будут лежать сертификаты
crl_dir = $dir/ssl.crl # Это где будут листы "отзывов подписей"
database = $dir/index.txt # Здесь index file для индексирования запросов на подпись
new_certs_dir = $dir/ssl.crt # Сюда будут писать новые сертификаты
certificate = $dir/gw-ca.pem # Корневой сертификат
serial = $dir/serial # Серийный номер запроса
crl = $dir/ssl.crl/gw.pem # Текущий лист отзывов подписей
private_key = $dir/ssl.key/gw-ca.key # Секретный ключ для основного сертификата
RANDFILE = $dir/ssl.key/.rand #



Инсталируем apache13-modsll
---------------------------

Предварительно деинсталируем тот апач, который сейчас установлен, иначе
апач с поддержкой ssl не захочет устанавливатся из-за конфиликта с
текущей версией. Стандартно, из портов

# make
# make install

После инсталяции в /usr/local/etc/apache должны быть дополнительние папки:
ssl.crt
ssl.csr
ssl.key
ssl.prm



Создаём "корневой" сертификат
-----------------------------

# cd /usr/local/etc/apache

Корневой сертификат является корнем дерева подписей и является как бы
самой ГЛАВНОЙ подписью.

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

# openssl req -config /usr/local/openssl/openssl.cnf -new -x509 -keyout ssl.key/gw-ca.pem -out gw-ca.pem -days 365


Вас спросят пароль - введите и запомните его. Будьте аккуратны в
ответах, ведь это потом увидят все. Если ошиблись, все можно повторить
заново. Да, не ошибитесь, CommonName - это адрес хоста без http://
Снимите пароль с ключа:

# openssl rsa -in ssl.key/gw-ca.pem -out gw-ca.key

Если вы не сможете спасти этот ключ от посягательств, то и пароль вам не
поможет. Что делает эта строка, я затрудняюсь ответить точно, но так
сделать рекомендуют:

# openssl x509 -in gw-ca.pem -out gw-ca.crt

Вот и всё - главная подпись, т.е. корневой сертификат, у вас есть. Он
подписан сам собой. Далее Следует создать два файла с некоторой
индексной информацией, создать которые openssl не может, равно как и
выдать разумное сообщение по этому поводу. Создадим индексный файл
(ключевое слово database из openssl.cnf)

# touch index.txt

Создадим файл серийных номеров (ключевое слово serial из openssl.cnf):

# echo '01' > serial

Этот файл должен содержать две цифры (обязательно). Если вы ещё не
создавали никаких сертификатов кроме корневого, файл должен содержать 01.



Создаём сертификат сервера
--------------------------

Создание сертификатов сервера состоит из процедуры создания запроса на
попись, а затем подписания этого запроса в отличии от создания
самоподписанного корневого сертификата.

Создаём запрос на подпись нового сертификата и создаём секретный ключ к нему:

# openssl req -config /usr/local/openssl/openssl.cnf -new -keyout ssl.key/gw.pem -out ssl.csr/gw.pem

Вводя даные, учтите, что поле Common Name должно содержать полностью
определённое доменное имя (FQDN) того сайта, где вы будете использовать
https-протокол, чтобы броузеры не выдавали предупреждения о неверности
имени.

# openssl rsa -in ssl.key/gw.pem -out gw.key

Подпишите запрос (подписка запроса и есть создание нового сертификата)
своим корневым сертификатом:

# openssl ca -config /usr/local/openssl/openssl.cnf -policy policy_anything -out ssl.crt/gw.pem -infiles ssl.csr/gw.pem

Подготовьте сертификат к использованию:

# openssl x509 -in ssl.crt/gw.pem -out ssl.crt/gw.crt

Незабудем сделать chmod 400 на все сгенирированые ключи и сертификаты



Настройка Apache
----------------

Открываем httpd.conf и вместо сторочки SSLPassPhraseDialog builtin пишем
(потом станет ясно для чего)

SSLPassPhraseDialog exec:/usr/local/etc/rc.d/startssl.pl

В моём случае апач держит на этом сервере несколько виртуальных сайтов.
Для каждого сайта есть свой файл-конфиг. Посему в httpd.conf
комментарим все, что касается SLL для виртуальных сайтов. А в
файле-конфиге сайта дописываем следующее:

SSLEngine on
SSLCertificateFile /usr/local/etc/apache/ssl.crt/gw.crt
SSLCertificateKeyFile /usr/local/etc/apache/ssl.key/gw.key
SSLCACertificateFile /usr/local/etc/apache/gw-ca.crt
SSLLog /var/log/apache/ssl/ssl.log
SSLLogLevel warn
<Directory />
SSLOptions +StdEnvVars
....
</Directory>
SetEnvIf User-Agent ".*MSIE.*"
nokeepalive ssl-unclean-shutdown
downgrade-1.0 force-response-1.0

Организация автоматического запуска апача Все правильно! Теперь вы
готовы чтоб запустить апач. Однако дело в том, что при выполнении
apachectl startssl у вас запросят пароль. Ввести нужно второй пароль,
тоесть тот, который вы задавали при создании сертификата сервера. Если
все ОК, то апач стартанет, и в процессах вы увидете:

5163 ?? Ss 0:04.36 /usr/local/sbin/httpd -DSSL
5164 ?? IW 0:00.00 /usr/local/sbin/httpd -DSSL
5165 ?? IW 0:00.00 /usr/local/sbin/httpd -DSSL
5166 ?? IW 0:00.00 /usr/local/sbin/httpd -DSSL
5167 ?? IW 0:00.00 /usr/local/sbin/httpd -DSSL
5168 ?? IW 0:00.00 /usr/local/sbin/httpd -DSSL
5171 ?? IW 0:00.00 /usr/local/sbin/httpd -DSSL

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

# cd /usr/local/etc/rc.d
# vi startssl.pl

#!/usr/bin/perl
print "<пароль для сертификата сервера > ";

# chmod 550 startssl.pl

Хотя есть еще второе, более элегантное решение подстановки пароля. В
httpd.conf раскомментариваем сторочку SSLPassPhraseDialog builtin, а
SSLPassPhraseDialog exec:/usr/local/etc/rc.d/startssl.pl можно удалить.
Незабудем удалить startssl.pl

# cd /usr/local/etc/apache/ssl.key
# cp gw.key gw.key.org
# openssl rsa -in gw.key.org -out gw.key

Далее apachectl startssl должен пройти гладко, без всякого упоминания о
вводе пароля

Все, начинаем радоватся :-)


P.S.
Пока вы не разберётесь в работе SSL, нельзя считать соединение
безопасным. В данном случае представлен быстрый вариант настройки, не
дающий никаких гарантий. Практически - это защита от дурака, которой
тоже пренебрегать не следует.

Берегите секретные ключи - иначе вся эта мышиная возня не имеет смысла.
Поддержка виртуальных хостов "name based" возможна не в полном варианте
- сетрификат вы не сможете сделать различными для разных "name based"
виртуальных хостов. Это связано с тем, что сначала устанавливается
SSL-туннель, а затем по нему идёт обмен данными, что определяет выбор
сертификатов до получения HTTP-запроса.

P.P.S.
Инсталяция русского Apache
Нужно было установить modssl на сервере где ранее был установлен русский
апач, и все сайты были сконфигурены с применением Charset. В этом
случае установка английского апача нам не подходит, будем ставить
русский. При выполнении стандартных make, make install апач инсталится,
но без поддержки ssl. Поэтому я выбрал другой путь, который показался
мне легче, чем какой-либо дгугой, хотя это конечно-же на любителя

# cd /usr/ports/russian/apache13-modssl
# make
# cd work/mod_ssl-2.8.16-1.3.29
# ./configure --with-apache=../apache_1.3.29 --with-ssl=/usr/local --enable-shared=ssl --with-mm=/usr/local
# cd ../apache_1.3.29/
# make
# make install

Теперь уже точно все :-)
Удачи!

Обновлено: 13.03.2015