Testing Server Name Indication (SNI) In The Lab

People have been saying that Internet will run out of IPv4 address space for a long time now, and somehow hosting companies always managed to cope. One of the “coping mechanisms” consists of regrouping several websites behind one IP address – either through NAT or just by hosting several websites on the same web server. In the past, this was not supported by browsers and servers if you wanted to encrypt the traffic: it wasn’t possible to have multiple certificates (and, therefore, domains) on the same IP address. This became a problem so RFC 3546 (“TLS Extensions”) introduced Server Name Indication (SNI).

This article explains how to test SNI in the lab. Avalanche supports this feature since release 4.39. I will not delve into methodologies specifically but instead how to setup an environment and configure Avalanche to use it. Customers will probably need to adjust this to mimic their own architecture, of course.

Environment – Private Key Infrastructure

For this lab I’m going to use CentOS 6.5 and nginx 1.6. I will assume that CentOS is installed and properly configured, and that the nginx repository was installed. Let’s update the OS and install the required packages:

yum -y install nginx openssl; yum -y update

Let’s create the PKI architecture. I like to store that in /etc/pki/:

mkdir -p /etc/pki/spirent/{certs,newcerts,private,crl,csr}
cd /etc/pki/spirent

Let’s generate a Certificate Authority and Intermediate Authority certificates. This IA will sign the keys for our domain names. We could self-sign the certificates, or have the CA sign them directly, but that’s not how it’s done in real life so we’ll keep it (more or less) realistic:

openssl genrsa -out private/ca.key 2048
openssl req -new -x509 -days 3650 -key private/ca.key -out certs/ca.crt
echo 01 > certs/ca.srl
openssl req -new -key private/ia.key -out csr/ia.csr
openssl x509 -req -days 730 -in csr/ia.csr -CA certs/ca.crt -CAkey private/ca.key -out certs/ia.crt
echo 01 > certs/ia.srl

Now let’s generate a Private Key for each of the servers we want to have. I will create certificates for “www.spirent.net” and “www.spirent.fr” but there could be more of course. Note: obviously these are valid only in the lab since my users will trust the CA that signs these keys.

openssl genrsa -out private/spirent.fr.key 2048
openssl genrsa -out private/spirent.net.key 2048

Let’s generate a Certificate Signing Request (CSR) – we need this file for the IA to sign the public key. This step is important because the “Common Name” that OpenSSL asks for will during this test be the hostname of the server.

openssl req -new -key private/spirent.fr.key -out csr/spirent.fr.csr
openssl req -new -key private/spirent.net.key -out csr/spirent.net.csr

And now let’s create public keys from those CSR that will be signed by the IA we created before:

openssl x509 -req -days 3650 -in csr/spirent.fr.csr -CA certs/ia.crt -CAkey private/ia.key -out certs/spirent.fr.crt
openssl x509 -req -days 3650 -in csr/spirent.net.csr -CA certs/ia.crt -CAkey private/ia.key -out certs/spirent.net.crt

One last thing: Remember that our server certificates are signed by an Intermediate Authority, which itself was signed by a Certificate Authority. This is a Certification Chain and we need to create a file that reproduces that chain. This is required because when Avalanche is presented the server certificates, it will check for the signing authority (the IA), and then for the signing authority of that authority (the CA). PKI is great, isn’t it? I can’t wait for DNSEC to be more widely deployed…

Anyway, Avalanche will check the chain, but it needs to check it against something. That something is a file (yet another certificate) that will contain both the IA and CA certificates so Avalanche can do its job. We simply need to put the two certificates into one file, and use that file later on in the Avalanche configuration.

cat certs/ca.crt certs/ia.crt > certs/chained-ca.crt

This will append the content of the ca.crt and the ia.crt files into a new file called “chained-ca.crt”. We do it in that order because the signing was done like so : server->IA->CA. So when Avalanche (or other systems) read the files, they first read the server (spirent.fr.key for instance), then IA (first part of chained-ca.crt) then CA (second part of chained-ca.crt).
Keep chained-ca.crt handy, we’ll use it when running Avalanche. But first…

Environment – nginx configuration

I like nginx because I can make sense of its configuration files. Apache seems overly complex to me, but that’s just me. I will generate two websites for this test, each consisting of only one 10 KB page. It could be a real website, but I want to keep this article simple. Feel free to use a WordPress or the web application of your choice. The file I used is in the zip file at the end of the article. Simply edit it in some text editor, copy the content, and paste it into vi (press “i” in vi then right-click to paste the content):

mkdir -p /var/www/{spirent.fr,spirent.net}
vi /var/www/spirent.fr/index.html
vi /var/www/spirent.net/index.html

Let’s remove the default nginx configuration files as well (I like to keep a clean system):

rm -f /etc/nginx/conf.d/default.conf
rm -f /etc/nginx/conf.d/example_ssl.conf

Now let’s create nginx configuration files for both of these websites. I use the TLS configuration recommended by Mozilla because it makes a lot of good sense in my opinion and their article is a good read. The configuration files are also in the archive, as before create the file by opening them in vi and copy/paste the content in each file:

vi /etc/nginx/conf.d/00-spirent.fr.conf
vi /etc/nginx/conf.d/01-spirent.net.conf

Add nginx to chkconfig to start the service upon reboot of the server and start the service:

chkconfig nginx on
service nginx start

Test Setup – Avalanche

Now it’s time to configure Avalanche to run traffic against these servers. In my case I will use Avalanche Anywhere (also running on CentOS) because it’s easy to connect two Virtual Machines, network-wise. It’s not really important as Virtual and Physical flavours of Avalanche have exactly the same feature set.

Create an “Application Test” (we’re emulating only the client side), setup the subnet and ports as required, and create an action list for each website, for instance:

1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr
1 GET https://www.spirent.fr

Duplicate the action list for http://www.spirent.net. Now go to Client/Profile/DNS and create a new hostname. Specify what the IP address of the two hostnames is. In my case it was

Avalanche DNS Host File configuration window

Avalanche DNS Host File configuration window

Now go to Client/Profile/SSL and keep only the “TLS 1” and “TLS 1.2” SSL versions. In “Certifying Authority Certificates” click on “New” and browse to the chained-ca.crt file we generated before (you can retrieve it from your server with a FTP client and connecting to sftp://<ip address> using the root account). The GUI will ask for a .pem format but .crt works fine (it’s the same format but different extension). Check the “Send TLS Extension SNI” box and enable all ciphers. Your profile should look like something like this:

Avalanche SSL configuration window

Avalanche SSL configuration window

Note that I set “Server Authentication” to “Valid Certificate Mandatory”. This means that Avalanche will actually check if the CA file (chained-ca) was the key that signed the servers’ certificates. We could have set it to “No Checking” but that would be too easy 🙂 And also it means that if you were to test Man-in-the-Middle scenarios (e.g.: your DUT needs to inspect the SSL traffic and replaces the real certificates with its own, but its CA is not known to the users that Avalanche emulates) it would not fail; that wouldn’t be too realistic, although that scenario is entirely possible to run.

All that is left is to create your associations and try to run against your servers: all transactions should be successful. Now you can run the usual test cases: new SSL sessions per second, concurrently established SSL sessions, SSL throughput, etc…

You can download all the files that I used in this test at this address: https://dl.dropboxusercontent.com/u/1400710/blog/sni_4.40.zip

Happy testing!


About acastaner

I'm a Business Development Engineer at Spirent, specialized in Layer 4-7 testing, Virtualization and Automation.
This entry was posted in Tutorial and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s