NGINX SSL - Score an A+

Having just setup this blog I though I would cover the SSL setup with NGINX. Chrome, Firefox and other browsers are now marking plain text HTTP sites as "insecure" so having SSL enabled on a site is becoming important, tie this together with LetsEncrypt free SSL and it should become part of a standard webserver build these days.

Getting an A Ranking

First off you will need to install LetsEncrypt using your distributions package manager ( apt-get , yum , dnf , pac man etc )

Once Installed you will need to ensure that the DNS for your site is correct and replicated.

Now we will need to use certbot to request the certificates

# sudo certbot --nginx certonly -d mydomain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Obtaining a new certificate
Performing the following challenges:
    http-01 challenge for mydomain.com
    Waiting for verification...
    Cleaning up challenges

IMPORTANT NOTES:
     Congratulations! 
Your certificate and chain have been saved at: /etc/letsencrypt/live/mydomain.com/fullchain.pem

Your key file has been saved at: 
/etc/letsencrypt/live/mydomain.com/privkey.pem 

Your cert will expire on 2019-02-27. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew all of your certificates, run "certbot renew"

     If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le

Now we will need to configure your site to listen on 443, for this example I am using NGINX as a proxy for Ghost.  Note the ssl_protocols line, this is what gets you the "A" ranking as we have disabled old TLS 1.0 & TLS 1.1 protocols by removing them from this line.  Disabling TLS 1.0 & 1.1 may result in users who are on older devices being unable to access your website, so please bare in mind your audience when disabling these legacy security mechanisms.

server {
	listen 443;
	server_name mydomain.com;
	root /var/www/ghost/system/nginx-root;


    ssl on;
    ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;

	location / {
   		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    	proxy_set_header X-Forwarded-Proto $scheme;
   		proxy_set_header X-Real-IP $remote_addr;
   		proxy_set_header Host $http_host;
    	proxy_pass http://127.0.0.1:2368;
	}

    location ~ /.well-known {
        allow all;
    }

    client_max_body_size 50m;
}

Next, before we restart NGINX we should check the configs for errors using the -t flag.

# nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

If the test is successfully then restart NGINX else fix the issues reported

# service nginx restart

Getting the A+

To get an A+ on the SSL Labs and others you need to enable HTTP Strict Transport Security or HSTS . This enables extra security which should prevent downgrade attacks and possible cookie hijacking. Something to bare in mind with this is that it will require all sub domains to have a certificate and could cause some issues when moving hosts. To enable this we just need to add a new header into our site, the easiest way to do this is by adding the add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; line into our SSL site config above :

server {
	listen 443;
	server_name mydomain.com;
	root /var/www/ghost/system/nginx-root;


    ssl on;
    ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;

	location / {
   		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    	proxy_set_header X-Forwarded-Proto $scheme;
   		proxy_set_header X-Real-IP $remote_addr;
   		proxy_set_header Host $http_host;
    	proxy_pass http://127.0.0.1:2368;
	}

    location ~ /.well-known {
        allow all;
    }

    client_max_body_size 50m;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

Again test NGINX with -t flag and restart the service once everything checks out. If everything goes as planned then you can use https://www.ssllabs.com/ssltest/ to check your rating.

TLS v1.3

Although NGINX does support TLS 1.3 you will need a update to OpenSSL 1.1.1 to take advantage of it.