Metriche repository
- Star
- (2871 star)
- Metriche merge PR
- (Metriche PR in attesa)
Descrizione
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:
- 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: /
- 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
- 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
- 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"
}
- the ALB IPs
dig test-envoy.xxxxx
test-envoy.xxx A 172.18.38.251
test-envoy.xxx A 172.18.39.85
- I expected
X-Real-Ip=100.64.0.53but 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