envoyproxy/gateway

ClientTrafficPolicy how to set x-real-ip header

Open

#7,150 opened on 2025年10月7日

GitHub で見る
 (24 comments) (2 reactions) (0 assignees)Go (802 forks)auto 404
help wantedkind/feature

Repository metrics

Stars
 (2,871 stars)
PR merge metrics
 (PR metrics pending)

説明

Description: HI, I'm trying to migrate from ingress-nginx to Envoy Gateway. I'm using the x-real-ip header for the real client IP address and want to inject it for all requests.

I'm attempting to configure the header extraction for X-Forwarded-For (XFF) but am encountering unexpected behavior. When I use earlyRequestHeaders in ClientTrafficPolicy, it does not configure the header X-Real-Ip as I expected.

I am trying to configure the use of ALB (L7) while preserving the correct client IP.

Request > AWS ALB (L7) > Envoy Gateway > Backend

Envoy logs

{
  ":authority": "test-envoy.xxxx",
  "bytes_received": 0,
  "bytes_sent": 1454,
  "connection_termination_details": null,
  "downstream_local_address": "172.18.38.111:10080",
  "downstream_remote_address": "100.64.0.53:0",
  "duration": 1,
  "method": "GET",
  "protocol": "HTTP/1.1",
  "requested_server_name": null,
  "response_code": 200,
  "response_code_details": "via_upstream",
  "response_flags": "-",
  "route_name": "httproute/ingress-gateways/backend/rule/0/match/0/test-envoy_xxx",
  "start_time": "2025-10-07T11:17:14.881Z",
  "upstream_cluster": "httproute/ingress-gateways/backend/rule/0",
  "upstream_host": "172.18.39.75:3000",
  "upstream_local_address": "172.18.38.111:44318",
  "upstream_transport_failure_reason": null,
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
  "x-envoy-origin-path": "/",
  "x-envoy-upstream-service-time": null,
  "x-forwarded-for": "100.64.0.53,172.18.39.85",
  "x-request-id": "b004eb7c-252d-4ec7-b285-077d67e0dce7"
}

App response

{
  "path": "/",
  "host": "test-envoy.xxxx",
  "method": "GET",
  "proto": "HTTP/1.1",
  "headers": {
    "Accept": [
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
    ],
    "Accept-Encoding": ["gzip, deflate, br, zstd"],
    "Accept-Language": ["en-US,en;q=0.9,uk;q=0.8,ru;q=0.7"],
    "Cache-Control": ["no-cache"],
    "Dnt": ["1"],
    "Pragma": ["no-cache"],
    "Priority": ["u=0, i"],
    "Sec-Ch-Ua": ["\"Chromium\";v=\"141\", \"Not?A_Brand\";v=\"8\""],
    "Sec-Ch-Ua-Mobile": ["?0"],
    "Sec-Ch-Ua-Platform": ["\"macOS\""],
    "Sec-Fetch-Dest": ["document"],
    "Sec-Fetch-Mode": ["navigate"],
    "Sec-Fetch-Site": ["none"],
    "Sec-Fetch-User": ["?1"],
    "Upgrade-Insecure-Requests": ["1"],
    "User-Agent": [
      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
    ],
    "X-Amzn-Trace-Id": ["Root=1-68e4f6ba-43e432cc3d702b141cfb5442"],
    "X-Forwarded-For": ["100.64.0.53,172.18.39.85"],
    "X-Forwarded-Port": ["443"],
    "X-Forwarded-Proto": ["https"],
    "X-Real-Ip": ["172.18.39.85"],
    "X-Request-Id": ["b004eb7c-252d-4ec7-b285-077d67e0dce7"]
  },
  "namespace": "ingress-gateways",
  "ingress": "",
  "service": "",
  "pod": "backend-869c8646c5-8f9rf"
}

The header X-Real-Ip is not 100.64.0.53 like in logs

Repro steps:

  1. deploy the app
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend
  namespace: ingress-gateways
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: ingress-gateways
  labels:
    app: backend
    service: backend
spec:
  ports:
    - name: http
      port: 3000
      targetPort: 3000
  selector:
    app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: ingress-gateways
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
      version: v1
  template:
    metadata:
      labels:
        app: backend
        version: v1
    spec:
      serviceAccountName: backend
      containers:
        - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
          imagePullPolicy: IfNotPresent
          name: backend
          ports:
            - containerPort: 3000
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
  namespace: ingress-gateways
spec:
  parentRefs:
    - name: eg
      namespace: ingress-gateways
  hostnames:
    - "test-envoy.xxxx"
  rules:
    - backendRefs:
        - group: ""
          kind: Service
          name: backend
          port: 3000
          weight: 1
      matches:
        - path:
            type: PathPrefix
            value: /

  1. Deploy the GW
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
  annotations:
    external-dns.alpha.kubernetes.io/target: xxxxx.us-east-1.elb.amazonaws.com.
spec:
  gatewayClassName: eg
  infrastructure:
    parametersRef:
      group: gateway.envoyproxy.io
      kind: EnvoyProxy
      name: custom-proxy-config
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: All
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: custom-proxy-config
  namespace: ingress-gateways
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyDeployment:
        replicas: 2
      envoyService:
        name: envoy-ingress-gateways-eg
        type: ClusterIP
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
  name: http-client-ip-detection
  namespace: ingress-gateways
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: eg
  headers:
    requestID: PreserveOrGenerate
    earlyRequestHeaders:
      set:
        - name: x-real-ip
          value: "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%"
  clientIPDetection:
    xForwardedFor:
      numTrustedHops: 1
  1. deploy ALB
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol: HTTP
    alb.ingress.kubernetes.io/group.name: pvt-gateway-alb
    alb.ingress.kubernetes.io/group.order: "80"
    alb.ingress.kubernetes.io/healthcheck-path: /ready
    alb.ingress.kubernetes.io/healthcheck-port: "19003"
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/target-type: ip
  name: internal-envoy-gateway-alb
  namespace: ingress-gateways
spec:
  ingressClassName: alb
  rules:
    - host: test-envoy.xxxxx
      http:
        paths:
          - backend:
              service:
                name: envoy-ingress-gateways-eg
                port:
                  number: 80
            path: /
            pathType: Prefix
  1. Send request to ALB
curl https://test-envoy.xxx/
{
  "path": "/",
  "host": "test-envoy.xxxx",
  "method": "GET",
  "proto": "HTTP/1.1",
  "headers": {
    "Accept": [
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
    ],
    "Accept-Encoding": ["gzip, deflate, br, zstd"],
    "Accept-Language": ["en-US,en;q=0.9,uk;q=0.8,ru;q=0.7"],
    "Cache-Control": ["no-cache"],
    "Dnt": ["1"],
    "Pragma": ["no-cache"],
    "Priority": ["u=0, i"],
    "Sec-Ch-Ua": ["\"Chromium\";v=\"141\", \"Not?A_Brand\";v=\"8\""],
    "Sec-Ch-Ua-Mobile": ["?0"],
    "Sec-Ch-Ua-Platform": ["\"macOS\""],
    "Sec-Fetch-Dest": ["document"],
    "Sec-Fetch-Mode": ["navigate"],
    "Sec-Fetch-Site": ["none"],
    "Sec-Fetch-User": ["?1"],
    "Upgrade-Insecure-Requests": ["1"],
    "User-Agent": [
      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
    ],
    "X-Amzn-Trace-Id": ["Root=1-68e4f6ba-43e432cc3d702b141cfb5442"],
    "X-Forwarded-For": ["100.64.0.53,172.18.39.85"],
    "X-Forwarded-Port": ["443"],
    "X-Forwarded-Proto": ["https"],
    "X-Real-Ip": ["172.18.39.85"],
    "X-Request-Id": ["b004eb7c-252d-4ec7-b285-077d67e0dce7"]
  },
  "namespace": "ingress-gateways",
  "ingress": "",
  "service": "",
  "pod": "backend-869c8646c5-8f9rf"
}
  1. the ALB IPs
dig test-envoy.xxxxx
test-envoy.xxx A	172.18.38.251
test-envoy.xxx A	172.18.39.85

  1. I expected X-Real-Ip=100.64.0.53 but it's "X-Real-Ip": "172.18.39.85" the LB ip

Environment:

docker.io/envoyproxy/gateway:v1.5.1
docker.io/envoyproxy/envoy:distroless-v1.35.3

コントリビューターガイド