fyi: Consider reading this first (newer blog post): How to buy a new domain and SSL cert from NameCheap, a Server from Digital Ocean and configure it.
If you have read my quickest way to setup a scalable development ide and web server guide chances are you setup a www.c9.io development IDE connected and Digital Ocean Ubuntu VM in the cloud for about $5 a month. It did not take me long to install an NGINX web server, PHP, MySQL and phpMyAdmin sites. The next logical step is to secure my site with an SSL certificate.
I have purchased commercial SSL certificate in the past for a CPanel sub domain and they cost about $150 a year. I always thought the certificate was set in stone and if it was a weak certificate it would perform poorly in the essential https://www.ssllabs.com/ssltest/index.html certificate tester.
I ran a quick test over my previously purchased managed host provided certificate (lets just say it performs poorly).
Generating a $0 self signed SSL Certificate (Digital Ocean VM)
Digital Ocean have fantastic guides and I searched Google for “digital ocean how to create an ssl certificate” and read this guide. Within a few minutes I had generated a self signed certificate and added it to my NGINX config and had SSL enabled on my site. The only problem the certificate said it was not trusted by a third party (this may be ok for a closed development box but it would not be good on a production environment).
Generating a $9 commercial SSL Certificate (Digital Ocean VM)
I googled and found this Digital Ocean guide How To Install an SSL Certificate from a Commercial Certificate Authority.
Without listing each step I performed I was able to generate a “key” and “csr” file (from the digital ocean guide, I ignored the Namecheap’s guide). These files are needed to seed the commercial SSL certificate.
I decided to buy a domain certificate from RapidSSL via Namecheap (as they responded to a Livechat support request where GoDaddy ignored the live chat). A Namecheap certificate for my subdomain was going to cost me $9 US a year (that is mega cheap compared to the $150 a CPanel host was going to charge me). Maybe the $9 certificate will be crap?
I followed the digital ocean guide and to my surprise I had a valid certificate emailed to me within 15 minutes once I followed the process to purchase, verify activate the certificate. To Namecheap’s credit the live chat person (“Anastasia B”) stuck with me as answered frequent questions I had (I thought $9 was too good to be true).
Once I had the commercial keys I was able to generate the private/public keys that feed into the commercial certificate with this command (replace “thesubdomain” with your subdomain and the “the domain” with your domain, if you are not applying the certificate to a subdomain then exclude the sub domain.).
> openssl req -newkey rsa:2048 -nodes -keyout thesubdomain_thedomain_com.key -out thesubdomain_thedomain_com.csr
The contents of the locally generated certificates were then pasted into the Namecheap SSL pages based on the digital ocean guide. At the end of the Namecheap purchase and verification process I was emailed 4 files that make up the certificate. The Digital Ocean and Namecheap guides were a bit short on combining the certificated but this was the working command to merge the bits intone valid certificate.
> cd /etc/nginx/ssl/
>cat thesubdomain_thedomain_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt >> cert_chain.crt
Then all I had to do was configure NGINX to use the certificate.
> listen 443 ssl;
> server_name thesubdomain.thedomain.com;
> ssl_certificate /etc/nginx/ssl/cert_chain.crt;
> ssl_certificate_key /etc/nginx/ssl/thesubdomain.thedomain.key;
A quick restart of the NGINX server and the certificate was good to go, I now had trusted SSL certificate enabled on my site.
I ran a SSL labs test over the site and got a lame C ranking. WTF, I though SSL was supposed to make sites secure. Maybe there is more I can do to make this secure.
Research and Lockdown Mode
I googled as much as I could find on NGINX and SSL security.
To me the biggest failing point in the OpenSSL test was a weak PRIME in the Diffe-Hellman crypto, I thought I could just disable these crypto algorithms but this was not the case. The secret is to generate a new 2048 bit key on my digital ocean server for ssl to use in connections with browsers instead of the known 1024 bit key. This was as simple as running this command (and waiting 10 mins):
> openssl dhparam -out dhparams.pem 2048
>Generating DH parameters, 2048 bit long safe prime, generator 2
>This is going to take a long time
Then when the key is generated you can add it to your NGINX config
> ssl_dhparam /etc/nginx/path/dhparams.pem;
So after much trial and error this is the bulk of my NGINX configuration
listen 443 ssl;
# Change to your server
# Location of the private key and merged certificates
# Here are the cyphers we are ignoring
# ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
# Only use a small set of ciphers (may not work on older devices or browsers (but screw them)
# Force only allowing the ciphers above
#use the 2048bit DH key
# Don't allow old encryption methods like SSL3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# Set SSL caching and storage/timeout values:
# More info: http://nginx.com/blog/improve-seo-https-nginx/
# Prevent Clickjacking
add_header X-Frame-Options DENY;
# Prevent MIME Sniffing
add_header X-Content-Type-Options nosniff;
# Disable session tickets
ssl_session_tickets off; # Requires nginx >= 1.5.9
# OCSP (Online Certificate Status Protocol) is a protocol for checking if a SSL certificate has been revoked
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on; # Requires nginx => 1.3.7
# Use Google DNS
resolver 126.96.36.199 188.8.131.52 valid=300s;
# force https over http
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
# No need to manually redirect all traffic to https as the header above does this
#rewrite ^/(.*) https://thesubdomain.thedomain.com/$1 permanent;
This is my result on SSLLabs SSL test now. Not bay for $9 and a few hours researching.
A big Thank You goes to “Anastasia B” on the Namecheap Livechat, they stuck with me while I jumped ahead and ignored the guides.
Also listen to this podcast of you an to understand how HTTPS and the internt works.
Also check out how to update your Open SSL and security: https://fearby.com/article/update-openssl-on-a-digital-ocean-vm/
Having ssl may not be enough, do check your website often in https://www.shodan.io and see if it has open software or is known to hackers.
Please signup for our newsletter
Donate and make this blog better
Ask a question or recommend an article