Client IP Address Appears as Traefik Pod IP

Hello everyone,

After many hours of testing and searching on this forum, I have not found a solution to my problem.

I have a K3S Cluster (1 control plane and 2 worker). Traefik (v3.2.0) is deployed as a Daemonset. A Traefik loadbalancer Service is deployed on my Cluster (metallb) with externalTrafficPolicy to Local.

A client (outside the cluster) is trying to make connections to an application (within my cluster) through Traefik loadblancer service. This flow works well, but the issue is that the source IP seen from the application corresponds to the IP of one of the Traefik pods (not the real client's).

I have tried:

  • proxy protocol on entry point
  • proxy protocol on ingressRouteTcp
  • externalTrafficPolicy to Local to my Traefik service

None of these solutions work. However, Traefik does see the remote address as the client one.

If I don’t go through Traefik to access my application and I expose a service of type LoadBalancer with externalTrafficPolicy set to Local, the client IP is correct.

Any help would be greatly appreciated.

Here is my configuration:

Traefik:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  namespace: traefik
  name: traefik
  labels:
    app: traefik
spec:
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      tolerations:
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Exists"
          effect: "NoSchedule"
      serviceAccountName: traefik-ingress-controller
      volumes:
        - name: docker-socket
          hostPath:
            path: /var/run/docker.sock
      containers:
      - name: traefik
        image: storage.registry:5001/traefik:v3.2.0
        imagePullPolicy: Always
        envFrom:
          - configMapRef:
              name: traefik-entrypoints-global
        env:
          - name: TRAEFIK_ACCESSLOG
            value: "true"
          - name: TRAEFIK_API_DASHBOARD
            value: "true"
          - name: TRAEFIK_API_INSECURE
            value: "true"
          - name: TRAEFIK_ACCESSLOG
            value: "true"
          - name: TRAEFIK_LOG_LEVEL
            value: "TRACE"
          - name: TRAEFIK_PROVIDERS_DOCKER
            value: "true"
          - name: TRAEFIK_PROVIDERS_KUBERNETESCRD
            value: "true"
          - name: TRAEFIK_PROVIDERS_KUBERNETESCRD_ALLOWCROSSNAMESPACE
            value: "true"
          - name: TRAEFIK_ENTRYPOINTS_TOOLS_ADDRESS
            value: ":4444"
          - name: TRAEFIK_ENTRYPOINTS_TOOLS_PROXYPROTOCOL
            value: "true"
          - name: TRAEFIK_ENTRYPOINTS_TOOLS_PROXYPROTOCOL_INSECURE
            value: "true"
        volumeMounts:
          - mountPath: /var/run/docker.sock
            name: docker-socket

Traefik service:

apiVersion: v1
kind: Service
metadata:
  name: traefik
  namespace: traefik
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
    - protocol: TCP
      name: tools
      port: 4444
      targetPort: 4444
    - protocol: TCP
      name: dashboard
      port: 8080
      targetPort: 8080

  selector:
    app: traefik

IngressRouteTcp:

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: myapp-service-traefik-tcp
spec:
  entryPoints:
    - tools
  routes:
    - match: ClientIP(`10.10.205.30`)
      priority: 50
      services:
        - name: myapp-service-traefik
          port: 8080
          proxyProtocol:
            version: 1

Thanks !

Try this configuration:

deployment:
  kind: DaemonSet

service:
  spec:
    externalTrafficPolicy: "Local"

(the values are for the Helm chart). This works for me. The daemonset ensures that the external load balancer always finds an instance of traefik on any node and the traffic does not have to be forwarded thru the cluster.

Hello and thanks for your reply

I have already tried this configuration. Traefik is deployed as a daemonset and my traefik service is LoadBalancer type with externalTrafficPolicy: "Local".

I've to had a haproxy in front of my pod Traefik. With the directive send_proxy haproxy sends the proxy protocol header.
I need to update my final client to decode this header to get to client IP in scr addr

server traefik traefik.traefik.svc.cluster.local:4444 send-proxy

Traefik entry point and IngressRouteTcp have also proxy protocol activated:

          - name: TRAEFIK_ENTRYPOINTS_TOOLS_PROXYPROTOCOL
            value: "true"
          - name: TRAEFIK_ENTRYPOINTS_TOOLS_PROXYPROTOCOL_INSECURE
            value: "true"
  entryPoints:
    - tools
  routes:
    - match: HostSNI(`*`)
      priority: 50
      services:
        - name: myapp-service-traefik
          port: 8080
          proxyProtocol:
            version: 1

With this configuration (source -> haproxy -> traefik -> client), I'm able to get real source IP

hi, Where did you put this config?
I faced the same issue but with UDP. I set this config for UDP entryPoint

 - --entryPoints.udp.address=:4001/udp
        - --entryPoints.udp.proxyProtocol.insecure=true
        - --entryPoints.udp.proxyProtocol.trustedIPs=0.0.0.0/0

But at the UDP server, I still got the traefik pod IP as source IP.

To receive ProxyProtocol on the target service side, you need to enable ProxyProtocol on the Traefik service proxying/forwarding the packets (doc). But it might only be available for TCP, not UDP.

Hi @bluepuma77, If it doesn't work for UDP, do you have any idea how to keep the source IP as intended? I want to send syslog messages via Traefik UDP to a Logstash instance deployed as a pod in Kubernetes, which then forwards them to Elasticsearch. With the current configuration, every log I receive shows the host as the IP of the Traefik pod.

You can test it. If it doesn’t work, you can open a feature request on Traefik Github. But I am not sure it will be implemented.

Hi @tuongvu

This configuration is haproxy one. The only way for me to get source IP is to

  1. set haproxy in front of Traefik
  2. Add proxy protocol at all level (haproxy/send-proxy, traefik entrypoint and IngressRouteTcp)
  3. update my final client to get the real source IP in PROXY PROTOCOL Header (begining of TCP frame).

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.