При миграции сервера в облако возникла необходимость разместить несколько веб-сайтов, работающих по 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