Увод
Mod_SSL
е интерфейс на apache httpd към openssl. Той може да се използва както
за шифриране на комуникацията между уеб сървъра и клиента,
удостоверяване на идентичността на сървъра, а така и за ограничение на
достъпа до ресурсите, които предлага. В тази статия ще се опитам да
представя основите на конфигуриране на тези ограничения по начин
подобен на този, по който ще бъдат ползвани на новата машина на Linux-BG.
За подръжката на mod_ssl
mod_ssl
е стандартна част от всички дистрибуции, които предлагат apache httpd.
Особеност при Дебиан, е че пакетът се казва libapache-mod-ssl. В
дистрибуцията съществува и пакет apache-ssl, който представлява отделен
уеб сървър използващ проекта apache-ssl.org,
който проект не се разработва от години и е изместен почти навсякъде от
mod_ssl, който се зарежда като модул на основния уеб сървър.
Въпреки,
че няма разлики във функционалността на mod_ssl в 1.3.x и 2.0.x
клоновете има проблем, който прави невъзможно изпращането на POST
заявки при определени изисквания за сертификатна автентикация. Този
проблем е породен от различния начин, по който 2.0.x клона обработва
POST заявките и е описан в този коментар.
Съществува и пач, който решава този проблем и аз съм компилирал и
стартирал httpd с него, но тъй като автор на пача е Joe Orton, който
поддържа пакета httpd в RHEL и Fedora и той не го е включил в
дистрибуцията, предполагам, че има причини за това и не го ползвам, а и
не препоръчвам на вас да го ползвате. Ще спомена по-долу
конфигурациите, които са приложими засега само за 1.3.x клона, а на
тези, които ползват 2.0.x клона, им препоръчвам да следят changelog-а
на httpd пакета на своята дистрибуция както и следните два доклада в
системите за доклад на грешки на:
Това
са проблеми специфични за apache httpd 2.0.x клона, а ние ползваме
доказалата се за стабилна 1.3.х версия и затова можем да ползваме
пълните възможности на модула.
Начална конфигурация
Започваме
с генерирането на сертификат за уеб сървъра, подписването му от нашата
CA и поставянето им в конфгурационните директории:
# openssl req -new -sha1 -keyout newkey.pem -out newreq.pem
# ./CA.pl -signreq
# mv newcert.pem /etc/apache/ssl.crt/server.crt
# mv newkey.pem /etc/apache/ssl.key/server.key
# cp Linux-BG-CA/cacert.pem /etc/apache/ssl.crt/cacert.crt
Горният пример ще създаде частен ключ, който ще
бъде криптиран и ще се иска парола при зареждането му от уеб сървъра.
Първоначално така го бяхме направили, но бързо ни мина и го
декриптирахме. За да не бъде криптиран използвайте опцията -nodes.
Дебиан
не включва никаква примерна конфигурация на модула и затова е нужно да
си я създадем сами. Това е нетипично за другите дистрибуци и аз ви
съветвам да погледнете съдържанието на пакета си, примерните
конфигурационни файлове и коментарите в тях. За останалите дистрибуции
ви съветвам да не се отклонявате от стойностите, с които е
конфигурирана общата част на модула по подразбиране. Долните настройки
са мое дело и са правени като съм търсел консервативните и работещи със
сигурност стойности, но в действителност може и да са възможни по-добри
решения.
Продължаваме с общата конфигурация на mod_ssl, за която създаваме файла /etc/apache/conf.d/mod_ssl.conf.
В него описваме общите настройки на модула, които ще се опитам да поясня кратки коментари:
<IfModule mod_ssl.c>
# На кой порт слуша. Стандартно 443ти
Listen 443
# Допълнители mime типове за сертификатите и за листата с отменените сертификати
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
SSLPassPhraseDialog builtin
# Не съм запознат със спецификите на Дебиан и затова взимам консервативно и работещо със сигурност решение:
SSLSessionCache dbm:/var/run/ssl_scache
# В RedHat работи така:
# SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
#
5 мин. трябва да са достатъчно. Това ще е нужно да го променяте само,
ако сайта ви е специфичен и/или ви трябва много да оптимизирате.
SSLSessionCacheTimeout 300
# mutex-ите при нас работят така:
SSLMutex file:/var/run/ssl_mutex
# Източници на случайни числа
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
# Или може би ще ползваме:
#SSLRandomSeed startup file:/dev/urandom 512
#SSLRandomSeed connect file:/dev/urandom 512
# Журнали
SSLLog /var/log/apache/ssl_engine_log
# Ниво на детайл (възможни са: none, error, warn, info, trace, debug)
# След като се уверим, че работи вероятно ще минем на error само
SSLLogLevel warn
# Специално вниманите заслужават потребителите на любимия Internet Explorer:
SetEnvIf User-Agent “.*MSIE.*” nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
Конфигурационните директиви за заключени между
<IfModule mod_ssl.c> и </IfModule>, за да не предизвикат
грешки, ако модулът не е зареден.
Специфични настройки за виртуалния хост
Минаваме към специфичните настройки за виртуалния хост:
# Ако имаме повече от един виртуален ssl хост може да ползваме:
# Include /etc/apache/vhosts/*.vhost
<VirtualHost 212.50.10.155:443>
# Тия си ги знаете
ServerName linux-bg.org
ServerAlias www.linux-bg.org
DocumentRoot /home/path/
# Пуск машина
SSLEngine on
# Със стари версии на SSL протокола не се занимаваме:
SSLProtocol all -SSLv2
# Същото ще е и ако напишем долното, защото TLSv1 и SSLv3 са синоними
# SSLProtocol TLSv1
# Използвани шифри. Те може да се променят в <:Directory контейнери.
# Тук допускаме шифри, които се подържат от всеки скорошен браузър
SSLCipherSuite HIGH:MEDIUM
# Указваме къде се намират сертификата, ключа и сертификата на нашето CA
SSLCACertificateFile /etc/apache/ssl.crt/cacert.crt
SSLCertificateFile /etc/apache/ssl.crt/server.crt
SSLCertificateKeyFile /etc/apache/ssl.key/server.key
# Ако трябва да възстановявате верига на доверие ползваме долната директива. Друг начин е просто да конкатенираме сертификатите.
# SSLCertificateChainFile /etc/apache/ssl.crt/certchain.crt
# За директориите съдържащи много сертификати се ползва:
# openssl c_rehash /dir
#
Листи с отменени сертификати. Тук се включват сертификати, които са
компроментирани, загубени или просто сме ги издали, за да си играем с
тях:
SSLCARevocationFile /etc/apache/ssl.crl/server.crl
# Лист на отменените сертификати се генерира чрез командата:
# openssl ca -gencrl -out /etc/apache/ssl.crl/server.crl
#
Нямаме под-удостоверители — всичко си го подписваме ние. Ако
имахме SubCA ще трябваше да увеличим долната стойност с едно за всяко
междинно звено:
SSLVerifyClient 1
# Ако са ни нужни променливи на обкръжението за cgi скриптовете ни:
#<Directory /home/path/cgi-bin&>
# SSLOptions +StdEnvVars
#</Directory>
# За да гледаме какво точно се случва може да наблюдаваме заявките, които нашия сървър получава:
CustomLog /var/log/apache/ssl_request_log \
“%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \”%r\” %b”
</VirtualHost>
Настройки за ограничаване на достъпа
Тези
настройки също се правят в рамките на виртуалния хост, но тук ще са
отделно, за да илюстрират някои от възможностите. За тях се изисква
предоставянето на PKCS#12 сертификат от страна на потребителя. Как се
създава той може да прочетете в статията за Postfix и TLS.
Отново поясненията ще бъдат като коментари:
# За общия случай нямаме никакво ограничение. Т.е. не поставяме никакви
условия потребителя да ни представи сертификат, нито за полетата на
този сертификат:
SSLVerifyClient none
#
А защо не и да приемем сертификат, ако има такъв. Това не би се
използвало на много места, но може да се укаже удачно решение за някои
специфични случаи:
# SSLVerifyClient optional
# За наистина интересните места ние повишаваме изискванията:
<Location /secure>
# Сега вече повишаваме и изискванията като допускаме само 3 комбинации
от шифри, защото всички имаме свястни браузъри. Това ще наложи
предоговаряне на шифрите, ако по някаква причина е била избрана
по-слаба комбинация.
SSLCipherSuite HIGH:-MD5:-ADH:-3DES
#
С долната директива искаме да ни бъде представен подписан от нас
валиден сертификат. Тази директива се комбинира с SSLVerifyClient 1 и
това означава, че искаме този сертификат да е подписан от нас.
SSLVerifyClient require
# От тук надолу за httpd 2.0.x става трудно:
# Или пък може да го изискаме изрично, като укажем, че в полето за организация трябва да сме ние:
# SSLRequire %{SSL_CLIENT_S_DN_O} eq “Linux-BG”
#
Също така е възможно и да дадем достъп и само на отделни подгрупи в
нашата организация. Примерно администраторите на пощенския или уеб
сървъра може да си достъпват контролните панели:
# SSLRequire %{SSL_CLIENT_S_DN_O} eq “Linux-BG” and \
# %{SSL_CLIENT_S_DN_OU} in {”Web Admin”, “Mail Admin”}
</Location>
#
Възможността да проверяваме стойностите в сертификатните полета
означава, че може и да създадем директории, които да са достъпни през
уеб само от един единствен потребител
<Location /secure/peio>
SSLVerifyClient require
SSLRequire %{SSL_CLIENT_S_DN_CN} eq “Peio Popov”
</Location>
За да прегледаме сертификатните полета може да използваме командата:
openssl x509 -subject -noout -in cert.pem
Ако искаме да видим целия сертификат в текстови вид ползваме:
openssl x509 -text -noout -in cert.pem
Понякога
може да ни се наложи да ограничим достъпа до някоя директория във
виртуален хост, който е достъпен и по http. За да пренасоча всички
заявки към https аз ползвам mod_rewrite:
RewriteEngine On
RewriteBase /dir
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^(.*)$ https://servername/dir/$1 [R,L]
Възможности на SSLRequire
Синтаксисът
на SSLRequire директивата е изключително гъвкав и ни позволява да
въвеждаме изключително разнообразни ограничения и съм сигурен, че всеки
ще намери нужните средства, за да задоволят нуждите му. Нека само
спомена, че освен всички параметри на сертификата разполагаме и със
стандартните променливи на обкръжението (CGI 1.0) и apache и може да ги
включваме и тях в изрази като викаме променливата под формата на
%{ИмеНаПроменлива}.
Освен богатството от променливи ние имаме и възможностите на BNF
нотацията да сравняваме реални и желани стойности (включително и
възможност да създаваме функции), а освен това може и да посочваме
файл, от който да четем.
Имайки
предвид тези богати възможности горните примери са само начално
въведение, за запознаване със синтаксиса им и аз не виждам смисъл да се
опитвам да изброявам всичките им възможни приложения.
За четене
mod_ssl е изключително добре и достъпно документиран. Всеки, който се запознае с документацията му
ще може да използва неговите пълни възможности. Все пак е добре и да
погледнете спецификите и отворените проблеми свързани с пакетите в
системата за следене на грешки на дистрибуцията ви.