A Complete Guide of SSL and the Provisioning of It With Traefik on Docker
Traefik Labs released version
2.4.0-rc1
recently. This version includes an ACME enhancement called External Account Binding which I had been waiting for quite some time now. After doing some testing, I can finally start writing this post. This post is aiming to provide a comprehensive review of using TLS certificates with Traefik. Although the environment I used was Docker, you should apply the same rules on other platforms.
TL; DR
It is very easy to provision TLS certificates to your server automatically with Traefik. What you need to do is to define a certResolver
in your static configurations and then tell Traefik how you want to use the certificate. Traefik will do the rest for you.
An example of certResover
:
1 | # Static configuration |
NAME_YOUR_PROVIDER
You can give your certResolver any name. For example, LE-http to indicate it is a provider for LetsEncrypt with http-01 validation method. You can create multiple
certificatesResolvers
and choose the right one for yourrouter
.YOUR_VALID_EMAIL :
Provide a valid email address to recieve renewal notification. Some CA will reject your requests if you use bogus email addresses.
-
Some commercial CAs does not have a fixed ACME URL. Users need to generate ACME directory URL from their accounts. Please follow your certificate provider’s instructions to generate these urls.
-
Although CAB forum allows the use of 521 bit ECC key, most CAs only accept 256 or 384 bits ECC keys.
EXTERNAL_ACCOUNT_BINDING (EAB)
Commercial CAs normally require users to generate EAB credentials from their accounts to pair with their ACME URLs. Although Zerossl is free, you still need to create an account and genreate EAB credentials as it is under Sectigo’s root.
SSL Basics
The whole PKI industry had been forced to adapt some critical changes In the past few years. Major browsers like Chrome started marking http webpages not secured since 2018, certificate validty was reduced from 3 years -> 2 years and it is reduced to 1 year. Especially after the official release of Let’s Encrypt, SSL certificate should be default feature of any public facing websites. I won’t be covering what SSL is or how SSL worksto day, I would be talking about a few SSL concepts and then explain the configurations I use with Traefik.
Key Algorithm
The CAB forum baseline requirement currently requires key strengths of all issued TLS certificates are at least 2048-bit RSA using SHA-256, SHA-384 or SHA-512 or Elliptic Curve using NIST P-256, P-384, or P-521. Most of the TLS certificate issued today are based on RSA 2048 keys. What is ECC key?
from Wikipedia:
Elliptic-curve cryptography (ECC) is an approach to public-key cryptography based on the algebraic structure of elliptic curves over finite fields. ECC allows smaller keys compared to non-EC cryptography (based on plain Galois fields) to provide equivalent security
ECC Key Size | RSA Key Size |
---|---|
256-bit | 3072-bit |
384-bit | 7680-bit |
521-bit | 15360-bit |
According to this article, ECC certificates has smaller size and better security and performance. Unless very old systems/devices support are need, I reckon everyone should start using ECC private keys to generate their TLS certificates.
Certificate coverage
Except EV certificate, users can get a single domain, a multi-domain certificate or a wildcard certificates depends on their needs. Single/Multi-Domain SSL are pretty self-explanatory, your certificate covers a single or multiple FQDN. Wildcard certificate on the other hand covers ALL sub-domains of one level. For example, *.my.domain
covers <EVERYTHING>.my.domain
. As there is nothing in the front, my.domain
is not covered. If you want it to be covered, you need to add it as SAN to your wildcard certificate.
Why do we use different CAs?
There are 5 aspects users need to consider from which Certificate authority they get their certificates from.
Reputation
This option looks stupid, why would anyone get their cert from a non-reputatble CA? When you are applying a certificate you naturally want to make sure it will work till it expired. Choosing certificates from a more reputatble CA might help users avoid service distruption if certificate needs to be revoked and replaced in time. Let’sEncrypt revoked 3 million certificates in March 2020 due to a CAA check bug they had . You can read the whole story here.
The root matters
TLS certificates are trusted because their roots are pre-installed and trusted on softwares, devices, browsers or operating systems. It is critical to know if certificate’s root is supported on clients’ environment before making the purchase. SSL certificate won’t be trusted if its root is not pre-installed on clients’ devices. For example, . A good example is again, Let’sEncrypt, they are cross signing their certificates with ISRG Root X1
(newer root) and DST Root CA X3
roots. If most of your clients are using older systems, you probably want to avoid using Let’sEncrypt’s newer root to sign your certificate.
Clarity of workflow
Users need to know what the steps are to get their certificates issued. Even for a simple DV certificate, sometiems it takes a long time simply because users are unclear about what they need to do to get their certificates issued.
Validation Method
Although CAB forum baseline requirement defines how validation should be done, different CAs have their own interpretations. It is important to get your certificate from a CA that provides easiest validation methods. For example, DNS validation, some CAs only allow DNS CNAME records while the others allow both DNS TXT or DNS CNAME records.
OCSP response speed
This is often overlooked by users but it is actually critical. Every time your client connects to your server via https, there will be some sort of revocation checks behind the scene. Chrome is using CRLset, Firefox and others are using OCSP to check certificate status. (This is part of the reason people feel Chrome is faster than its rivals) There are lots of software and devices are using OCSP to do certificate checks. It is very important to make sure your certificate OCSP response is quick and stable. If you want to know more about how SSL revocation check affects connection speed, you can read this article.
Let’s move on to today’s main topic.
SSL certificate provisioning
You might have already sensed that, I take TLS security seriously. IMO no public facing application/webpages should be deployed without TLS. Ever since I found Traefik, it quickly became my MUST-HAVE tool to deploy applications on Docker. I can hide all application at the back and use Traefik to handle all SSL handshakes without configuring each application itself.
Traditional Method
The traditional way of provisioning TLS certificate can be summarised in 5 steps.
- Generate private key and CSR on users server/device
- Provide CSR to the CA.
- Complete required validation.
- CA issue the certificate to you in the format your server needs.
- Install this certificate on your server.
If you prefer using TLS certificates this way with Traefik, you can check my previous post for more detail.
Automated Method with Traefik
If you are lazy as I am, you probably want your tool to do as much work as possible for you. Provisioning TLS certificate via ACME protocol does exactly that. Tools like certbot
and cert-manger
have been widely used for quite some time now. Traefik also utilise ACME protocol for provisioning certificates.
Most commercial CAs should support ACME protocols nowadays. If your CA does not support ACME, you probably need to consider purchasing certificates somewhere else. (IMO there is no excuse for a commercial CA not to have ACME support)
Free SSL providers
Here are 3 free SSL certificate providers that issue certificates free of charge to everyone via ACME protocol.
CA Name | Rate Limit | FQDN Limit | preferredChain |
Wildcard | Required EAB |
---|---|---|---|---|---|
Let’s Encrypt | 50/week | 100 Names/cert | Yes | Yes | No |
Buypass | 20/week | 5 Name/cert | No | No | No |
ZeroSSL | No | No | No | Yes | Yes |
You can find their root certificates below.
ZeroSSL’s intermediate certificates are issued under Sectigo’s root. Hence the roots name contain
USERTrust
.A fun fact: A lot of certificate providers are merely sub-CAs, they do NOT have their own roots. I was surprised to find out Sectigo (formerly Comodo) had issued a HUGE number of sub-CAs. You can find all sub-CAs certificates issued under these two
USERTrust
roots here if you are interested.
Name | Valid From | Valid To | Signature Algorithm | Serial |
---|---|---|---|---|
DST Root CA X3 | 2000-09-30 | 2021-09-30 | SHA1-RSA | 44afb080d6a327ba893039862ef8406b |
ISRG Root X1 | 2015-06-04 | 2035-06-04 | SHA256-RSA | 8210cfb0d240e3594463e0bb63828b00 |
Buypass Class 2 Root CA | 2010-10-26 | 2040-10-26 | SHA256-RSA | 2 |
USERTrust ECC Certification Authority | 2010-02-01 | 2038-01-19 | ECDSA-SHA384 | 5c8b99c55a94c5d27156decd8980cc26 |
USERTrust RSA Certification Authority | 2010-02-01 | 2038-01-19 | SHA384-RSA | 01fd6d30fca3ca51a81bbc640e35032d |
CA ACME directory URLs
Free CA production ACME directory URLs.
Let’sEncrypt
1
https://acme-v02.api.letsencrypt.org/directory
Buypass
1
https://api.buypass.com/acme/directory
ZeroSSL
1
https://acme.zerossl.com/v2/DV90
Validation Methods
You need to define validation method of your certResolver
. There are three methods, http-01
, dns-01
and tls-01
. I will only cover the first two.
DNS-01
1 | dnsChallenge: |
**DNS_PROVIDER_NAME **: Please provide your dns provider here. You can check the full list of supported providers here.
You can also use custom DNS servers to resolve FQDN by adding resolvers
param. In above example, I am using cloudflare as my DNS resolver because it is the fastest resolver according to dnsperf.
HTTP-01
You just need to let Traefik know the name of your port 80 entry point. In official documentation, port 80 entry point name is web
.
1 | entryPoints: |
Preferred chain
If you feel the need of using different root with LetsEncrypt after reading above section, you can add preferredChain
param to your ACME resolver. You can find official doc here.
1 | preferredChain: 'DST Root CA X3' |
External Account Binding
It is actually pretty straight forward, you just need to add below to your ACME resolver. You can find the official documentation here.
1 | eab: |
Usage Examples
After reading above, I hope you will have some ideas of what certificate you want to use for your service. Let me list down some examples:
To define providers
1 | entryPoints: |
As you can see, the first two are using http-01
validation method with entry point web
. If you choose to use Let’sEncrypt, you don’t need to specify caServer
url. You might have also noticed that I am using the same email address for all certResolver, that’s because of a bug
(I believe it is a bug) that was briefly mentioned here. Frankly this requirement makes no sense to me…🥱
The next two providers are using dns-01
. One is using acme-dns
provider, the other one is using cloudflare
. acme-dns
is useful if your DNS management provider is not a supported provider. To know more about using acme-dns
, pleaes read this post.
To use Providers
Official configuration examples shows how to assign certResolver
to each router.
Defining a certificates resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must reference it.
You can also define a default
certResolvrer in your static configuration to avoid adding cert resolver to each router. My static config does exactly that. As you can see from below code snippet, I am using letsencypt
as my default resolver.
1 | entryPoints: |
Extra Settings
entryPoint http redirect to https
This feature was introduced in v2.2. I was so excited about its release I even wrote a post for this feature. You can find official documentation here.
HSTS secure headers and Mozilla SSL Intermediate config
If you followed any of my tutorials before, you may have noticed that I’ve been using these setting in my dynamic configuration.
I define a
headers
middleware calledsecureHeaders
. This is for HSTS. Please check please check Wikipedia or Chromium HSTS preload list website to understand each setting and make your own decision if you want to use it or not, especiallystsPreload
.If you maintain a project that provides HTTPS configuration advice or provides an option to enable HSTS, do not include the
preload
directive by default. We get regular emails from site operators who tried out HSTS this way, only to find themselves on the preload list by the time they find they need to remove HSTS to access certain subdomains. Removal tends to be slow and painful for those sites.I got my TLS options from Mozilla SSL Configuration Generator. I chose the intermediate config for better compatibility.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# Dynamic configuration
http:
middlewares:
secureHeaders:
headers:
sslRedirect: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
tls:
options:
default:
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
minVersion: VersionTLS12
That’s all I want to share today. I did not expect to write such a long post before I started but I guess it is a really good start of 2021.
Thanks for reading, see you next time.