SSL-enabled Name-based Apache Virtual Hosts with mod_gnutls

This article describes how to implement SSL-enabled name-based vhosts – that is secure virtual hosts which share the same IP address and port – with the SNI-capable mod_gnutls module for Apache’s httpd web server.

Server Name Indication (SNI), as described in section 3.1 of the RFC3546, is a TLS extension which makes the configuration of SSL-enabled name-based virtual hosts possible. This extention eliminates the need for the assignment of one IP address per secure virtual host, therefore the cost for secure web hosting is greatly reduced, as all secure virtual hosts can share the same IP address and port combination. SNI is a huge step forward as it promotes security by making secure web services easier and cheaper to implement. The current version of OpenSSL – 0.98 at the time of writing – does not support SNI yet, but this is planned for the upcoming 0.99 release. On the other hand, mod_gnutls, an experimental module for Apache’s httpd which has been around for 2+ years, includes support for SNI.

Introduction

Searching the web for mod_gnutls binary distribution packages or information on how to set it up returned very few relevant results. This was a surprise, as, at this moment, the only implementation that supports SNI is mod_gnutls. So, I decided to write a tutorial on how to set things up for a test. I hope you find it useful.

The test that is described in this guide includes:

  1. The compilation of the mod_gnutls module.
  2. The generation of SSL certificates.
  3. The configuration of the SSL-enabled name-based virtual hosts.

This test was performed on a server that runs Fedora 7.

Installation

In order to compile mod_gnutls, you will need the development tools for Fedora:

# yum groupinstall "Development Tools"

Install the mod_gnutls dependencies:

# yum install httpd-devel gnutls-devel

As an unprivileged user, download the mod_gnutls distribution and compile it.

$ wget http://www.outoforder.cc/downloads/mod_gnutls/mod_gnutls-0.2.0.tar.bz2
$ tar -xjvf mod_gnutls-0.2.0.tar.bz2
$ cd mod_gnutls-0.2.0
$ ./configure --prefix=/usr
$ make

Do not use the ‘make install‘ script, but perform the installation manually – it is only one library.

As root, copy libmod_gnutls.so to the directory that holds the Apache modules (usually /usr/lib/httpd/modules) and rename it to mod_gnutls.so for consistency:

# cp mod_gnutls-0.2.0/src/.libs/libmod_gnutls.so /usr/lib/httpd/modules/mod_gnutls.so

During the compilation, two keys, dhfile and rsafile, have been generated in the mod_gnutls-0.2.0/data/ directory. It is absolutely important to copy these files in httpd’s configuration directory (usually /etc/httpd/conf/), otherwise mod_gnutls will never work. This is undocumented, and I found out about it after some trial&error.

As root:

# cp mod_gnutls-0.2.0/data/{dh,rsa}file /etc/httpd/conf/

Installation is complete.

SSL certificates

In this test installation, two virtual hosts will be used. Thus, two SSL certificates will be required. Please read my article on how to generate SSL certificates for your servers, as this information is beyond the scope of this document. Alternatively, you may use a ready-made script which will create those certificates for you quickly. Such scripts are shipped will almost all Linux distributions. Please consult your distribution’s documentation for more information.

HTTPd Configuration

The configuration of the Apache web server includes two phases:

  1. The configuration of the main server.
  2. The configuration of the virtual hosts.

In the following instructions, some brief notes about what each directive does is included. For more detailed information, please consult the mod_gnutls documentation.

Main Server Configuration

This includes setting some general mod_gnutls options, which will be inherited by all virtual hosts.

But, first of all, httpd needs to be set to listen on port 443 (in addition to port 80). Instead of specifying the SSL port only (Listen 443) which will lead httpd to listen to all the available network interfaces, you may specify the exact network interface on which the server will listen. For example:

Listen 192.168.0.1:443

Next, load mod_gnutls:

LoadModule gnutls_module modules/mod_gnutls.so

Add some MIME-types for downloading Certificates and CRLs from your web sites (taken from the mod_ssl configuration):

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

It is suggested that you use a session cache for mod_gnutls. This will increase its performance. In this example, the dbm cache type is used. This cache type requires a directory where mod_gnutls will actually save SSL session data. So, creating a directory for this purpose and giving ownership to the user that runs Apache (usually apache or www-data) is needed. Assuming that the Apache user is apache, as root issue the commands:

# mkdir -m 0700 /var/cache/mod_gnutls_cache
# chown apache:apache /var/cache/mod_gnutls_cache

Now, back to the Apache configuration. The following directive sets the dbm SSL Session Cache for mod_gnutls:

GnuTLSCache dbm "/var/cache/mod_gnutls_cache"

Set a timeout for the SSL Session Cache entries. Usually, this is set to 300 seconds:

GnuTLSCacheTimeout 300

Finally, specify that on the 192.168.0.1:443 interface and port there will be name-based virtual hosts; that is vhosts that share the specified interface and port:

NameVirtualHost 192.168.0.1:443

Virtual Host Configuration

The example virtual hosts are: v1.example.org and v2.example.org. It is assumed that two SSL certificates with the canonical name (CN) correctly set to each of the aforementioned vhost domains have been generated.

In the following vhost configs, only the absolutely required directives have been used. The rest of the options are inherited from the main server.

<VirtualHost 192.168.0.1:443>
    ServerName v1.example.org:443
    GnuTLSEnable on
    GnuTLSCertificateFile /etc/pki_custom/certs/v1.example.org.crt
    GnuTLSKeyFile /etc/pki_custom/private/v1.example.org.key
    DocumentRoot "/var/www/v1/public_html"
</VirtualHost>

<VirtualHost 192.168.0.1:443>
    ServerName v2.example.org:443
    GnuTLSEnable on
    GnuTLSCertificateFile /etc/pki_custom/certs/v2.example.org.crt
    GnuTLSKeyFile /etc/pki_custom/private/v2.example.org.key
    DocumentRoot "/var/www/v2/public_html"
</VirtualHost>

Testing the setup

Having finished with the configuration, review the changes, restart the server and check the error logs for any errors.

Use a web browser to visit each of the virtual hosts by using the HTTPS protocol:

https://v1.example.org/
https://v2.example.org/

Until now, the web server did not support the SNI TLS extension. Therefore, when visiting the v2.example.org virtual host, you would see two warnings in your browser. The first one would be because the vhost’s certificate has not been issued by a trusted Certificate Authority – this is normal as it was you who issued that certificate – and the other one because on a server without SNI support it is actually the V1 vhost’s certificate that is used when visiting V2 vhost over https. Remember the limitation with SSL and name-based virtual hosts?

With mod_gnutls, the server supports the SNI TLS extension. Although the virtual hosts are name-based, no matter which one you visit, the relevant certificate for each vhost is used and the only warning you see is the one about the certificates being self-signed. You can get rid of these by purchasing a certificate that is issued by a trusted Certificate Authority.

Conclusion

mod_gnutls works. Actually, it was a real pleasure to see SNI work!

It is important to note though that mod_gnutls is still in experimental phase. Therefore, performance issues should be considered as normal when using it.

At the moment of writing, my server uses Fedora 7 as an operating system. As I haven’t upgraded my desktop to F7 yet and my server does not have any development tools installed, I compiled mod_gnutls on a Fedora 6 system and used it on Fedora 7. I do not know if that was the reason – and I did not have the necessary free time to investigate – or anything else, but, during the use of mod_gnutls, my server’s load average increased significantly.

Load average increase during mod_gnutls testing

I will test mod_gnutls again soon and post the new results, if they are different than the ones I present in this article. I highly recommend that you try it, as it is currently the only way to easily achieve SSL-enabled name-based virtual hosts using the SNI TLS extension. Note, that this extension will be supported by openssl 0.99, so the moment that SNI goes mainstream and such a setup becomes easy and cheap to implement with any Linux distribution is close.

One last thing that has not been mentioned at all is about SNI support in web browsers. Currently, with the exception of Safari (this is unconfirmed, please correct me if I am wrong), the latest versions of all major web browsers, Firefox and other Mozilla-based browsers, Internet Explorer, Opera, support SNI.

SSL-enabled Name-based Apache Virtual Hosts with mod_gnutls by George Notaras is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Copyright © 2007 - Some Rights Reserved

18 responses on “SSL-enabled Name-based Apache Virtual Hosts with mod_gnutls

  1. Ignacio Permalink →

    Have you considered packaging mod_gnutls for Fedora?

  2. dotan Permalink →

    This is the reason that Apache is so widespread. IIS isn’t this configurable, at least not without an M$ support contract. I love the Apache community. Thanks for the help. Bookmarked!

  3. George Notaras Post authorPermalink →

    I’ve been away for some days. I would like to thank you all for your feedback. :-)

    @Ignacio: Indeed, mod_gnutls is a very good piece of software to get started with RPM packaging for the Fedora project. I have already written a SPEC file including a mod_gnutls.conf configuration file (based on mod_ssl.conf) for the in-house needs. Time permitting, I’ll soon start following each one of the 20 guidelines in order to become a packager. :)

  4. Adam Permalink →

    Actually IIS has had a feature not as powerful but close since IIS6 came out. It only works with sharing a single wildcard certificate for all sites so they have to be under the same domain (site1.example.com, site2.example.com, etc). It also requires some edits to the metabase for each site. We have been using that for quite a few years now with great results and it works with all browsers.

    This feature with apache is a big step forward though because it allows different certificates for each site. Not supporting some older browsers could be an issue though. I know I wouldn’t want to deploy it just yet.

  5. Nikos Permalink →

    If you increase the GnuTLSCacheTimeout to 900 or 1500 does the load decrease?

  6. George Notaras Post authorPermalink →

    @Nikos: This is a very interesting suggestion that I hadn’t thought about when trying mod_gnutls. Next time (when time permits) I will try setting the timeout to different values as suggested and check if it has any impact on the server load.

    Thanks for your feedback.

  7. Tony Boylan Permalink →

    I would like to try out the mod_gnutls module. However I cannot compile it because the following definitions cant be found: “gnutls_certificate_credentials_t, cert_x509, privkey_x509, mgs_srvconf_rec ………. “.

    Can you tell me how to get these definitions ?

    This is the first line of the reported errors when I run make:

    In file included from mod_gnutls.c:18:
    ../include/mod_gnutls.h:79: error: syntax error before ‘gnutls_certificate_credentials_t’

    Thank you. I found the articale very interesting.

  8. George Notaras Post authorPermalink →

    I write this for other readers who run into issues:

    mod_gnutls requires the httpd and gnutls development libraries in order to compile.

  9. George Permalink →

    Has onyone tried using mod_gnutls in conjunction with startcom (free as in beer) certificates? I have set the GnuTLSClientCAFile directive and am still receiving an invalid certificate error in Firefox 2.0. This _should_ work without any popups whatsoever. Has anyone had any experience with this?

  10. George Notaras Post authorPermalink →

    @ Jeremy: Thanks for those links about the SNI browser support.

    @George: It would work without any popups only if the root startcom certificate had been added to the list of trusted certificate authorities in the browser. I seriously doubt that firefox includes this root certificate by default. The user has to trust it first. IIRC, the same happens with certificates from cacert.org.

  11. George Notaras Post authorPermalink →

    Indeed. I checked the list of the root certificates in FF2 and the startcom certificate is there.

    From the mod_gnutls documentation:

    GnuTLSClientCAFile
    Takes an absolute or relative path to a PEM Encoded Certificate to use as a Certificate Authority with Client Certificate Authentication.

    This means that the certificate that has been specified by the GnuTLSClientCAFile directive is only used for client autrhentication via a certificate and actually not when the client enters the secure mode in the browser. Perhaps you should try commenting out this directive and see if it works.

  12. George Permalink →

    Tried commenting out the GnuTLSClientCAFile directive and still no dice. Wonder if there is any way to make this work without having to wait for mod_ssl 0.9.9 to be released supporting SNI?

    Tried contacting the author of mod_gnutls and have not received any response.

  13. George Notaras Post authorPermalink →

    In this comment, Vasili Sviridov points to a website that uses a snapshot version of OpenSSL 0.9.9. Perhaps you could try to contact them too and ask for some info about how well that snapshot version works.

  14. George Permalink →

    Unfortunately I would need a Gentoo ebuild of OpenSSL working with Apache 2.0 for things to work well. Dont think these ebuilds exist yet.

  15. John Permalink →

    Hey guys,

    Make sure to install gnutls-utils before attempting the same.