Multiple Apache VHosts on the same IP and port
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
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:
- Listen 443
- NameVirtualHost *:443
- SSLEngine On
- ServerName serverone.tld:443
- SSLCertificateFile /etc/apache2/ssl/serverone.crt
- SSLCertificateKeyFile /etc/apache2/ssl/serverone.key
- SSLEngine On
- ServerName servertwo.tld:443
- SSLCertificateFile /etc/apache2/ssl/servertwo.crt
- SSLCertificateKeyFile /etc/apache2/ssl/servertwo.key
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.
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).
Display comments as Linear | Threaded
Strahler on :
"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?"
I don't see the problem. That host has one Virtual Host for each hostname, each has its own certificate and its own access rules. The Intranet Virtual Host should already be filtering out incoming traffic from the internet.
If it isn't, there was a security issue previous to the use of SNI, just as serious and exploitable as before.
Daniel Lange on :
Your assuming a safe set-up. That's quite often not the case. Apache servers are used to serve many applications in parallel. That makes SNI so attractive in a corporate environment. Not another IP to allocate to the Apache host(s) once a new project needs SSL. But: There are usually no access rules to shield VHosts from the internet IPs or the gateway proxy IPs. I've not seen a single company use them "by default". The intranet is assumed "safe".
Luckily a lot of reverse proxies terminate SSL connections on the proxy and open a new connection to the destination host. This will break all SNI functionality (as the proxies don't even know about this functionality yet) but will also only allow access to the default SSL VHost as the SNI tag does not get through to the destination host. Those who have saved on computing power and forward SSL connections without interim termination or use port forwarding, are at risk though.
The "servername" is determined from a callback out of the TLS library to Apache ("ssl_servername_cb"), then a patched Apache sets the context ("ssl_set_vhost_ctx") and finally checks the hostname that came from the client against the available vhosts ("set_ssl_vhost"). Thus separate (name based) VHosts won't help you, separate certificates won't either (the attacker will see the other certificate as his/her first indication of success). Access rules will help, but as stated above, I've not seen them being used as a default anywhere. That has to change, if one deploys SNI in a DMZ scenario.
Oliver on :
hmmmmm... i have just activated the sni use flag on a reverse proxy where the certificate issue has always bugged me. does not seem to do anything.....
ServerName internal.myserver.org ServerAdmin firstname.lastname@example.org
ProxyRequests Off ProxyPreserveHost On
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL SSLCertificateFile /etc/apache2/ssl/internal.myserver.org.crt SSLCertificateKeyFile /etc/apache2/ssl/internal.myserver.org.key
ErrorLog /var/log/apache2/ssl_error_log TransferLog /var/log/apache2/ssl_access_log
Order deny,allow Allow from all
ProxyPass /sharedfiles/ https://internal.myserver.org/sharedfiles/ ProxyPassReverse /sharedfiles/ https://myserver.org/sharedfiles/
ProxyPass /myapp/ https://internal.myserver.org/myapp/ ProxyPassReverse /myapp/ https://myserver.org/myapp/
am i doing something really wrong here?
Daniel Lange on :
You need to have a VHOST section that encapsulates your proxy settings. Each VHOST can have different SSLCert* settings, thus a different certificate offered to the client.
addicted on :
You do realize that "because something was not setup secure in the first place, SNI enables new ways for attackers" is not a valid argument, and also not even true. Let's see what's needed here: To get access to the intranet site via the external IP address, one would have to now the internal site's name and the external (public) ip address of the webserver. Entering this information in one systems hosts file, everyone would easily be able to contact the intranet site. Now, where did I use TLS/SSL or SNI? Right, nowhere. Because that has nothing to do with it. Meaning: If the setup is not secure in the first place, it won't be secure after SNI. Not a big surprise for me.
Daniel Lange on :
Huh? Not everything that is insecure is automatically also easily exploitable. SNI lowers the barrier in certain setups. Also the SNI implementation can be buggy and thus provide another attack vector, see this Apache bug .
Hanno on :
I know this entry is pretty old, but your information about konqueror is wrong. Even with current kde 4.4.4, Konqueror does not support SNI and there's no light in sight.