Situation: you have traefik as your reverse proxy / API gateway, traefik terminates TLS for client connections, but you also want TLS for the traefik-backend part.
tldr: possible securely with static backends, insecurely with dynamic (eg k8s)
When setting the scheme
to https
for backend services,
traefik uses TLS for connecting directly
to the IP address without ServerName
in the ClientHello
.
This causes issues since your certificate now needs to be signed for the
IP address (ephemeral on kubernetes) instead of a stable domain name
(any of $service
, $service.$namespace
, $service.$namespace.svc
,
$service.$namespace.svc.cluster.local
would have been fine).
This appears unlikely to be fully fixed soon, partial fix in v2.4.
Using internal Certificate Authority, generate CA cert+key (ex using mkcert). Inject CA cert into traefik container and run traefik with static config:
serversTransport:
rootCAs:
- /etc/internal-ca/ca.crt
Generate backend cert+key signed by CA key for the IP address and run server with it. Ex with Cert Manager:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: http-server-internal
spec:
secretName: http-server-internal
duration: 2160h
renewBefore: 360h
ipAddresses:
# testing only
# guessing whick IP the pod will have
- "10.205.0.44"
- "10.205.0.45"
- "10.205.0.46"
- "10.205.0.47"
- "10.205.0.48"
- "10.205.0.49"
- "10.205.0.50"
issuerRef:
name: internal-ca
kind: ClusterIssuer
Setup and IngressRoute to point traefik to the service
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: http-server
spec:
entryPoints:
- https
routes:
- kind: Rule
match: Host(`http-server.example.com`)
services:
- kind: Service
name: http-server
port: 443
scheme: https
tls: {}