Wednesday, August 01, 2012

Enabling Host based SSL vhost using SNI in Apache 2.2

Multiple virtual host on the same IP


It is not unusual to host multiple website using the same IP address over HTTP (port 80). In fact, it is very easy to build a family of websites based on *.your_web_site.com, for instance

- product1.mycompany.com
- product2.mycompanycom
- product3.mycompany.com
- product4.mycompany.com

and so on and so forth.

The problem.

 

It is when the system needs to move to HTTPS (port 443), problem arises. Upon migrating all the configuration to ssl.conf in Apache, you may hit the following

[Mon Jul 30 18:18:43 2012] [warn] Init: SSL server IP/port conflict: product2.mycompany.com:443 (/usr/local/apache2.2.22/conf/second_vhost.conf:1) vs. product1.mycompany.com:443 (/usr/local/apache2.2.22/conf/first_vhost.conf:1)
[Mon Jul 30 18:18:43 2012] [warn] Init: SSL server IP/port conflict: product3.mycompany.com:443 (/usr/local/apache2.2.22/conf/third_vhost.conf:1) vs. product1.mycompany.com:443 (/usr/local/apache2.2.22/conf/first_vhost.conf:1)
[Mon Jul 30 18:18:43 2012] [warn] Init: SSL server IP/port conflict: product4.mycompany.com:443 

and
 
[Mon Jul 30 18:18:43 2012] [warn] Init: You should not use name-based virtual hosts in conjunction with SSL!!

The reason is that the SSL protocol is a separate layer which encapsulates the HTTP protocol.

As SSL seesion is separate transaction that take place before HTTP session begins, it is impossible for the browser or the client to determine the SSL vhost it is supposed to access. Only IP and port is accessible at this stage and Apache will just return the first vhost if found which matches the port and iP address specified.

workaround?


The usual advise is to use a separate IP for each SSL vhost but this is merely a workaround. In addition, with the public IPs (v4) becoming scarce, soon we will run out of IP (v4).

Solution


With Apache 2.2.12 and newer PLUS OpenSSL 0.9.8j, it is possible to build what we have done on HTTP onto HTTPS.

We will need SNI (subject name indication). This allows you to host multiple SSL websites on the same IP address. This is effectively providing host headers for SSL.

Not much information (many questions but not much answer with good explanation) has been found on the internet to get SNI support, hence the below steps to help folks out.

background

The procedures is done on RHEL 4.6 64bit. I believe this should work for the variants of *NIX. We will do the following
  • Upgrade OpenSSL to v0.9.8x
  • Upgrade Apache to 2.2.22 with SNI support.

Upgrade Openssl with SNI support

Unpack openssl-0.9.8x.tar.gz then try the following

# ./config enable-tlsext shared
# make
# make install
 


Openssl 0.9.x series uses 'enable-tlsext' while Openssl 1.x series uses '--enable-tlsext' switch
ensure that you use the 'shared' command, else the config will fail

After its done, check that openssl is installed with the correct version

[root@server bin]# /usr/local/ssl/bin/openssl version
OpenSSL 0.9.8x 10 May 2012

Install Apache with openssl 0.9.8x support + SNI

Unpack httpd-2.2.22.tar.gz and then try the following

# LDFLAGS=-L/usr/local/ssl/lib/ CPPFLAGS=-I/usr/local/ssl/include/ ./configure --with-included-apr --prefix=/usr/local/apache2222_pntest/ --enable-so --with-ssl=/usr/local/ssl/lib/ --enable-ssl=static --enable-mods-shared='all proxy rewrite'
# make
# make install
 

LDFLAGS is to include any library path that is not default within the httpd binary directory.
CPPFLAGS is for including the header files for compilation that is not default within the httpd binary directory.

Configure the Apache

Now that Apache is installed, configure your httpd.conf and ssl.conf.

To prevent non SNI browsers from having issues connecting, add in below in ssl.conf

# Go ahead and accept connections for these vhosts
# from non-SNI clients
SSLStrictSNIVHostCheck off

Setup the environment

Lastly, add in LD_LIBRARY_PATH into /etc/profile so that the libraries can be found.

LD_LIBRARY_PATH="/usr/local/ssl/lib/:LD_LIBRARY_PATH"
export LD_LIBRARY_PATH

Check that now Apache can link to the new openssl library

[root@server bin]# ldd httpd | grep ssl
        libssl.so.0.9.8 => /usr/local/ssl/lib/libssl.so.0.9.8 (0x00002b7019d09000)
        libcrypto.so.0.9.8 => /usr/local/ssl/lib/libcrypto.so.0.9.8 (0x00002b7019f58000)
 
If environment is not setup properly, ldd will report that the library is "missing" Also you may need to re-apply your profile by either logout/login or ". /etc/profile".


Result


With SNI support, you should see the following line only in the error log.
[warn] Init: Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)

Client supportability

SNI support in browsers is as follows
  • FF 2.0 and newer
  • IE7 + vista and newer
  • Chrome + vista
  • Opera 8
  • Safari 8.2.1
My reference: <http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI>

~Done.

No comments: