Удалёнка: опыт и лайфхаки
28 июля 2011

Apache HTTP Server: Обслуживание нескольких HTTPS-хостов на одном IP-адресе

Серверное администрирование
Из песочницы
При миграции сервера в облако возникла необходимость разместить несколько веб-сайтов, работающих по 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 пакеты из штатных репозитариев, список нужных пакетов приводить не буду.
  1. Из комплекта Fedora Core 15 (Fedora Mirror List) взял пакеты:
    libtasn1-2.7-2.fc15.src.rpm
    gnutls-2.10.5-1.fc15.src.rpm
  2. С домашней страницы проекта (mod_gnutls) взял актуальную версию исходных кодов модуля.
  3. Установил пакеты исходных кодов (ключ --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
  4. Архив исходных кодов (mod_gnutls-0.5.9.tar.bz2) cкопировал в /usr/src/redhat/SOURCES.
  5. В /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).
  6. Удалил старые пакеты вместе с зависимостями:
    yum erase gnutls libtasn1
  7. Собрал libtasn1:
    rpmbuild -bb --clean /usr/src/redhat/SPECS/libtasn1.spec
  8. Установил пакеты libtasn1:
    yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/libtasn1-*.rpm
  9. Собрал gnutls:
    rpmbuild -bb --clean /usr/src/redhat/SPECS/gnutls.spec
  10. Установил пакеты gnutls:
    yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/gnutls-*.rpm
  11. Из файла /usr/lib64/pkgconfig/gnutls.pc из строки Requires.private удалил zlib, т.к. установленный zlib-devel не содержит определения для pkg-config.
  12. Собрал mod_gnutls:
    rpmbuild -bb --clean /usr/src/redhat/SPECS/mod_gnutls.spec
  13. Установил пакеты 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
Теги: apache httpd https tls mod_tls centos
Хабы: Серверное администрирование
+26
16,7k 81
Комментарии 32
Реклама

Рекомендуем