<-- home

tls and server hardening Post - nginx

post by:

TL;DR I need a configuration for my nginx server that has the latest in SSL/TLS support, go to the end of the post for the gist.

This blog post goes over hardening your nginx server. Nginx itself is a server that was designed to solve the C10K problem. Many people use a variety of servers available to them, Apache probably being the most famous (other than say IIS). I decided that NGINX provided a good balance between performance and security. NGINX actually now supports mod_security which was a Web App Firewall that used to only be available for Apache. There will be a forthcoming blog on the subject.

I’d like to thank the following sites that helped me configure my server appropriately. First of all there is the wonderful people at raymii. Specifically this post. They also provided a great little writeup (shortcut) on the following website:

Here are some additional links however that have greatly helped in my research:

WordPress-Nginx + Thawte SSL Setup

HTTP Public Key Pinning Explained

HTML5 BoilerPlate Examples

If you want the TL;DR go ahead and use the configuration found on cipherli.st and you can more than likely be safe. I, however wanted to make sure I documented my own server configuration. One of the first things I did setting up my server was enable the Content Security Policy (CSP) and XSS support. I will update this blog with the link to that post soon.

Just for everyone’s education here. SSL 2.0 was ‘replaced’ by SSL 3.0 which was then replaced by TLS 1.0, then 1.1, and now onto 1.2. Soon TLS 1.3 will be ratified and we will be looking at updating this blog post. I felt this post was even more critical since Google will be knocking down everyone’s search ranking on weather they have enabled SSL/TLS or not.

While I may use NGINX in this post, understand that Apache2, Lighttpd can be configured similary. For web servers running Windows IIS the configuration will be dramatically different.

Certificate Implementation on NGINX

Make sure you have the appropriate Certificates in the correct order. For example, I was using NameCheap as well as LetsEncrypt. In the NameCheap example I was failing to do any of the SSL Checking at SSLDecoder because I implemented my certs out of order.

Why do I say this? Because I concatenated all of my certificate chains in a string of files like so:

$ cat yoursite.crt intermediate.crt upthechain.crt final.crt > site-bundle.crt

This created a certificate Bundle, and how was I sure that it was correct? This Knowledge Page Article, which is not simple to locate. The concept is that you need to add the certs in reverse order in order to be loaded correctly.

Now in my NGINX.CONF I have a few ways that I’ve divided my configuration. I have placed the General Server configuration in a file that I load from the conf.d directory. Here is a snippet of it:

$ cat /etc/nginx/nginx.conf
user www-data; 
worker_processes 2;
pid /run/nginx.pid;
http {
...
   include /etc/nginx/sites-enabled/*;
...
}

The path’s shown here are all the default paths that I’ve seen on installations. I have put all my header configurations in the .conf’s that are included in the conf.d directory. I then put all my general website configurations in the site-enabled directory under a file that I would recognize. Now lets load the appropriate certificates and Keys that would need to load:

server { 
    listen 443 default_server;
    listen [::]:443 default_server ipv6only=on
    server_name www.server.name server.name;
    root /var/www/html;
    index index.php;

    ssl on;</code>
    ssl_certificate /etc/nginx/ssl/certs/site/server.crt;
    ssl_certificate_key /etc/nginx/ssl/private/server.key;
}

You want to make sure that NGINX reads the new configuration file:

$ nginx -t # Test the Configuration
$ nginx -s reload # Reload and re-read the configuration

Hardening the TLS Configuration

Lets harden the TLS Configuration. First, I have redirected all port 80 traffic to port 443. There are numerous reasons to do this, some ‘security related’, some not. Simple Example, monetization, if you’re a website operator and you want to ensure that your ads are served and not someone else’s, you need to do this.

Disable SSL v2.0 and SSL v3.0. There are too many issues to go on here about but just to name the big one, it was called POODLE. Here is a nice writeup on how severe the problem is: http://disablessl3.com/

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

We have also disabled many of ciphers that honestly are just too weak by now. If you need to support Windows XP and IE6 or Android 2.2.7 then I wouldn’t recommend reading this blog. Those operating systems should be dead and buried, and I’ll refuse to show you how to re-enable those protocols.

Step 4. Enable prioritization of server ciphers and extend the SSL Session Cache. The SSL Cache is more of a performance tuning option, although it was somewhat responsible for Heartbleed in a very odd way.

ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;

Enable perfect forward secrecy, this will help with issues when for example, people want to reconstruct your session by stealing the servers private key. For this step we need to BUILD the diffie helman key:

$ cd /etc/ssl/certs
$ openssl dhparam -out dhparam.pem 2048

Then use it in your configuration:

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Finally we want to enable OSCP stapling. This one is a bit tricky as it requires the server to be able to communicate in an outbound direction which may not be available in all cases.

ssl_stapling on;
ssl_stapling_verify on;
resolver 208.67.222.222 208.67.220.220 valid=300s;
resolver_timeout 5s;

Now testing OSCP can be done with the following one liner:

$ openssl s_client -connect example.org:443 -tls1 -tlsextdebug -status

If you get something like this:

OCSP response:
======================================
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response

Then you have been successful. This page will be updated with SPDY, TLS 1.3 and HTTP 2.0 support.

Completed Configuration

You can find the wordpress.conf file for setting a ‘hardened’ wordpress for the TLS/SSL setting here:

https://gist.github.com/mosesrenegade/8b37188cb25860c6f523

Is there something I missed? Please comment below.

comments powered by Disqus

© . All rights reserved.