The main source I found for this useful stuff was at this excellent page, I just translated this into my environment.
The basic difficulty is that Traefik by default allows TLS 1.0 and 1.1 connections, along with their rather unfortunate weak ciphers. In addition, there are a bunch of security related HTTP headers that we can get Traefik to add for any services it serves to the world.
It’s a Very Bad Idea to support TLS v1.0 and a Bad Idea to support TLS v1.1, both of these are no longer secure. HTTPS sites should always serve TLS v1.2 as the lowest supported version. In some cases you may even want to limit a more sensitive site to a minimum of 1.3.
To set the default minimum TLS version to 1.2, you can set the default TLS options in the dynamic config file (traefik_dynamic.toml) as follows:
[tls.options.default] minVersion = "VersionTLS12" cipherSuites = [ "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305" ]
This sets the default minimum TLS version to 1.2 and limits the encryption cipher suites to the secure ones supported by TLS 1.2 and 1.3. If you have a need to limit some services to TLS v1.3, you can also add:
[tls.options.tlsv13only] minVersion = "VersionTLS13"
With that in place, you can add
traefik.http.routers.web1.tls.options=tlsv13only to the labels related to the service you want to secure with TLS v1.3.
The TLS version stuff above will make SSL Labs happier already, but it’s a good idea to add a bunch of headers that tell browsers and any potential proxy servers between the browser and Traefik how to behave.
The reasoning behind using these headers is beyond the scope of this post, there’s a lot of great info out there explaining them. Here I just show how to get Traefik to add these headers in case your application doesn’t.
In your traefic_dynamic.toml file, you can define a middleware as follows:
[http.middlewares.secure-headers.headers] sslRedirect = true frameDeny = true stsIncludeSubdomains = true stsPreload = true stsSeconds = 63072000 contentTypeNosniff = true accessControlAllowMethods = [ "GET", "POST" ] accessControlAllowOriginList = [ "https://web1.mydomain", "https://web2.mydomain", "https://web3.mydomain" ] accessControlMaxAge = 100 addVaryheader = true contentSecurityPolicy = "script-src 'self'" referrerPolicy = "origin-when-cross-origin"
You will want to edit the accessControlAllowOriginList line to show your origin servers.
Once that’s defined, you can add labels to your containers or file defined routers. In my previous post, I defined three routers (two via container labels and one in traefik_dynamic.toml). For the two defined in docker labels, just add these two labels:
- traefik.http.routers.web1.middlewares=secure-headers@file - traefik.http.routers.web2.middlewares=secure-headers@file
For web3, which is defined in traefik_dynamic.toml, you can add the line in bold shown below:
[http.routers.web3] rule = "Host(`web3.mydomain`)" entrypoints = ["web","websecure"] service = "web3@file" middleware="secure-headers@file" [http.routers.web3.tls] certResolver = "lets-encrypt"