FINALLY. After months of intermittently pounding my head and trying to figure this out, I finally got SSL (Secure Socket Layers) working on nginx (this blog’s web server) alongside the SSL-based OpenVPN Access Server. It was quite an adventure and took a bit of trial and error since most of the sites I found out there are pretty good at detailing some of the steps, but there was always something lacking.
First things first, I needed to change the way OpenVPN presented its web GUI. Normally, connecting a browser to
https://private.vertner.net (my VPN’s subdomain) would present OpenVPN’s client login page. I don’t support any external clients and don’t really have a need to download OpenVPN client configuration files when I’m away from my local network, so I switched the OpenVPN client login page over to port 943 (where the administrator login page resides). Just look under the Server Network Settings page and set the Client Web Server to Use the same address and port as the Admin Web Server. While on that same page, make sure that your Protocol is set to TCP. Why TCP? Because the default UDP port is sometimes filtered on networks and – as I learned the hard way – multi-daemon mode isn’t supported with port-sharing.
OpenVPN’s port-sharing feature is for doing exactly what we’re trying to accomplish. Basically, it allows OpenVPN to monitor port 443 (the default SSL port) and pass any non-VPN traffic heading into port 443 to another port. Simply go to Advanced VPN Settings and add
port-share 127.0.0.1 4343 or whatever unused port number you want to the Server Config Directives.
Heading over to my server configuration file, I changed my primary server configuration block from this:
1 2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Now, instead of listening for vertner.net traffic on port 80, it’s listening on the port 4343 that I defined earlier in OpenVPN. I’m purposefully only allowing certain protocols and cyphers to eliminate the security holes created by using older deprecated encryption methods.
I could generate self-signed certificates, but most browsers will generate errors instead of trust for doing so. Instead, I headed over to StartSSL and registered for a free SSL certificate and in order to get the following files:
- An encrypted private key file (ssl.key)
- The SSL/TLS certificate with a public key (ssl.crt)
- An intermediate and root certificates which identify StartCom as a CA (certificate authority) (sub.class1.server.ca.pem and ca.pem)
I copied the ssl.key and ssl.crt over the server, created a new directory for nginx to store these files, then moved them into my new directory using the following commands:
1 2 3 4 5
That last command should prompt you for your certificate password to decrypt the key. Next, I secured the decrypted key a bit by entering the following commands:
This way if the site is compromised, the exploiter will only be able to read the contents of the key if they also get root access. Next, I downloaded the CA certificates with my old friend
wget and squeezed all of the certificates together using
1 2 3 4
With my certificates installed and ready, I made some minor additional tweaks to my server configuration file. First, I altered my “stop trying to go to www.vertner.net” block like so:
1 2 3 4 5
This makes it so anybody who comes to the site on regular unsecured port 80 (http) will be automatically redirected to the secure site. Next, I wanted to make sure that anybody who tried to go to my VPN subdomain for a web page would also get pushed over to https://vertner.net by adding the following:
1 2 3 4 5 6 7 8 9
I saved my work and reloaded nginx with a quick
sudo /etc/init.d/nginx restart.
Testing My Work
Finally, I wanted to verify the security of my SSL implementation. The number of very aggressive SSL exploits coming out in the last few years should be a cautionary tale for anybody looking to secure their sites. I headed over to Qualys SSL Labs Server Test and put it to the test. I’m making a note here: huge success.