For many sites, especially those run by individuals or small charities, the cost of obtaining an SSL certificate has been the main barrier to HTTPS everywhere. Even sites that really should have been accessed via an encrypted connection, such as those where users or administrators were asked to log in with passwords that they probably also use elsewhere, were often left using plain old un-encrypted HTTP.
The importance of encryption has never been higher. Mobile devices and laptops are ubiquitous, and with them comes the use of WiFi hot-spots. Sniffing traffic from unsecured hotspots or setting up fake access points is child’s play. The solution to this is HTTPS, which will authenticate that you’re connecting to the correct server and then provide end-to-end encryption of the communication.
But HTTPS only provides the guarantees that we want if the site operator obtains a signed certificate that is trusted by our web browser. Typically this meant paying for it. Some organizations, like CAcert, attempted to run an authority that provided free certificates. Unfortunately they were never trusted by the major browsers, which significantly limited their utility.
Historically you also needed to worry about your site having its own IP address, but that’s now a thing of the past thanks to SNI which is supported by recent versions of all major browsers.
Fortunately we also now have a solution to the problem of having to pay for the signed certificates. The solution comes in the form of Let’s Encrypt, an organization supported by the EFF, mozilla and many others. They are a truly free certificate authority, who issue certificates for free and use a high level of automation to keep their own costs low. They’re currently in a “public beta” phase, but you can use them right now to obtain certificates for your website.
To obtain a certificate from Let’s Encrypt you use their script. This can attempt to work in an entirely automated manner, assuming that you’re running a supported web server and that it can parse the server configuration correctly. I prefer a little more control, so I use it with its “webroot” plugin. It needs access to the web root in order to prove to the certificate authority that you’re the person who is really in control of the website.
# ./letsencrypt-auto certonly --webroot \ --webroot-path /srv/web/www.mysite.org/ \ -d mysite.org.uk -d www.mysite.org.uk
That will generate the appropriate keys and certificates and place them in /etc/letsencrypt/live/mysite.org/. Now you just need to configure your web server to offer up the new certificate. For an Apache VirtualHost (on port 443 for HTTPS) you need to add lines similar to the following:
SSLEngine on SSLProtocol all -SSLv3 -SSLv2 SSLCipherSuite !aNULL:!eNULL:!EXP:ALL:!ADH:!LOW:!EXP:!MD5:!3DES:!RC4 SSLHonorCipherOrder Off SSLCertificateFile /etc/letsencrypt/live/mysite.org/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/mysite.org/privkey.pem SSLCaCertificateFile /etc/letsencrypt/live/mysite.org/chain.pem
If you don’t have a webroot, perhaps because the site is entirely dynamically generated by a web application, then things will be harder. There is a manual method of obtaining certificates, but that’s not the recommended approach. Better would be to serve files from the web root if (and only if) they exist, and pass all other requests through to the web application. Using Apache this should be possible using the magic of mod_rewrite:
DocumentRoot /srv/web/mysite.org/ RewriteEngine On RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -f RewriteRule ^/(.+) /$1 [QSA,L]
Finally, I should note that the certificates produced are only valid for 3 months. So you’ll want to automate their renewal, probably on a monthly basis. For example, using cron:
25 6 3 * * cd /root/letsencrypt; ./letsencrypt-auto renew
Thanks to efforts like Let’s Encrypt and standards such as SNI I hope that in the near future we really will see HTTPS everywhere. Or at the very least nearly everywhere, and certainly everywhere that asks you to log in.
The approaches here still work, though it is also worth considering using DNS verification to gain access to wildcard certificates – which were not available through Let’s Encrypt when this post was written.
This https://www.vcloudnine.de/using-lets-encrypt-dns-01-challenge-validation-with-local-bind-instance/ and this https://certbot-dns-rfc2136.readthedocs.io/en/stable/ both document how to get that up and running with a local Bind 9 DNS server.
If you’re still using Debian Jessie this may also provide incentive to upgrade, as the CertBot DNS plugins won’t work there. Alternatively you can run the scripts inside Docker, but doing that while also still having domains that require access to the webroot to authenticate makes for a more complex set-up. Or at least more volume mounts for the docker container than suggested in the install docs.