I recently started really thinking about the dwindling number of available IPv4 addresses and what we can do to use them more efficiently. One option that I had not revisited in a while is Server Name Indication (SNI). It is an extension to SSL/TLS, which enables sending of the domain being requested during initial negotiation of the secure connection, allowing web servers to be able to provide the correct security certificate for that domain, even if there are multiple domains on the same IP. Previously this was not an option, as the servers would not receive information about the domain being requested until after the secure connection was negotiated, meaning that each domain with a certificate needed a separate IP address.
SNI really is not a new feature, but when I had previously tested SNI, the support for it was limited. Now, however, most web browsers either have had SNI support for a while or will probably never be upgraded to get SNI support. Fortunately, most of the software lacking SNI support is older by today’s standards and includes software like Internet Explorer 6 and the default web browser included with Android 2.x.
Now that basically all modern web browsers and servers support SNI, I think it is probably time to start taking advantage of that. This is especially needed now, with limited IPv4 space left.
So, how do system administrators go about using SNI to improve their IPv4 utilization? I am going to focus on the two web servers we use the most: Apache and Nginx.
Apache
The first requirement to run SNI with Apache to have the mod_ssl module installed on your web server. If you are already serving up secure websites from your server, then mod_ssl is probably already installed.
The second step to running SNI with Apache is turning on listening on port 443:
Listen 80
Listen 443
And the final step is enabling Name-based Virtual Hosting, which is commonly used on non-SSL domains already:
NameVirtualHost *:80
NameVirtualHost *:443
With the above completed, all that remains is to create the virtual host entries for both non-SSL and SSL. The format for SSL virtual host entry is similar to the non-SSL one, with just a few added directives that set the SSL-specific options.
Here is an example of a vhost with SSL:
ServerName “www.example.com”
ServerAdmin admin@example.com
DocumentRoot /home/example/public_html’
ErrorLog /home/example/log/www-example-com-error.log
LogLevel warn
CustomLog /home/example/log/www-example-com-access.log combined
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny,allow from all
SSLEngine On
SSLCertificateFile /home/example/certs/www-example-com.pem
SSLCertificateKeyFile /home/example/keys/www-example-com.key
Nginx:
For Nginx, the process is similar, although of course the exact configuration is a bit different (and possibly easier). If Nginx already has configured domains for non-SSL traffic, then all that is needed is to add a few lines to those existing configurations to enable and setup SSL. Unlike with Apache, separate SSL configurations are not needed. It is of course possible to configure an SSL-only domain, but that is not the norm.
Here is an example:
Each server configuration(vhost) for Nginx needs to have a server_name set to the domain for it.
Like with the Apache setup, we first enabling listening on port 443:
listen 80; #original line
listen 443 ssl; #added to enable SSL
Then, of course, add the certificate information:
ssl_certificate /home/example/certs/www-example-com.pem;
ssl_certificate_key /home/example/keys/www-example-com.key;
That is really all that is needed. There are a many other options available for SSL with Nginx (here), but this gets things started.
So, after getting my hands dirty and reviewing the SNI setup and configuration, it really is easy to implement. Given that and all of the support for it in most modern browsers and servers, we are going to start implementing this in-house whenever possible to help us conserve our IPv4 space and save some money (IPs aren’t cheap anymore).