Traefik doesn’t actually choose cipher suites or minimum TLS versions; it passes those decisions directly down to the underlying Go TLS library, which in turn relies on the operating system’s cryptographic providers.
package main
import (
"crypto/tls"
"fmt"
"net/http"
)
func main() {
// This is a simplified example. In a real Traefik setup,
// these options would be configured via dynamic config or static config.
// Default cipher suites for Go's TLS library (as of Go 1.19)
// This list is curated by the Go team for security and performance.
// You can see the current list in Go's crypto/tls source code.
// https://pkg.go.dev/crypto/tls#Config
// Default minimum TLS version for Go's TLS library (as of Go 1.19)
// This is tls.VersionTLS12.
config := &tls.Config{
MinVersion: tls.VersionTLS12, // Explicitly setting for clarity, though it's often the default
// CipherSuites: []uint16{ ... } // You *could* specify this, but it's rarely recommended.
}
server := &http.Server{
Addr: ":8443",
TLSConfig: config,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, world! TLS Version: %s, Cipher Suite: %x\n",
r.TLS.Version, r.TLS.CipherSuite)
}),
}
fmt.Println("Starting TLS server on :8443")
// In a real scenario, you'd also need to load your certificate and key.
// For demonstration, we'll use a self-signed cert.
err := server.ListenAndServeTLS("cert.pem", "key.pem")
if err != nil {
fmt.Printf("Error: %v\n", err)
}
}
When a client connects to Traefik over TLS, Traefik doesn’t have its own opinionated list of "good" or "bad" cipher suites. Instead, it configures the Go tls.Config struct, which is then used to establish the connection. The MinVersion and CipherSuites fields within tls.Config are the primary levers. However, for CipherSuites, the Go standard library’s approach is to use a secure default list if you don’t explicitly provide one. This default list is managed by the Go security team and is updated with new Go releases to reflect current best practices. Explicitly defining CipherSuites yourself is generally discouraged unless you have a very specific, well-understood requirement, as you risk disabling modern, secure ciphers or enabling older, vulnerable ones.
The MinVersion is more commonly adjusted. By default, Go’s tls.Config typically defaults to tls.VersionTLS12. If you need to support older clients, you might lower this to tls.VersionTLS10 (though this is highly discouraged due to security vulnerabilities in TLS 1.0 and 1.1). Conversely, if you want to enforce the absolute latest security, you might aim for tls.VersionTLS13. Traefik allows you to set this MinVersion through its configuration.
Here’s how you’d typically configure this in Traefik static configuration (e.g., traefik.yml):
# traefik.yml (static configuration)
entryPoints:
websecure:
address: ":443"
http:
tls:
options:
minVersion: "VersionTLS12" # Or "VersionTLS13" for stricter
# cipherSuites: # Rarely needed, use with extreme caution
# - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
# - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
# - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
And in Traefik dynamic configuration (e.g., Kubernetes Ingress or a Router definition):
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: secure-tls
spec:
minVersion: "VersionTLS13"
cipherSuites: # Again, use with caution. This list is illustrative.
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_256_GCM_SHA384
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-app-ingress
spec:
entryPoints:
- websecure
routes:
- match: Host(`example.com`)
kind: Rule
services:
- name: my-app-service
port: 80
tls:
secretName: my-tls-secret # Your TLS certificate and key
options:
name: secure-tls # Reference the TLSOption defined above
The key takeaway is that Traefik acts as a conduit for these TLS settings. It surfaces them in its configuration language but ultimately delegates the cryptographic choices to the Go standard library, which itself respects system-level security policies where applicable.
The most surprising thing is that if you don’t specify cipherSuites in your tls.Config (or Traefik’s equivalent TLSOption), the Go standard library doesn’t just pick any cipher suite. It has a hardcoded, curated list of modern and secure ones, and it prioritizes them based on performance and security. This default list is what most users should stick with.
When you set minVersion to VersionTLS13, Traefik tells the Go TLS library to only allow connections that negotiate TLS 1.3 or higher. This means older clients attempting to connect with TLS 1.2, 1.1, or 1.0 will be rejected outright. The cipher suites available for TLS 1.3 are also fundamentally different and more secure than those used in TLS 1.2.
The next concept you’ll likely grapple with is certificate management and how Traefik dynamically obtains and renews certificates, especially when using services like Let’s Encrypt.