Transport layer security

The HTTP protocol was not designed to encrypt the data passed between the client and the server. The Transport layer security (TLS) protocol is used to negociate a secret only known to the client and the server, that can be used to encrypt communiction over the network. This can be used to encrypt HTTP requests and responses, but also various other types of network communications, such as:

  • Secure Email (SMTPS, POP3S, IMAPS)
  • File Transfer (FTPS, SFTP)
  • Secure Shell (SSH)
  • Database Connections

Here is how the negociation of the session key for encryption is performed:

Video Summary:

  • The server sends it’s TLS/SSL certificate to the client. This is the public key of the server
  • The client generates a session key and encrypts it with the public key of the server
  • The encrypted session key can only be decrypted with the private key of the server, so nobody in the middle can read the session key

So far this seems pretty secure. There is just one caveat. What ensures that the public key recieved from the server is the real one, and has not been replaced by an attacker intercepting the communication?

Certificate authorities

Certificate authorities (CA) sign the public key of a server with their own private key. When you install a web browser on your computer or device, it comes with a pre-defined list of trusted CAs, known as the “root certificate store” or “trusted root certificates”. CAs take the public key of the server, encrypt it with their private key, and append the signature to the certificate of the server. The signature can then be verified by every browser by decrypting it with the CA’s public key. The result should be identical with the public key provided by the server.

Create a self signed certificate

You don’t necessary need a CA to sign your public key. You can generate a public and private key pair on your own and sign the public key with the same private key. This is called a self signed certificate.

Here is how you can do it (OpenSSL required):

# Generate a Private Key and a Certificate Signing Request (CSR)
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr
# Generate the Self-Signed Certificate
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Then you can use the certificate and the key as settings in the gunicorn.conf.py file.

bind = "0.0.0.0:443"
keyfile = "/path/to/server.key"
certfile = "/path/to/server.crt"

Now when you start gunicorn, your app will be automatically served with HTTPS on port 443. The problem is that browser won’t accept self signed sertificates as safe, so the security warning that you will get from your web browser you will be something like this. Therefore you have to use a CA that signs your certificate signing request.

Let’s Encrypt

Let’s Encrypt is a Certificate Authority that allows you to generate an SSL Certificate by yourself with their Certbot. You will require a domain name1 and a public server2 to generate a public-private key pair, since Let’s Encrypt does not issue certificates for bare IP addresses. Go to certbot.eff.org, select “My website is running other on pip” and follow the instructions.

certbot

After you have generated the cartificate and the public key, you can configure gunicorn to serve your application via https, as described in the previous section.

Other options

Sometimes DNS providers offer their own SSL certificates that you can use for your application. You can download them and install them on your server as described. Or, for example Cloudflare, offers an interesting solution, where you don’t even need to set up your webserver to serve over https. When you set up an A record in the DNS settings of your domain at Cloudflare, you can choose to proxy all requests through the Cloudflare network. This means that all requests intended for proxied hostnames will go to Cloudflare first and then be forwarded to your origin server. 3

This allows Cloudflare to cache requests to your application and protect your application from DDoS attacks, which is pretty cool stuff if you ask me. And it is entirely free! (except for the domain name) In the simplest case, you don’t even need a secure connection between Cloudflare and your server. But in case you don’t trust Cloudflare, you can use a self signed certificate to encrypt the connection.

Further reading

  1. I would personally recommend Cloudflare because they have a lot of other cool features, like caching, DDoS attack prevention, Analytics, etc. But feel free to try other alternatives 

  2. Feel free to use your prefered hosting provider, e.g. Digital Ocean, Linode, etc. 

  3. Here is a more detailed explanation of how Cloudflare proxies requests: Proxy status