IP Whitelisting in Traefik
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