Skip to content

Multiple Apache VHosts on the same IP and port

Apache

I just learned yesterday again, what I knew a few years ago, but since had forgotten:

You cannot put multiple SSL-enabled virtual Apache hosts onto the same IP and port.

Apache cannot identify which VirtualHost to serve a request from because the payload is encrypted in its entirety. So a

Host: servertwo.tld

header cannot be parsed until the encryption has been removed. Which requires the key, which is listed in the VHost section that could not be identified in the first place... So a name-based VirtualHost-configuration like this won't work:

  1. Listen 443
  2. NameVirtualHost *:443
  3. <virtualhost>
  4.    SSLEngine On
  5.    ServerName serverone.tld:443
  6.    SSLCertificateFile /etc/apache2/ssl/serverone.crt
  7.    SSLCertificateKeyFile /etc/apache2/ssl/serverone.key
  8.    [...]
  9. </virtualhost>
  10. <virtualhost>
  11.    SSLEngine On
  12.    ServerName servertwo.tld:443
  13.    SSLCertificateFile /etc/apache2/ssl/servertwo.crt
  14.    SSLCertificateKeyFile /etc/apache2/ssl/servertwo.key
  15.    [...]
  16. </virtualhost>

It will just serve any request out of the first VirtualHost (serverone.tld) regardless of the hostname in the request headers.

There is some light at the end of this tunnel though: RFC4366 describes an optional field to the TLS (Transport Layer Security) client request called "Server Name Indication" (SNI). With this the client just includes a list of ServerNames (usually one) that it's trying to contact. Apache can easily match the supplied name from the client against a ServerName (or ServerAlias) directive from it's configuration files.

SNI will be supported with OpenSSL v0.9.9 in mod_ssl. Sometime in the future. There is a backport to v0.9.8 available from Steven Henson linked here. Or you can use mod_gnutls as described by George Notaras in a recent blog entry.

In either cases the above configuration snippet will "just work" once SNI is understood by Apache.

Currently Internet Explorer 7 (on Vista only, wanna upgrade :-)), Mozilla Firefox 2+, Opera 7.6+, KDE Konqueror 3.5+ support sending the SNI. You can test your browser at Kaspar Brand's SNI testpage. He also has a patch available to make Apache 2.2 mod_ssl SNI capable when compiled against a CVS-version of OpenSSL.

I'm rather sure that spreading SNI capable hosts will also provide new hacking opportunities: Let's assume a system serves both Intranet and Internet traffic. A client contacts the Internet IP with SSL but specifies the Intranet Hostname in it's TLS SNI entry. Guess what will happen? Yup.

Update

02.09.2009: Gee, after two years people still read this blog entry. So I'll point you to a few updates. 2009 is not 2007 :-) SNI has made some slow progress since the original article. But major steps forward only came this summer: Apache has official support for SNI since 2.2.12 (tracking bug). Gentoo has been early to support SNI and Tobias Scheerbaum has written a blog entry on Apache, SSL und SNI in Gentoo (in German) summarizing how it works out of the box. Support for SNI has also been added to Debian (tracking bug) but for now the default config files don't reflect SNI capability yet. Ubuntu will see SNI in Karmic Koala, the release scheduled for next month i.e. "9.10" (tracking bug). Fedora has a SNI enabled Apache from httpd-2.2.13-1.fc11 onwards (tracking bug). Tobias also states that SP3 for Windows XP enables IE6 to send the SNI (SP2 is not sufficient).

Apache fails to start at boot, but works when started manually

ApacheGentoo

Since a baselayout update Apache fails to start on Gentoo at (re-)boot of a server if that server has unused ethernet interfaces.

The symptom is that Apache fails to start on boot although it has been added to the runlevel with
rc-update add apache default

This is caused by recent baselayouts not working properly with more than one eth and not all of them being up.

Thus changing depend() { need net ... } into
depend() { need net.eth0 ... } at the top of /etc/init.d/apache2 will help.

While you're at it you could also add an nice after urandom to the existing depend () construct
and make sure apr and apache are emerged with flag urandom set. Reading from /dev/random to initialize the digest authentication mechanism (or SSL for that matter) might cause apache to block otherwise if there is not enough entropy in the random pool.