When requests pass through proxies, load balancers, or CDN nodes before reaching your ASM gateway, the gateway sees the last proxy's IP instead of the client's originating IP address. Configure the gateway to extract the originating address from the X-Forwarded-For (XFF) header so that access control policies, compliance audits, and anti-fraud systems can identify the real client.
ASM supports two extraction methods. Choose based on your network topology:
| Topology | Method | Configuration field | When to use |
|---|---|---|---|
| Fixed number of proxies | Trusted hop count | numTrustedProxies | All requests pass through the same proxy chain |
| Variable number of proxies | Trusted CIDR allowlist | xffTrustedCidrs | Different clients may traverse different proxy paths |
This feature requires ASM version 1.24.6.83 or later. Upgrade your ASM instance if needed.
How XFF works
X-Forwarded-For is an HTTP request header that records IP addresses as a request passes through proxy servers, load balancers, or Alibaba Cloud CDN nodes. Each hop appends the previous hop's IP to the header:
X-Forwarded-For: <originating client IP>, <first proxy IP>, <second proxy IP>, ...The leftmost address is the client's originating IP. The rightmost addresses belong to proxies closer to the gateway.
Extract client IP by trusted hop count
Use this method when requests always pass through a fixed number of proxies before reaching the gateway.
How it works
The gateway counts backward from the end of the XFF list by the number of trusted hops and treats the next address as the client IP.
Example: Three proxies sit between the client and the gateway. Set numTrustedProxies to 2 (number of proxies in the chain minus 1).
After the request passes through all three proxies, the XFF header contains:
X-Forwarded-For: 1.1.1.1, 2.2.2.2, 3.3.3.3The gateway skips the last 2 addresses (3.3.3.3, 2.2.2.2) and identifies 1.1.1.1 as the client's originating IP.
Configure the trusted hop count
This operation triggers a rolling restart of the gateway. Perform it during off-peak hours.
Open the ASM gateway resource for editing using the ASM kubeconfig:
kubectl -n istio-system edit istiogateway <ASM gateway name>Add the
numTrustedProxiesannotation to the gateway pod: Replace<number of proxies in the chain minus 1>with the actual value. For example, with 3 proxies, set this to2.spec: podAnnotations: proxy.istio.io/config: | gatewayTopology: numTrustedProxies: <number of proxies in the chain minus 1>Save and close the file. The configuration takes effect after the gateway pod restarts.
Verify the configuration
After the gateway pod restarts, send a test request with a synthetic XFF header and check the gateway access log:
# Send a request with a simulated XFF header
curl -H 'X-Forwarded-For: 56.5.6.7, 72.9.5.6, 98.1.2.3' http://<gateway-address>/<path>In the gateway access log, confirm that the extracted client IP matches the expected originating address (56.5.6.7 in this example).
Usage notes
The value of
numTrustedProxiesmust be less than the total number of IP addresses in the XFF header. If it equals or exceeds the count, the gateway falls back to using the rightmost address in the XFF list as the client IP.WarningSetting
numTrustedProxieshigher than the actual number of proxies allows an attacker to spoof a trusted client IP by injecting extra entries into the XFF header. Always set this value to match your actual proxy chain length.The XFF header recorded in the ASM gateway access log includes an additional address appended by the gateway itself. This appending happens after the
numTrustedProxiescalculation. For example, if Proxy3's IP is4.4.4.4, the access log shows: This does not affect the accuracy of the extracted client IP.X-Forwarded-For: 1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4
Extract client IP by trusted CIDR allowlist
Use this method when requests pass through a variable number of proxies, making a fixed hop count unreliable.
How it works
Instead of counting hops, the gateway walks the XFF list from right to left and skips any address that matches a trusted CIDR range. The first non-matching address is treated as the client IP.
Example: Client1 connects through Proxy1 and Proxy3, while Client2 connects through Proxy2, Proxy4, and Proxy3. The hop count differs between the two paths, so numTrustedProxies alone cannot extract the correct client IP.
Add the IPs of Proxy1 through Proxy4 to the trusted CIDR allowlist. The gateway skips these known proxy addresses and correctly identifies each client's originating IP.
Configure the trusted CIDR allowlist
This operation triggers a rolling restart of the gateway. Perform it during off-peak hours.
Open the ASM gateway resource for editing using the ASM kubeconfig:
kubectl -n istio-system edit istiogateway <ASM gateway name>Add the
xffTrustedCidrsannotation to the gateway pod with all known proxy IPs in CIDR notation: Replace the CIDR values with your actual proxy IP addresses. Individual IPs require the/32suffix.spec: podAnnotations: proxy.istio.io/config: | gatewayTopology: xffTrustedCidrs: - 2.2.2.2/32 - 3.3.3.3/32 - 4.4.4.4/32 - 5.5.5.5/32Save and close the file. The configuration takes effect after the gateway pod restarts.
Verify the configuration
After the gateway pod restarts, send test requests with different XFF headers that simulate each client path and check the gateway access log to confirm the correct client IP is extracted.
# Simulate Client1's path (through Proxy1 and Proxy3)
curl -H 'X-Forwarded-For: 1.1.1.1, 2.2.2.2, 4.4.4.4' http://<gateway-address>/<path>
# Simulate Client2's path (through Proxy2, Proxy4, and Proxy3)
curl -H 'X-Forwarded-For: 6.6.6.6, 3.3.3.3, 5.5.5.5, 4.4.4.4' http://<gateway-address>/<path>In the gateway access log, confirm that the extracted client IP is 1.1.1.1 for the first request and 6.6.6.6 for the second request.
Usage notes
Only CIDR notation is accepted. Specify individual IPs with a
/32suffix (for example,2.2.2.2/32).Add all known proxy and load balancer IPs to the allowlist. Missing entries cause the gateway to misidentify a proxy IP as the client IP.
Configuration reference
| Field | Description | Format | Scope |
|---|---|---|---|
numTrustedProxies | Number of trusted proxy hops to skip when extracting the client IP from the XFF header. Set to the total number of proxies in the chain minus 1. | Integer | Per-gateway (pod annotation) |
xffTrustedCidrs | List of CIDR ranges for known proxy IPs. The gateway skips matching addresses when walking the XFF list from right to left. | CIDR list (e.g., 2.2.2.2/32) | Per-gateway (pod annotation) |
proxy.istio.io/config | Istio proxy configuration annotation key under spec.podAnnotations. | YAML string | Per-gateway (pod annotation) |
gatewayTopology | Configuration block within proxy.istio.io/config that contains XFF-related settings. | YAML object | Per-gateway (pod annotation) |
Related topics
Upgrade your ASM instance to the latest version for additional features and fixes.