tags | |
---|---|
|
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 negotiate a secret only known to the client and the server, that can be used to encrypt communication 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
This is in short how it works:
- 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
A certificate is a public key that is signed with some kind of private 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"
This way, gunicorn will serve your application over HTTPS on port 443.
So far this seems pretty secure. But there is just one caveat. What ensures that the public key received from the server is the real one, and has not been replaced by an attacker intercepting the communication?
Certificate authorities (CA) sign the public key of a server with their own private key. Web browsers come 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.
Browsers don't accept self-signed certificates as safe, so it will show a security warning when you try to use your own, self-signed certificate. Therefore, you have to use a CA that signs your certificate signing request.
Let's Encrypt is a Certificate Authority that allows you to generate an SSL Certificate by yourself with their Certbot. It requires a domain name and a public server to generate a public-private key pair, since Let's Encrypt does not issue certificates for bare IP addresses.
Sometimes DNS providers offer their own SSL certificates that you can use for your application. They are available for download and come with installation instructions, so follow that.
I will take Cloudflare as an example since this is what I am using, and it provides a free plan to play with the features.
This solution requires you to set an A record in the DNS settings of your domain, so all requests are proxied through the Cloudflare network. Requests will then go to Cloudflare encrypted and afterward will be forwarded to your origin server, unencrypted. Hence, you don't need to set up any encryption on your server or application. Here is a more detailed explanation of how Cloudflare proxies requests: Proxy status
Proxies such as Cloudflare provide additional functionality like response caching DDoS protection.
- SSL, TLS, HTTPS Explained - YouTube
- What are SSL/TLS Certificates? Why do we Need them? and How do they Work? - YouTube: I love this guy, he explains difficult concepts in great detail. He talks very slow, but he's fun and smart.