For many months, I’ve been wanting to add TLS support for this blog, mainly because I believe that the web needs better security. As a content publisher and website owner it is in my best interest to make my content available over a secure connection.

I recently read a post from the Electronic Frontier Foundation, on how site-wide encryption helps fight censorship in other countries. The article is about Medium, a popular blogging platform, and how the use of TLS prevented the Malaysian government from completely blocking the site, in an attempt to suppress speech.

I decided that it was worth my time to finally use TLS.

How TLS Works

TLS stands for Transport Layer Security and it’s purpose is to have encrypted connections between two parties on the internet. It work thanks to the underlying public-key cryptography, which exploits the mathematics of large prime numbers and modulo operations. In the abstract, private-key cryptography relies on each party having a key pair consisting of a public and a private key. The public key can be widely disseminated and is used to encrypt data, while the private key is known only to one party and is the only way to decrypt data encrypted with the corresponding public key.

A helpful analogy is to think of a public key as a pad lock. You can send your pad locks to anyone. A person wanting to send a message only for you, can put the message in a box, lock it with one of your pad-locks and send it to you. Since you are the only one with the key, it can not be read in-transit. Also worth noting that public-key cryptography can also be used to sign communications, so that not only they can’t be read by eavesdroppers, but the intended party can verify that they haven’t been tampered with either.

On the web, when a browser connects to a server using TLS (by typing an address that starts with https), the server and browser negotiate an encryption key, to be used during the rest of the connection. Before that happens though, the browser must know that the server it connected too is trusted and is not an impersonator on the network (which is surprisingly easy to accomplish).

The server presents a digital certificate that is generated by the owner of the domain. The domain the browser connects to and the one in the certificate must match. However, to establish trust, certificates need also to be signed by a Certificate Authority (CA).

CAs are entities that issue digital certificates at the request of domain owners and after verification that the requestor is indeed the owner of the domain. Each browser ships with a known list of CAs and will trust connections to servers whose certificates have been signed by one of those CAs.

See Wikipedia’s article on public-key cryptography and TLS for much more information.

Picking a CA

There are many Certificate Authorities out there that can sign a certificate. There are also many types of certificates, with things like Extended Verification (EV), wildcard domains, etc. For my purposes, the simplest one was enough. I considered two options: Let’s Encrypt and StartSSL.

Let’s Encrypt is a new Certificate Authority that is run for the public benefit. It’s mission is to create a free service so that anyone with a domain can use a the secure web. StartSSL is a commercial CA, but offers a free tier for non-commercial use.

I am particularly excited about Let’s Encrypt, however I decided to not use them. The have decided to issue certificates that expire every 90 days. In order to not make it very onerous on the domain owner, they renewal can be automated, but only for those having access for installing software in their servers.

I however, use Nearly Free Speech, which gives me affordable, metered hosting for static websites that have bare minimum requirements. They do offer TLS, but it’s a manual process to setup, which I am OK with repeating yearly, but seemed a bit much every 90 days.

There is another intriguing option: CloudFlare offers free SSL termination with their free CDN service. To function, CDN require to have full control of a domain’s DNS records, so that they can switch them as load shifts. CDN cache invalidation was something that I didn’t want to tackle at this time, but for bigger websites it might be a great solution.

The Nitty Gritty

Nearly Free Speech has a great concise article on their member help site on how to setup TLS.

We first generate a private key:

$ openssl genrsa -out www.example.com.key 2048

And then generate a Certificate Signing Request (CSR):

$ openssl req -new -sha256 -key www.example.com.key -out www.example.com.csr

Using that CSR, I signed up for StartSSL free certificate. The process was simple: It required verification of domain access (they sent a verification email to the technical contact in the domain registrar’s listing) and submitting the CSR.

The certificate was issued immediately and was available for download.

After that, I followed the instructions from Nearly Free Speech, which required me to submit a support ticket and upload the certificate and key to a protected section of my hosting space. A few minutes later, TLS was enabled!

Remember to keep the private key in a safe place! Having that key means anyone can decrypt traffic to your site or impersonate your server on the internet.

Cleaning Up

Service a site in TLS has a few requirement: Not only the document has to be served in TLS, but also all the assets and external resources. Otherwise, the browser cannot guarantee the security and will issue a warning, usually by having a broken padlock next to the URL.

This blog required a few tweaks, like for example loading fonts from Google via https, which where explicitly being loaded over http. For example:

-<link href="http://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
-<link href="http://fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
+<link href="//fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
+<link href="//fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">

Note that instead of hardcoding https instead of http, HTML accepts references that start with // but no protocol: That directive is to use the same protocol that the document was loaded with.

I also changed the canonical link to my blog to be in https:

<link rel="canonical" href="https://ylan.segal-family.com/">

The rel="canonical" tag tells web crawlers what they should consider to be the main URL.

Once I verified that TLS was being server correctly and without warning. It was time to redirect all http traffic to https. My host uses Apache, so the process is as easy as adding a directive file:

# .htaccess
RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

Conclusion

Adding TLS support was not particularly time consuming, but doing the research on the different possibilities was. I am hopeful that new services like Let’s Encrypt are going to make TLS more accessible in the near future and that the web will be a better place because of it.