Disabling SSLv3 on a server with multiple virtual hosts

While addressing security needs recently, I discovered that our primary domain was receiving a C rating on SSL Labs.  Eek.  Mainly, the biggest cause was that SSLv3 was still enabled.  Should be pretty straight forward to disable right?

All commands relate to CentOS 6.7.  These commands and config settings may not translate directly to another OS.

The Simple Server Solution

The fix is very easily found on Google.  You just have to find your SSL settings, usually in /etc/httpd/conf.d/ssl.conf.  Within that file, find the follow line.

SSLProtocol All -SSLv2

Replace that line with the following.

SSLProtocol All -SSLv2 -SSLv3

Then restart Apache.

/etc/init.d/httpd restart

Simple, right?

If your server only contains one primary host and document root, sure.  But when you have multiple Virtual Hosts, that goes out the window.  What should have been a simple edit and restart didn’t solve the problem.  I had to start investigating the individual Virtual Hosts.

Multiple Virtual Hosts Solution

I’ve been manually creating virtual hosts for use on this server without the use a host CMS.  This means manually creating and editing files in Apache config directory: /etc/httpd/

I needed to create 10 or more hosting environments and subdomains based on the same domain. In order to keep things organized, I started breaking each related subset into it’s own config file.  For example, domain.com, api.domain.com, test.domain.com in a file named domain.conf in /etc/httpd/conf.d/.  Similarly, other groups like old.domain.com, api.old.domain.com, oldapi.domain.com went into it’s own file: old.conf.  By breaking up the virtual hosts, I was able to keep a semblance of order.

Each file contained the insecure and secure versions of each subdomain, such as the following.

 <VirtualHost *:80>
    DocumentRoot /home/user/subdomain
    ServerName old.domain.com
</VirtualHost>

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile /etc/pki/tls/certs/ca.crt
    SSLCertificateKeyFile /etc/pki/tls/private/ca.key
    SSLCertificateChainFile /etc/pki/tls/certs/ca-bundle.crt
    DocumentRoot /home/user/subdomain
    ServerName old.domain.com
</VirtualHost> 

The real implementation has more content, but I’ve stripped it down to the bare necessities for this example.

Since my config contained so many virtual hosts, each secure definition was overriding anything in ssl.conf!  This is not intuitive and took me a while to discover.  I also discovered that a significant number of other people ended up having this issue, but the final solution wasn’t easy to find.

To get everything working, you have to put the individual SSL settings in EACH virtual host.  You can’t just test with one either since they like to override each other when using *:443 as your Virtual Host definition.  Once I changed all secure Virtual Hosts to the following, it worked and I received an A rating on SSL Labs!

 <VirtualHost *:80>
    DocumentRoot /home/user/subdomain
    ServerName old.domain.com
</VirtualHost>

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile /etc/pki/tls/certs/ca.crt
    SSLCertificateKeyFile /etc/pki/tls/private/ca.key
    SSLCertificateChainFile /etc/pki/tls/certs/ca-bundle.crt
    SSLProtocol All -SSLv2 -SSLv3
    SSLHonorCipherOrder on
    SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA
    DocumentRoot /home/user/subdomain
   ServerName old.domain.com
</VirtualHost> 

There are a few settings there I haven’t mentioned so here’s a quick explanation.

SSLHonorCipherOrder forces the system to try the ciphers in the exact order defined until one is found that works.  This also allows your configuration to pass the Forward Referencing requirement of SSL Labs, which, if failed, maxes your rating at B.

SSLCipherSuite defines which ciphers to use in your secure connection.  The ones listed above are currently considered secure.

That’s it!  I hope this helps anyone else that may have had this issue.