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:
1serversTransport:
2 rootCAs:
3 - /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:
1apiVersion: cert-manager.io/v1
2kind: Certificate
3metadata:
4 name: http-server-internal
5spec:
6 secretName: http-server-internal
7 duration: 2160h
8 renewBefore: 360h
9 ipAddresses:
10 # testing only
11 # guessing whick IP the pod will have
12 - "10.205.0.44"
13 - "10.205.0.45"
14 - "10.205.0.46"
15 - "10.205.0.47"
16 - "10.205.0.48"
17 - "10.205.0.49"
18 - "10.205.0.50"
19 issuerRef:
20 name: internal-ca
21 kind: ClusterIssuer
Setup and IngressRoute to point traefik to the service
1apiVersion: traefik.containo.us/v1alpha1
2kind: IngressRoute
3metadata:
4 name: http-server
5spec:
6 entryPoints:
7 - https
8 routes:
9 - kind: Rule
10 match: Host(`http-server.example.com`)
11 services:
12 - kind: Service
13 name: http-server
14 port: 443
15 scheme: https
16 tls: {}