How can I get the real IP address of the source

network topology

client --> google cloud Network (Passthrough) TCP Load balancing --> traefik --> k3s pods

How to install it

I used several virtual machines to build a K3S cluster, and Traefik was installed directly through K3S

traefik version

rancher/mirrored-library-traefik:2.11.10

k3s ingress && middlewares

---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: proxy-headers
  namespace: prod
  resourceVersion: '622452'
spec:
  headers:
    customRequestHeaders:
      Host: '{Host}'
      X-Forwarded-For: '{ClientIP}'
      X-Forwarded-Host: '{Host}'
      X-Forwarded-Port: '{ServerPort}'
      X-Forwarded-Proto: '{Protocol}'
      X-Real-IP: '{ClientIP}'
      http_x_forwarded_for: '{ClientIP}'
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: 'web, websecure'
    traefik.ingress.kubernetes.io/router.middlewares: >-
      default-http-to-https-redirect@kubernetescrd,prod-proxy-headers@kubernetescrd
...
spec:
  ingressClassName: traefik

What I hope to get

sourceIP from client

What I actually get

use a simple python script

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
def capture_headers():
    headers = dict(request.headers)  # 获取所有传入的 header
    print("Received headers:")
    for key, value in headers.items():
        print(f"{key}: {value}")
    return jsonify(headers), 200  # 将 header 以 JSON 格式返回到客户端

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

svclb-traefik DaemonSet pods ip (like: 10.42.1.29)

{"Accept":"*/*","Accept-Encoding":"gzip","Host":"","User-Agent":"curl/7.81.0","X-Forwarded-For":"{ClientIP}, 10.42.1.29","X-Forwarded-Host":"{Host}","X-Forwarded-Port":"{ServerPort}","X-Forwarded-Proto":"{Protocol}","X-Forwarded-Server":"traefik-7445d5d6-2cmnf","X-Real-Ip":"{ClientIP}"}

The modifications I made

  1. edit traefik svc yaml
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    meta.helm.sh/release-name: traefik
    meta.helm.sh/release-namespace: kube-system
  finalizers:
    - service.kubernetes.io/load-balancer-cleanup
  labels:
    app.kubernetes.io/instance: traefik-kube-system
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: traefik
    helm.sh/chart: traefik-27.0.201_up27.0.2
  name: traefik
  namespace: kube-system
  resourceVersion: '634622'
spec:
  allocateLoadBalancerNodePorts: true
  externalTrafficPolicy: Local # here
  internalTrafficPolicy: Cluster
  1. edit traefik forwardedHeaders.trustedIP
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: traefik
  namespace: kube-system
spec:
  chart: https://%{KUBERNETES_API}%/static/charts/traefik-27.0.201+up27.0.2.tgz
  set:
    global.systemDefaultRegistry: ""
  valuesContent: |-
    deployment:
      podAnnotations:
        prometheus.io/port: "8082"
        prometheus.io/scrape: "true"
    providers:
      kubernetesIngress:
        publishedService:
          enabled: true
    priorityClassName: "system-cluster-critical"
    # here
    additionalArguments:
      - "--entrypoints.web.forwardedHeaders.trustedIPs=0.0.0.0/0"
      - "--entrypoints.websecure.forwardedHeaders.trustedIPs=0.0.0.0/0"

Finally, what I want to say

I have used the same method in Azure before, and at that time Traefik could obtain the source IP normally. However, in Google Cloud, this does not work.
I hope all you traefik masters can help me!!! THX