IP Whitelisting in Traefik

- 2 mins read

Add externalTrafficPolicy: Local to a kubernetes service to capture source IPs.

The Issue

Kubernetes by default will not pass the source IP to a LoadBalancer service. Usually this is not particularly an issue most days, however this has become an issue as I re-combine all my rke2 clusters. It was simple before to place internal only applications on one of the two internal only clusters, as I move back to a single cluster Traefik needs to be made aware of source IPs so white listing can be used.

The Solution

Modify the Traefik Service

In general my preference is to use Kustomize, so Helm users will need to adjust their values to match, Traefik (as packaged by Helm) should create a List manifest named “traefik”, this manifest will need to be edited to add externalTrafficPolicy: Local to .items.0.spec example below:

---
# Source: traefik/templates/service.yaml
apiVersion: v1
kind: List
metadata:
  name: traefik
items:
  - apiVersion: v1
    kind: Service
    metadata:
      name: traefik
      labels:
        app.kubernetes.io/name: traefik
        app.kubernetes.io/instance: traefik
      annotations:
    spec:
      type: LoadBalancer
      externalTrafficPolicy: Local # Here
      selector:
        app.kubernetes.io/name: traefik
        app.kubernetes.io/instance: traefik
      ports:
      - port: 80
        name: web
        targetPort: "web"
        protocol: TCP
      - port: 443
        name: websecure
        targetPort: "websecure"
        protocol: TCP

This is well documented, but often overlooked.

Add a whitelist

Whitelists are applied per IngressRoute and generally very simple. A simple IPWhiteList would look like so:

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: ip-whitelist
spec:
  ipWhiteList:
    sourceRange:
      - 192.168.1.0/24

If Traefik is behind another proxy the depth of the IP can be set at spec.ipWhiteList.ipStrategy.depth. The whitelist can now be applied to your IngressRoute, like so:

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: meme
spec:
  entryPoints:
    - web
    - websecure
  routes:
    - match: Host(`init6.sh`) # Hostname to match
      kind: Rule
      middlewares:
          - name: ip-whitelist
      services: 
        - name: meme
          kind: Service
          port: 80
  tls:
    secretName: init6.sh

Sources: