HTTPS Virtual Hosts in Apache

Posted on July 2, 2009 by Tommy McGuire
Labels: eclipse virgo, software development, http, linux, osgi, java
Running multiple web sites that allow HTTPS connections on the same Apache httpd server is problematic. Typically, virtual servers (the individual web sites) use named virtual hosting, where the virtual host which serves the site is chosen based on the host name specified in the HTTP Host header. Named virtual hosting does not work for HTTPS because the server cannot interpret the Host header until the connection has been made, and making the connection requires the completion of the SSL encryption handshake used by HTTPS; SSL certificates (without extensions) can only have a single server host name as their subject, and thus the certificate and connection will only work for a single host name. As a result, the named virtual hosting mechanism never has a chance to operate on the incoming connection and the only remaining way to host multiple sites is to add multiple IP addresses to the host and use IP-based virtual servers.

The keys to supporting multiple sites using HTTPS and name-based virtual hosting are to use either wildcard names (specified in RFC2818) or the x509 version 3 certificate (specified in RFC3280) subject alternative names extension. I have not used wildcard names, although they allow one certificate to work for any number of hostnames below a given domain: *.example.com would allow any of a.example.com, foo.example.com, or elbow.example.com, but would not work for right.elbow.example.com or www.google.com. Wildcard certificates are much more expensive than standard certificates and are not administratively available in my particular work domain.

Subject alternative names, a.k.a. subjectAltNames, allow a certificate to list a number of host names for which it is valid. For example, a single certificate with www.example.com as its (single) subject could list www.example.com, www.example.org, and webapp.example.com as alternate names; the certificate would be recognized as valid for any of those host names.

Generating subjectAltName certificates



Convincing openssl to generate a certificate or certificate signing request requires changes to the openssl.conf file:

  1. Enable extensions:

    [req]
    req_extensions = v3_req

  2. Add a v3_req section including the subjectAltName field:

    [ v3_req ]
    subjectAltName = @alt_names

  3. List the host names in the proper format in the v3_req section:

    [alt_names]
    DNS.1 = web.example.com
    DNS.2 = dspl.example.com
    DNS.3 = nprop.example.com
    DNS.4 = webdir.example.com
    DNS.5 = hpps.example.com
    DNS.6 = remoteuser.example.com
    DNS.7 = esm.example.com
    DNS.8 = etsapprover.example.com
    DNS.9 = ep.example.com
    DNS.10 = cas.example.com
    DNS.11 = wat.example.com
    DNS.12 = ned.example.com

For more information, see Creating a Certificate With Multiple Hostnames and a discussion from the OpenLDAP list.

Apache mod_rewrite



There are at least two ways of configuring httpd to handle multiple web sites with a single certificate. One resembles the normal name-based virtual hosting (with the VirtualHost directive and everything); the other is the one I have used.

In the first, set up httpd to listen on port 443 and to present the certificate with the subjectAltNames:

NameVirtualHost *:443
Listen 443
SSLEngine On
SSLCertificateFile /etc/....
SSLCertificateKeyFile /etc/.....

Then, add all of the necessary named virtual hosts normally, making sure that they are listening on port 443:


ServerName foo.example.com
# Configuration for web site foo.example.com



ServerName bar.example.com
# Configuration for web site bar.example.com


Now, I have not actually done this, but it looks like it should work.

What I have done is used subjectAltName certificates with a reverse proxy httpd configuration, where each of several applications in an application server appears to have its own server name:

Listen 443
SSLEngine On
SSLCertificateFile /etc/....
SSLCertificateKeyFile /etc/.....

RewriteEngine On

RewriteCond %{HTTP_HOST} ^foo\..*$
RewriteRule ^(.*) http://127.0.0.1:8090/foo-2.2$1 [P,L]

RewriteCond %{HTTP_HOST} ^bar\..*$
RewriteRule ^(.*) http://127.0.0.1:8090/bar-2.2$1 [P,L]


Issues



There are a couple of caveats: when present, the subject alt names list may or may not replace the actual subject of the certificate; if a host name is present only in the certificate subject field and is absent from the subjectAltName field then the browsers I have tried will not recognize the certificate as valid for the host name. Not all clients support subjectAltNames; see SAN Certificates: Subject Alternative Name. Further, there are possibly some security issues with multi-host certificates. Check Phishing for Confirmations for details.
active directory applied formal logic ashurbanipal authentication books c c++ comics conference continuations coq data structure digital humanities Dijkstra eclipse virgo electronics emacs goodreads haskell http java job Knuth ldap link linux lisp math naming nimrod notation OpenAM osgi parsing pony programming language protocols python quote R random REST ruby rust SAML scala scheme shell software development system administration theory tip toy problems unix vmware yeti
Member of The Internet Defense League
Site proudly generated by Hakyll.