При миграции сервера в облако возникла необходимость разместить несколько веб-сайтов, работающих по HTTPS на одном физическом IP-адресе.
При этом нужно было остаться на той же операционной системе CentOS 5.6 и штатном apache-2.2.19.
Готового решения для CentOS не нашел, поэтому предлагаю свой вариант решения.
Согласно RFC 4366, раздел 3.1. Server Name Indication это возможно.
Для полноценной работы это расширение должен поддерживать и сервер и клиент (браузер).
Поддержка расширения SNI согласно Wikipedia появилась в Apache HTTP Server начиная с версии 2.2.12.
Подробности есть в Apache Wiki.
Для работы расширения нужна библиотека OpenSSL версии 0.9.8f или выше.
Проблема в том, что в CentOS 5.6 встроен OpenSSL версии 0.9.8e, и «поднять» ему версию не так то просто, т.к. именно на эту версию завязано много других компонент.
Собирать отдельный OpenSSL и Apache вне дерева пакетов — неспортивно.
В процессе поиска решения наткнулся на альтернативу: библиотеку gnutls и модуль mod_gnutls.
Библиотека gnutls в системе тоже присутствует и тоже очень старая, правда достаточно безболезненно удаляется вместе с зависимостями.
В результате были собраны и установлены «свежие» пакеты gnutls и mod_gnutls, которые дали нужный функционал с минимальным влиянием на остальную систему. Под катом подробности по процессу сборки и примеры файлов конфигурации.
Для сборки понадобятся *-devel пакеты из штатных репозитариев, список нужных пакетов приводить не буду.
Модулю нужен доступ к файлу, в котором ведется его собственный кеш, путь к файлу задается ключем GnuTLSCache в файле конфигурации.
Если включен selinux, нужно выполнить настройку политики:
semanage fcontext -a -f "" -t httpd_cache_t "/var/cache/mod_gnutls_cache(/.*)?"
Необходимо создать каталог для файла кеша и назначить ему права:
mkdir /var/cache/mod_gnutls_cache
chown apache:apache /var/cache/mod_gnutls_cache
chmod 700 /var/cache/mod_gnutls_cache
Файл конфигурации по умолчанию лежит в /etc/httpd/conf.d/mod_gnutls.conf.
При конфигурировании нужно учесть несколько моментов:
При этом нужно было остаться на той же операционной системе CentOS 5.6 и штатном apache-2.2.19.
Готового решения для CentOS не нашел, поэтому предлагаю свой вариант решения.
Теория
Согласно RFC 4366, раздел 3.1. Server Name Indication это возможно.
Для полноценной работы это расширение должен поддерживать и сервер и клиент (браузер).
Практика
Поддержка расширения SNI согласно Wikipedia появилась в Apache HTTP Server начиная с версии 2.2.12.
Подробности есть в Apache Wiki.
Для работы расширения нужна библиотека OpenSSL версии 0.9.8f или выше.
Проблема в том, что в CentOS 5.6 встроен OpenSSL версии 0.9.8e, и «поднять» ему версию не так то просто, т.к. именно на эту версию завязано много других компонент.
Собирать отдельный OpenSSL и Apache вне дерева пакетов — неспортивно.
В процессе поиска решения наткнулся на альтернативу: библиотеку gnutls и модуль mod_gnutls.
Библиотека gnutls в системе тоже присутствует и тоже очень старая, правда достаточно безболезненно удаляется вместе с зависимостями.
В результате были собраны и установлены «свежие» пакеты gnutls и mod_gnutls, которые дали нужный функционал с минимальным влиянием на остальную систему. Под катом подробности по процессу сборки и примеры файлов конфигурации.
Сборка пакетов
Для сборки понадобятся *-devel пакеты из штатных репозитариев, список нужных пакетов приводить не буду.
- Из комплекта Fedora Core 15 (Fedora Mirror List) взял пакеты:
libtasn1-2.7-2.fc15.src.rpm
gnutls-2.10.5-1.fc15.src.rpm
- С домашней страницы проекта (mod_gnutls) взял актуальную версию исходных кодов модуля.
- Установил пакеты исходных кодов (ключ --nomd5 нужен, если cpio ругается на несовпадение md5, т.к. srpm собран в более новой версии)
rpm -ivh --nomd5 libtasn1-2.7-2.fc15.src.rpm
rpm -ivh --nomd5 gnutls-2.10.5-1.fc15.src.rpm
- Архив исходных кодов (mod_gnutls-0.5.9.tar.bz2) cкопировал в /usr/src/redhat/SOURCES.
- В /usr/src/redhat/SPECS создал файл mod_gnutls.spec. За основу взят mod_gnutls.spec из http://dev.centos.org/centos/5/testing/SRPMS/mod_gnutls-0.2.0-1.el5.centos.src.rpm.
Содержимое файла в конце поста (mod_gnutls.spec). - Удалил старые пакеты вместе с зависимостями:
yum erase gnutls libtasn1
- Собрал libtasn1:
rpmbuild -bb --clean /usr/src/redhat/SPECS/libtasn1.spec - Установил пакеты libtasn1:
yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/libtasn1-*.rpm - Собрал gnutls:
rpmbuild -bb --clean /usr/src/redhat/SPECS/gnutls.spec - Установил пакеты gnutls:
yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/gnutls-*.rpm - Из файла /usr/lib64/pkgconfig/gnutls.pc из строки Requires.private удалил zlib, т.к. установленный zlib-devel не содержит определения для pkg-config.
- Собрал mod_gnutls:
rpmbuild -bb --clean /usr/src/redhat/SPECS/mod_gnutls.spec - Установил пакеты mod_gnutls:
yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/mod_gnutls-*.rpm
Конфигурирование плагина
Модулю нужен доступ к файлу, в котором ведется его собственный кеш, путь к файлу задается ключем GnuTLSCache в файле конфигурации.
Если включен selinux, нужно выполнить настройку политики:
semanage fcontext -a -f "" -t httpd_cache_t "/var/cache/mod_gnutls_cache(/.*)?"
Необходимо создать каталог для файла кеша и назначить ему права:
mkdir /var/cache/mod_gnutls_cache
chown apache:apache /var/cache/mod_gnutls_cache
chmod 700 /var/cache/mod_gnutls_cache
Файл конфигурации по умолчанию лежит в /etc/httpd/conf.d/mod_gnutls.conf.
Пример файла конфигурации модуля mod_gnutls.conf
## Documentation Link: ## http://www.outoforder.cc/projects/apache/mod_gnutls/docs/ ## Load the module into Apache. LoadModule gnutls_module modules/libmod_gnutls.so ## Set Certificate MIME-types, may instead be in ssl.conf AddType application/x-x509-ca-cert .crt AddType application/x-pkcs7-crl .crl ## Set TLS Cache info GnuTLSCache dbm "/var/cache/mod_gnutls_cache/server1_test_net.dbm" GnuTLSCacheTimeout 300 ##
Конфигурирование виртуальных хостов
При конфигурировании нужно учесть несколько моментов:
- Желательно полностью отключить mod_ssl.
- Каждый VirtualHost должен быть или полностью HTTP или полностью HTTPS, при «смешанном» варианте по протоколу HTTP все равно приходят SSL-шифрованные данные.
- Виртуальный HTTPS-хост «по-умолчанию» обязательно должен иметь сертификат и ключ, т.к. первоначальное соединение происходит именно с ним.
Пример конфигурации VirtualHost
Listen 80 Listen 443 NameVirtualHost *:80 NameVirtualHost *:443 ServerName defsrv.home.net # По умолчанию все запросы перенаправляются на основной сайт (http://www.home.net) <VirtualHost _default_:80> Redirect permanent / http://www.home.net/ </VirtualHost> # SSL-сертификат у дефолтного сервера должен присутсвовать обязательно! <VirtualHost _default_:443> GnuTLSEnable on GnuTLSPriorities NORMAL GnuTLSCertificateFile /etc/httpd/certs/defsrv_home_net.crt GnuTLSKeyFile /etc/httpd/certs/defsrv_home_net.key Redirect permanent / https://www.home.net/ </VirtualHost> <VirtualHost *:80> ServerName www.home.net:80 UseCanonicalName On ServerAdmin webmaster@www.home.net DocumentRoot /srv/www.home.net #Конфигурация хоста </VirtualHost> <VirtualHost *:443> ServerName www.home.net:443 UseCanonicalName On ServerAdmin webmaster@www.home.net DocumentRoot /srv/www.home.net GnuTLSEnable on GnuTLSPriorities NORMAL GnuTLSCertificateFile /etc/httpd/certs/www_home_net.crt GnuTLSKeyFile /etc/httpd/certs/www_home_net.key #Конфигурация хоста </VirtualHost> <VirtualHost *:80> ServerName test.home.net:80 UseCanonicalName On ServerAdmin webmaster@test.home.net DocumentRoot /srv/test.home.net #Конфигурация хоста </VirtualHost> <VirtualHost *:443> ServerName test.home.net:443 UseCanonicalName On ServerAdmin webmaster@test.home.net DocumentRoot /srv/test.home.net GnuTLSEnable on GnuTLSPriorities NORMAL GnuTLSCertificateFile /etc/httpd/certs/test_home_net.crt GnuTLSKeyFile /etc/httpd/certs/test_home_net.key #Конфигурация хоста </VirtualHost>
Спек-файл (mod_gnutls.spec)
Summary: mod_gnutls is a DSO module for the apache Web server. Name: mod_gnutls Version: 0.5.9 Release: 1%{?dist} Group: System Environment/Daemons URL: http://www.outoforder.cc/projects/apache/mod_gnutls/ Source: http://www.outoforder.cc/downloads/mod_gnutls/%{name}-%{version}.tar.bz2 Source1: mod_gnutls.conf License: Apache Software License BuildRoot: %{_tmppath}/%{name}-root BuildRequires: httpd-devel > 2.0.42 BuildRequires: gnutls >= 1.2.0, gnutls-devel >= 1.2.0, gnutls-utils >= 1.2.0, apr-devel Requires: httpd-mmn = %(cat %{_includedir}/httpd/.mmn || echo missing httpd-devel) Requires: gnutls >= 1.2.0, httpd >= 2.0.42 %description mod_gnutls uses the GnuTLS library to provide SSL v3, TLS 1.0 and TLS 1.1 encryption for Apache HTTPD. It is similar to mod_ssl in purpose, but does not use OpenSSL. %prep %setup -q %build %configure --disable-srp make %install [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{_libdir}/httpd/modules install -m755 src/.libs/lib%{name}.so $RPM_BUILD_ROOT%{_libdir}/httpd/modules # Install the config file mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d install -m 644 %{SOURCE1} \ $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf #Create a cache directory mkdir -p -m 0700 $RPM_BUILD_ROOT%{_var}/cache/mod_gnutls_cache %clean [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc LICENSE NOTICE README %{_libdir}/httpd/modules/*.so %config(noreplace) %{_sysconfdir}/httpd/conf.d/*.conf %attr(0700, apache, apache) %{_var}/cache/mod_gnutls_cache
