We finished setting up Apache web server on Google Compute Engine in the last post. Now we’re finally ready for the whole point of this exercise: getting a free certificate from Let’s Encrypt for the new site at https://www.bibliote.ch/. We’re going to use certbot, so we follow that link to their site, and see a pretty user-friendly starting point:
We’re using Apache on CentOS 7 (a.k.a. RHEL 7) so we make those choices and get our instructions. But rather than following them (which include a step not needed on our Google image), here are the steps: SSH to your instance and issue the following commands.
sudo yum install -y python-certbot-apache
sudo certbot --apache
sudo service httpd graceful
You’ll have to answer some questions when certbot runs, but the answers are obvious or the default just works. And that’s it. If you go to your site on a fresh browser window you should no longer see any security warnings. This seems almost anticlimactic.
What just happened? Let’s Encrypt issues domain validation (DV) certificates. That means that they need to verify that the certificate requester (that’s us, here) is the authorized controller of the domain(s) to put on the certificate. Some certificate authorities will have the requester add a special record to their DNS; others ask them to put a special file somewhere on a web server in the domain. That latter is what Let’s Encrypt does. But certbot handles that automatically: it creates virtual hosts for each domain name on the certificate, starts them up on non-standard ports, and waits for Let’s Encrypt to check them. Then it gets rid of the domains and fetches and installs the certificate. It edits your Apache configuration files as necessary to do these steps. It’s all automatic and, in my experience, trouble-free.
The other possible kinds of certificates are organization validation (OV) and extended validation (EV). These require the certificate authority to check out who the requester is in the real world, such as checking company registration or business directories. That requires human interaction, so it takes more time and costs more. It’s not clear that these kinds of certificates actually protect web users any more than DV ones. In any case, this is a personal site and DV fits our needs fine.
And that’s it. Well, almost it. Your new certificate will expire in 90 days and the scary browser messages will come back. To solve that, put the following two lines in the system crontab using the command
sudo crontab -e to open it in the vi editor. Type an i to enter insert mode, type a variant of these lines, then hit the Escape key and ZZ (in caps) to get out of vi. (Yes, vi is really strange. The standard joke for it is “I’ve been using vi for years. Because I can’t figure out how to exit it.”)
17 6 * * * /bin/certbot renew --quiet
17 18 * * * /bin/certbot renew --quiet
This will make certbot check to see if the certificate is within 30 days of expiration, and it will automatically renew it if so. The check will run every day at 0617 and 1817 (UTC). Why those times? Let’s Encrypt suggests checking every 12 hours at a random starting time so everybody doesn’t hit their servers at the same time. I asked Google for random numbers between 1 and 12 for the hour and 0 and 59 for the minute and got 6 and 17.
We’ve done what we set out to do, but let’s make sure we not only have a secure web site, but a well-configured secure web site. The Qualys SSL Labs SSL Server Test site is a fantastic way to see how secure your server really is. Just go to that page and enter your URL. In a few minutes you’ll get a score:
Yech. That’s a passing score, but just barely. Reading the fine print, we see that the server supports the obsolete (and insecure) SSL 3 protocol, the now deprecated RC4 cipher, and doesn’t support new algorithms that enable forward secrecy. If you’d like to learn more about those things I strongly recommend the Bulletproof SSL and TLS book by Ivan Ristić. Ristić is one of the people behind the SSL test page we just used, and this book is authoritative and clear. A few years ago I spent several days studying TLS to work out the best configuration for my servers. But now there’s another option.
If you don’t want to study TLS in depth you can do what I do now: use the Mozilla SSL Configuration Generator. Fill in your web server (Apache), version number (2.4.6, displayed using
httpd -v), and OpenSSL version number (1.0.1e, displayed via
openssl version), and then select how aggressive you want to be on security. Older browsers can’t handle the most secure options, so if you want to support them you’ll select Old or Intermediate and live with lesser security. I selected Modern instead, to get the most secure options that work with pretty much anything at all recent. Based on what that shows, you’ll need to edit both
/etc/httpd/conf.d/ssl-www.conf. For each of them, remove or comment out the old lines for
SSLCipherSuite, and add the following lines:
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
Header always set Strict-Transport-Security "max-age=15768000"
Note that the next line after
SSLCipherSuite should be
SSLHonorCipherOrder. Your browser will likely split that long
SSLCipherSuite line and you’ll need to put it back together.
What do these lines do? The
SSLProtocol line essentially says “use any protocol version except for the known vulnerable ones SSL version 3 and TLS version 1 or version 1.1.” At the moment, that means use TLS version 1.2, though version 1.3 is getting close to being finalized. Note that there are even older versions of SSL that the line doesn’t exclude, but Apache and OpenSSL never support them, anyway.
SSLHonorCipherOrder tell the server which encryption algorithms to allow, and their preferred order. This is the line that requires either many days of study to figure out, or the use of Mozilla’s great generator. These combinations of algorithms are the ones still considered secure as of today. Not every browser supports every algorithm, which is why there are so many choices listed.
SSLCompression seems like a bad idea for performance, but it really doesn’t do any harm there, and it eliminates one kind of cryptographic vulnerability. Finally, the
Strict-Transport-Security header that’s now always being sent tells the browser to never again even attempt to connect to the site via plain HTTP, and to never accept an invalid certificate in the future.
sudo service httpd graceful to reload the configuration file, and test again (if you still have the old page open, just click the Clear cache link to do that). Now we get a much better score:
That’s more like it! We should check this periodically to make sure our certificate is getting renewed properly and that there are no newly discovered vulnerabilities we should address. Renewal is particularly important now, because the
Strict-Transport-Security header will cause browsers to refuse to connect to your site again if the certificate expires.
After several steps needed to set up any web server, and some very simple ones to get a certificate, we have a good secure server that we can do almost anything with, and it’s costing less than $5 per month.