Apache HTTP Server: Serving Multiple HTTPS Hosts on the Same IP Address

When migrating the server to the cloud, it became necessary to host several websites using HTTPS on the same physical IP address.
In this case, it was necessary to stay on the same CentOS 5.6 operating system and standard apache-2.2.19.
I did not find a ready-made solution for CentOS, so I propose my own solution.

Theory


According to RFC 4366 , section 3.1. Server Name Indication is possible.
For proper operation, this extension must support both the server and the client (browser).

Practice


Support for expansion SNI according to Wikipedia appeared in the Apache HTTP Server since version 2.2.12.
Details are in the Apache Wiki .
For the extension to work, you need the OpenSSL library version 0.9.8f or higher.
The problem is that in CentOS 5.6 OpenSSL version 0.9.8e is built-in, and "raising" it is not so easy, because many other components are tied to this version.
Building a separate OpenSSL and Apache outside the package tree is unsportsmanlike.
In the process of finding a solution, I came across an alternative: the gnutls library and the mod_gnutls module .
The gnutls library in the system is also present and also very old, although it is quite painlessly removed along with the dependencies.

As a result, “fresh” gnutls and mod_gnutls packages were assembled and installed , which gave the necessary functionality with minimal impact on the rest of the system. Under cat details on the assembly process and examples of configuration files.

Package assembly


To build, you need * -devel packages from the regular repositories, I won’t give a list of the necessary packages.
  1. From the Fedora Core 15 bundle ( Fedora Mirror List ) I took the packages:
    libtasn1-2.7-2.fc15.src.rpm
    gnutls-2.10.5-1.fc15.src.rpm
  2. From the project home page ( mod_gnutls ) I took the current version of the module source codes.
  3. Installed source packages (the --nomd5 key is needed if cpio swears at md5 mismatch, because srpm is compiled in a newer version)
    rpm -ivh --nomd5 libtasn1-2.7-2.fc15.src.rpm
    rpm -ivh - -nomd5 gnutls-2.10.5-1.fc15.src.rpm
  4. The source code archive (mod_gnutls-0.5.9.tar.bz2) copied to / usr / src / redhat / SOURCES.
  5. In / usr / src / redhat / SPECS created the mod_gnutls.spec file . The basis is taken from mod_gnutls.spec from http://dev.centos.org/centos/5/testing/SRPMS/mod_gnutls-0.2.0-1.el5.centos.src.rpm .
    The contents of the file at the end of the post ( mod_gnutls.spec ).
  6. Removed old packages with dependencies:
    yum erase gnutls libtasn1
  7. Assembled libtasn1 :
    rpmbuild -bb --clean /usr/src/redhat/SPECS/libtasn1.spec
  8. Installed the libtasn1 packages :
    yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/libtasn1-*.rpm
  9. Gathered gnutls :
    the rpmbuild -bb --clean /usr/src/redhat/SPECS/gnutls.spec
  10. Installed gnutls packages :
    yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/gnutls-*.rpm
  11. From the file /usr/lib64/pkgconfig/gnutls.pc from the line Requires.private removed zlib , because installed zlib-devel does not contain a definition for pkg-config.
  12. Assembled mod_gnutls :
    rpmbuild -bb --clean /usr/src/redhat/SPECS/mod_gnutls.spec
  13. Installed mod_gnutls packages :
    yum localinstall --nogpgcheck /usr/src/redhat/RPMS/x86_64/mod_gnutls-*.rpm

Plugin configuration


The module needs access to the file in which its own cache is maintained, the path to the file is specified by the GnuTLSCache key in the configuration file.
If selinux is enabled , you need to configure the policy:
semanage fcontext -a -f "" -t httpd_cache_t "/var/cache/mod_gnutls_cache(/.*)?"
You must create a directory for the cache file and assign it rights:
mkdir / var / cache / mod_gnutls_cache
chown apache: apache / var / cache / mod_gnutls_cache
chmod 700 / var / cache / mod_gnutls_cache
The default configuration file is in /etc/httpd/conf.d /mod_gnutls.conf.

Example module configuration file 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
##

Virtual Host Configuration


There are several points to consider when configuring:
  • It is advisable to completely disable mod_ssl .
  • Each VirtualHost must be either fully HTTP or fully HTTPS, with the "mixed" version of the HTTP protocol, SSL-encrypted data still arrives.
  • The default virtual HTTPS host must have a certificate and a key, as The initial connection occurs precisely with him.

VirtualHost Configuration Example

Listen 80
Listen 443
NameVirtualHost *:80
NameVirtualHost *:443
ServerName defsrv.home.net
# По умолчанию все запросы перенаправляются на основной сайт (http://www.home.net)

    Redirect permanent / http://www.home.net/

# SSL-сертификат у дефолтного сервера должен присутсвовать обязательно!

    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/

    ServerName www.home.net:80
    UseCanonicalName On
    ServerAdmin webmaster@www.home.net
    DocumentRoot /srv/www.home.net
    #Конфигурация хоста

    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
    #Конфигурация хоста

    ServerName test.home.net:80
    UseCanonicalName On
    ServerAdmin webmaster@test.home.net
    DocumentRoot /srv/test.home.net
    #Конфигурация хоста

    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
    #Конфигурация хоста


Speck file ( 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

Also popular now: