Pull to refresh

SSL virtual host на Apache 2.2 mod_ssl и самоподписанные сертификаты

SSL virtual host на Apache 2.2 mod_ssl и самоподписанные сертификаты

Начнем с перечисления раскрываемых в заметке тезисов
1. В Сети бродят слухи о том, что виртуальный SSL хост на Apache невозможен.
Name-based Virtual Host под SSL не возможен, но он нам и не нужен.
Шифрованные HTTPS соединения прекрасно поддерживаются средствами GNU TLS, www.gnu.org/software/gnutls, ru.wikipedia.org/wiki/GnuTLS, wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI

1.1. А зачем нам Name-based Virtual Host под SSL?
Затем, чтобы поддерживать три или или сто пятьдесят https web-серверов одной копией Апача.
Без того, чтобы иметь по отдельному IP и отдельному запущенному Апачу на каждый https web-сервер, который вам нужен.

1.2. Почему Apache 2.2?
Потому, что пора.

2. А зачем нам SSL?
А затем, что любой ваш сосед по колокейшену вынюхает, например, абсолютно все ваши пароли от всего к чему только вы или ваши юзеры будут иметь несчатье обратиться, пока его снифер запасает траф.
Ettercap NG ( ettercap.sourceforge.net ), рекомендую.

Если у провайдера/хостера есть есть дисциплина выявления и реакции на arp-spoofing ( xgu.ru/wiki/ARP-spoofing ), — он прихлопнет сниффера в обозримый, но бесполезный срок, — ваши пароли уже у «забаненного».
Arp-spoofing позволяет «прорезать» коммутаторы и слушать весь проходящий через них траф, а не только траф локальной подсети, доступной promiscuous mode интерфейсу.
Борьба с arp-spoofing идет двумя путями:
2.1. VLAN коммуторы настраиваются провайдером так, чтобы минимизировать объем доступных спуферу подсеток. Тут что ваше (когда вы атакуете), то ваше. Большой западный хостер плюет на arp-spoofing, полагаясь на сделанную настройку «железа» и не следит за его проявлениями.
2.2. В этом случае работа СОРМ невозможна. «Коробочка» теряет траф, не «видит» бОльшую его часть.
2.3. Поэтому на Руси спуферу доступен весь траф, проходящий через коммутаторы площадки, а провайдер фильтрует спуфинг на санкционированный и самопальный. Самопальщиков банят.
2.4. Атакующий может купить минимальный контракт на интересующей его площадке, запустить, например, Ettercap NG и наслаждаться результатами ночь или выходные, пока утром понедельника или любым другим утром «админы-супербизоны» не отрегируют на свистки из логов.
2.5. Это в лучшем случае. А в худшем атакующий будет слушать площадку вечно. Ибо дисциплина выявления спуфинга существует не у каждого хостера.
2.6. Если вы и атакующий в одном VLAN'е — arp-spoofing не нужен. Достаточно слушать VLAN, не засвечиваясь спуфингом. Решается так: «Вась, мне высоко/низко к серверу лазать. Вась я хочу в другую стойку ближе/дальше к кондиционеру. Я мерзну/сервер греется. Давай переставим? Я быстро патчи передерну! Все равно три утра, никто даже не заметит. Пиво — с меня.» СерверА, как правило, подписаны фломастерами или выявляются наводящими вопросами под воблу.

Опасность выявления promiscuous mode интерфейсов, если пров/хостер сканирует площадку на предмет их выявления, купируется кусачками — перерезается один проводок RJ-45 фишки и никто никогда не узнает, что ваша сетевая карта находится в promiscuous mode.
Короче, спасения нет.
А СОРМ — знает все. Просто имейте это ввиду. Все, что вам только может прийти в Сети в голову — при минимальном интересе СОРМ к вашей персоне — имеется в распоряжении кого угодно.
Живите и помните — любой заход в Сеть через нешифрованное соединение — это как кейлоггер с бесконечным объемом памяти.
Есть еще и обычай «пить пиво в серверной». Любой может завести себе «знакомого админа» и обснифать площадку «за пиво», прямо из прилегающего к «аквариуму» дата-центра административного помещения ночной смены саппорта.

2.7. Лично меня смешат «интернет-магазины», работающие через HTTP.

3. Единственный способ защитить свои «веб-морды» и «веб-морды» своей организации (CRM, groupware, web-mail, «админки» etc. etc.) — пересадить их за HTTPS.

4. И покончим с вводной частью, чтобы перейти уже к скриптам и конфигам.
Для установления HTTPS соединения нужен SSL сертификат.
4.1. SSL сертификат можно сгенерировать самостоятельно. Тогда браузеры будут давать предупреждения при заходе на защищенную таким сертификатом страницу. Внутри организации или сообщества вопрос решается директивной установкой ваших самопальных сертификатов в браузеры юзеров или директивным требованием доверять сайту и сертификату невзирая на предупреждения браузера.
4.2. SSL сертификат можно купить. Тогда браузеры не будут ругаться (при правильной покупке сертификата (валидный CSR!) и настройке Апача! а то все равно будут ругаться, не глядя на потраченные деньги).
Цена вопроса от 400 руб. в год за RapidSSL сертификат, подтверждющий, что сертификат на домен/сервер выдан лицу/организации, являющейся по данным WHOIS владельцем домена, до 30000-40000р. в год за «брендовый» сертификат, удостоверяющий существование организации, лица, бизнеса, физического адреса офиса и т.д. и т.п.

5. Зачем могут понадобиться самоподписанные сертификаты?
Как бы браузер ни ругался на «подозрительный сертификат» — соединение все равно зашифровано. Задача выполнена, сниферы отдыхают.
Осталось сохранить лицо в глазах новичков и серферов, впервые заходящих на защищенную страницу, купив сертификат у организации, которая «прошита» в браузере из коробки.
Но и в случае покупки «брендового» сертификата БЕЗ самоподписанного сертификата вам НЕ обойтись. Потому, что опыт его выпуска даст вам знания для генерации ключа сервера и CSR файла.
Вам нужно отладить сервер и научиться генерировать ключи веб-серверов и CSR файлы, без которых сколько денег ни отдай — браузеры, в самых оскорбительных выражениях, будут сообщать о не доверенном соединении.

6. Процесс покупки сертификата (или генерации самоподписанного сертификата) выглядит так:
Средствами OpenSSL вы создаете ключ веб-сервера (без него Апач НЕ запустится!), «самопальный» сертификат сервера и CSR файл (Certificate Signing Request).
Содержимое CSR файла передается продавцу сертификата, котрый на основе заключающихся в нем данных выпустит для вас коммерческий сертификат, на который браузеры не будут ругаться.
Файл ключа веб-сервера и CSR файл должны содержать валидную информацию о защищаемом сервере. Если данные в них не корректны — ругань браузера не прекратится никогда, несмотря на плаченные деньги.
Коммерческий сертификат, выданный вам по CSR запросу, будет работать в паре с созданным вами ключом веб-сервера и только с ним.
Итак перед вами задача: научиться генерировать ключи веб-сервера и выпускать самоподписанные сертификаты.
В момент, когда браузер будет выдавать единственную претензию к странице — сертификат подписан организацией, не входящей в состав доверенных на этой планете, — вы готовы к покупке коммерческого сертификата или к внедрению внутри организации/сообщества своего самоподписанного сертификата.

7. Весь секрет массового виртуального HTTPS хостинга по ссылке: wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI

Просто добавьте
SSLStrictSNIVHostCheck off
в конфиг Апача и все.

$ cat /usr/local/pic-apache22/conf/extra/httpd-ssl.conf
— # — SSLv2 only
#SSLProtocol -all +SSLv2
#SSLCipherSuite SSLv2:+HIGH:+MEDIUM:+LOW:+EXP

# — all SSL versions
SSLProtocol all
SSLCipherSuite HIGH:MEDIUM

# — #SSLRandomSeed startup file:/dev/random 512
#SSLRandomSeed startup builtin
SSLRandomSeed startup file:/dev/urandom 512

Listen IP:443
NameVirtualHost IP:443

AddType application/x-x509-ca-cert .crt
AddType application/x-x509-ca-cert .cer
AddType application/x-pkcs7-crl .crl

SSLPassPhraseDialog builtin

#SSLSessionCache «dbm:/usr/local/pic-apache22/logs/ssl_scache»
SSLSessionCache «shmcb:/usr/local/pic-apache22/logs/ssl_scache(512000)»
SSLSessionCacheTimeout 300

SSLMutex «file:/usr/local/pic-apache22/logs/ssl_mutex»
SSLStrictSNIVHostCheck off

##
## SSL Virtual Host Context
##

#--- MSIE6 берет данные сертификата ПЕРВОГО виртуального хоста! И все.
#--- Все остальные виртуальные хосты он считает не доверенными.
#--- Возможно, это побеждается директивой BrowserMatch, но я пока не знаю, как.
#--- Возможно, это побеждается использованием mod_tls, не пробовал пока.
#--- Определенно, это побеждается использованием IIS :) Но утверждать не могу, не пробовал.
#--- httpd.apache.org/docs/2.0/ssl/ssl_faq.html#msie
Include conf/extra/https-vhosts-mailbox.conf
Include conf/extra/https-vhosts-hotbox.conf
Include conf/extra/https-vhosts-myserver.conf
— Я не люблю «звездочек» в директивах Listen, рано или поздно ум у системы заходит за разум и Апач перестает запускаться. У меня на одном боксе полсотни Апачей на полсотне IP.
Вместо
Listen *:443
NameVirtualHost _default_:443

Я использую
Listen IP:443
NameVirtualHost IP:443

Что и вам советую.

В расширениях имен файлов сертификатов существует некоторый разнобой. Поэтому убедитесь в том, что раширение используемого вами файла сертификата опредлено в директиве Апача AddType.
Например:
AddType application/x-x509-ca-cert .crt

Иначе Апач запустится, установит HTTPS соединение, но браузер НЕ увидит данных сертификата и продолжит сообщать о не доверенном соединении.

8. Начинаем генерацию ключей и самопальных сертификатов.

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

8.1. Создаем ключ корневого хранилища, наш самый главный ключ:
— #!/bin/sh
# создаем ключ корневого хранилища
openssl genrsa -des3 -out some-domain-tld-ca.key 2048
— При генерации ключа openssl запросит у вас пароль. Запишите и спрячьте свой пароль. openssl будет запрашивать этот пароль при любой попытке использовать этот ключ.

$ chmod 400 some-domain-tld-ca.key
Для порядку.

8.2. Создаем и зашифровываем ключом корневого хранилища корневой сертификат, сертификат издателя сертификатов:
— #!/bin/sh
# создаем и зашифровываем ключом корневого хранилища корневой сертификат, сертификат издателя сертификатов
openssl req -new -x509 -days 3650 \
-key some-domain-tld-ca.key -out some-domain-tld-ca.crt
— openssl запросит у вас пароль, заданный вами для ключа корневого хранилища и, если вы его не забыли, создаст сертификат корневого хранилища.
На всяк случай, пока — на 10 лет. После отладки можно генерить на управляемые сроки.

$ chmod 400 some-domain-tld-ca.crt

Для облегчения ввода данных можно поправить раздел [ req_distinguished_name ] файла openssl.cnf:

[ req_distinguished_name ]
countryName = RU
countryName_default = RU
countryName_min = 2
countryName_max = 2

stateOrProvinceName = Russia
stateOrProvinceName_default = Russia

localityName = Moscow
localityName_default = Moscow

0.organizationName = Some-Domain.Tld
0.organizationName_default = Some-Domain.Tld

# we can do this but it is not needed normally :-)
1.organizationName = Back Office
1.organizationName_default = Back Office

organizationalUnitName = Web Services
organizationalUnitName_default = Web Services

commonName = www.some-domain.tld
commonName_max = 64

emailAddress = info@some-domain.tld
emailAddress_max = 64

SET-ex3 = SET extension number 3

[ req_attributes ]
challengePassword = somepassphrase
challengePassword_min = 4
challengePassword_max = 20

unstructuredName = Some-Domain.Tld Officer
— Создайте скриптик для просмотра данных сертиф#!/bin/sh

$ cat show_x509_cert.sh
— #!/bin/sh
# просмотреть данные сертификата
openssl x509 -in $1 -text -noout | less
— $ ./show_x509_cert.sh some-domain-tld-ca.crt

В выводе обратите внимание на поле CN. Оно должно выглядеть именно так:

CN=Some-Domain.Tld/emailAddress=info@some-domain.tld

Ваш диалог с командой
$ openssl req -new -x509 -days 3650 \
-key some-domain-tld-ca.key -out some-domain-tld-ca.crt
должен выглядеть примерно так.
— Enter pass phrase for some-domain-tld-ca.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.
— RU [RU]:
Russia [Russia]:
Moscow [Moscow]:
Some-Domain.Tld [Some-Domain.Tld]:
Back Office [Back Office]:
Web Services [Web Services]:
www.some-domain.tld []:Some-Domain.Tld
info@some-domain.tld []:info@some-domain.tld
— Там, где в квадратных скобках что-то есть и оно вас устраивает, просто жмите Enter.
Для того, чтобы оно вас заранее устраивало, подправьте, как описано выше, файл openssl.cnf
Значения двух последних полей впечатайте вручную и просмотрите полученный сертификат командой

$ openssl x509 -in some-domain-tld-ca.crt -text -noout | less

чтобы убедиться, что в нем все верно.

В вашем распоряжении появился корневой сертификат вашего личного корневого центра сертификации.
Его зовут: some-domain-tld-ca.crt

8.3. Создаем ключ веб-сервера, который вы намерены защитить сертификатом.
Этот ключ будет указан в качестве ключа к сертификату в conf файле Апача.
— #!/bin/sh
# создаем ключ веб-сервера
openssl genrsa -des3 -out myserver-server.key 1024
— openssl запросит пароль, которым зашифрует ключ. Запоминаем и сохраняем его в надежном месте.

8.4. Создаем запрос на подписание сертификата веб-сервера. Этот запрос на подписание будет использоваться вами и для создания самопального сертификата веб-сервера, и для покупки коммерческого сертификата у уполномоченной организации.
— #!/bin/sh
# создаем запрос на подписание сертификата, шифруя его ключом веб-сервера
openssl req -new -key myserver-server.key -out myserver-server.csr
— openssl запросит пароль, которым зашифрован ключ веб-сервера

Enter pass phrase for myserver-server.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.
— RU [RU]:
Russia [Russia]:
Moscow [Moscow]:
Some-Domain.Tld [Some-Domain.Tld]:
Back Office [Back Office]:
Web Services [Web Services]:
www.some-domain.tld []:myserver.some-domain.tld — это поле должно ПОЛНОСТЬЮ СОВПАДАТЬ с FQDN защищаемого веб-сервера!!!
info@some-domain.tld []:info@some-domain.tld

Please enter the following 'extra' attributes
to be sent with your certificate request
somepassphrase []: — здесь я ничего не воожу, просто жму Enter
Some-Domain.Tld Officer []:Some-Domain.Tld Officer

8.5. Создаем и подписываем сертификат веб-сервера, используя запрос на сертификат, корневой ключ и корневой сертификат
— #!/bin/sh
# создаем и подписываем сертификат веб-сервера, используя запрос на подписание сертификата, корневой ключ и корневой сертификат
openssl x509 -req -in myserver-server.csr \
-out myserver-server.crt -sha1 -CA some-domain-tld-ca.crt \
-CAkey some-domain-tld-ca.key -CAcreateserial -days 3650
— openssl запросит пароль корневого ключа

8.6. Апач будет требовать при запуске пароль к ключу веб-сервера. Если эта фича вам не нужна, сделайте страховую копию ключа веб-сервера
$ cp myserver-server.key myserver-server.key.dist

и очистите пароль ключа веб-сервера командой:
— #!/bin/sh
# очищаем пароль ключа веб-сервера для того, чтобы Апач стартовал без запроса пароля
openssl rsa -in myserver-server.key.dist -out myserver-server.key
— openssl запросит пароль ключа веб-сервера, чтобы расшифровать ключ и записать его в открытом виде.

Теперь у вас есть пара, самоподписанный сертификат и ключ к нему, которые вы можете использовать для запуска Апача c mod_ssl
myserver-server.crt
myserver-server.key

Обратите внимание на то, что валидным ключом к комерческому сертификату, который вы получите, переслав продавцу запрос на подписание сертификата myserver-server.csr, будет служить именно созданный вами ключ myserver-server.key.

Просмотрите содержимое сертификата myserver-server.crt командой:
$ openssl x509 -in myserver-server.crt -text -noout | less
Обратив внимание на правильность данных в строках «Issuer:» и «Subject:»

Выше приведено содержимое файла /usr/local/pic-apache22/conf/extra/httpd-ssl.conf
А вот содержимое файла /usr/local/pic-apache22/conf/extra/https-vhosts-myserver.conf, включенного в /usr/local/pic-apache22/conf/extra/httpd-ssl.conf директивой Include:
Файл /usr/local/pic-apache22/conf/extra/httpd-ssl.conf, в свою очередь, включен директивой Include в содержимое всем знакомого файла httpd.conf

$ cat /usr/local/pic-apache22/conf/extra/https-vhosts-myserver.conf
— <VirtualHost 195.91.136.3:443>
DocumentRoot "/dump/domain/myserver"
DirectoryIndex index.php
ServerName myserver.some-domain.tld
ServerAlias www.myserver.some-domain.tld
ServerAdmin info@some-domain.tld
ErrorLog «logs/myserver.error.log»
TransferLog «logs/myserver.access.log»
CustomLog "/usr/local/pic-apache22/logs/myserver.ssl_request.log" "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

SSLEngine On
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile "/usr/local/pic-apache22/conf/ssl.crt/myserver-server.crt"
SSLCertificateKeyFile "/usr/local/pic-apache22/conf/ssl.crt/myserver-server.key"
SSLCertificateChainFile "/usr/local/pic-apache22/conf/ssl.crt/some-domain-tld-ca.crt"
SSLCACertificateFile "/usr/local/pic-apache22/conf/ssl.crt/some-domain-tld-ca.crt"
#SSLCARevocationFile "/usr/local/pic-apache22/conf/ssl.crl/ca-bundle.crl"

#SSLVerifyClient require
#SSLVerifyDepth 10

# Access Control:
# With SSLRequire you can do per-directory access control based
# on arbitrary complex boolean expressions containing server
# variable checks and other lookup directives. The syntax is a
# mixture between C and Perl. See the mod_ssl documentation
# for more details.
#<Location />
#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
# and %{SSL_CLIENT_S_DN_O} eq «Snake Oil, Ltd.» \
# and %{SSL_CLIENT_S_DN_OU} in {«Staff», «CA», «Dev»} \
# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
#

SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars

<Directory "/usr/local/bla-bla/cgi-bin">
SSLOptions +StdEnvVars

BrowserMatch ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

— Если все «завелось» и единственной причиной, вызывающей «ругань» броузера является что-нибудь вроде:
К сертификату нет доверия, так как к сертификату его издателя нет доверия.
(Код ошибки: sec_error_untrusted_issuer)
и вы видите свой сертификат в цепочке, подтверждающей его выпуск вами же, то можно еще несколько раз до, автоматизма, перевыпустить и протестировать сертификаты и отправить CSR файл поставщику коммерческих сертификатов для приобретения сертификата нужного вам уровня доверия.
«Гугл/яндекс: купить SSL сертификат».

Все разжевал, аж самому понятно :)
Удачи!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.