Skip to content

feat: add XFFLeftmost option to ExtractIPFromXFFHeader (#2803) - #3172

Open
MrBeldum wants to merge 1 commit into
labstack:masterfrom
MrBeldum:fix/xff-trust-leftmost-2803
Open

MrBeldum wants to merge 1 commit into
labstack:masterfrom
MrBeldum:fix/xff-trust-leftmost-2803

Conversation

@MrBeldum

Copy link
Copy Markdown

Summary

Fixes #2803. ExtractIPFromXFFHeader scans the X-Forwarded-For chain from the right, returning the first untrusted IP. Behind Azure Front Door that stops at the proxy's public egress IP instead of reaching the client: with XFF: client, <Front Door egress> and a private RemoteAddr, the extractor returns the egress IP.

This PR adds a new TrustOption, XFFLeftmost(), that opts into scanning from the left, returning the first untrusted IP from that direction. All existing trust options keep applying (a trusted leftmost entry is skipped), and default behavior is unchanged.

e.IPExtractor = echo.ExtractIPFromXFFHeader(
    echo.XFFLeftmost(),
)

Safety caveat

Only use XFFLeftmost() when the outermost proxy strips incoming X-Forwarded-For headers and is the sole writer of the chain. Otherwise the leftmost entry is client-controlled and can be spoofed (a client can prepend arbitrary addresses; Front Door appends the real client IP to the end). This is documented on the option and in the IP-address guide in ip.go. If the edge does not strip incoming headers, trust the proxy's address ranges with TrustIPRange instead.

Tests

  • Reproduced azure front door x-forwaded-for #2803 first: on the reporter's chain (XFF: 203.0.113.195, 203.0.113.199, RemoteAddr: 10.0.0.5) the default extractor returns 203.0.113.199 (the proxy); with XFFLeftmost() it returns 203.0.113.195 (the client).
  • New TestExtractIPFromXFFHeaderLeftmost: 8 cases covering the reporter scenario, trusted entries skipped on the left, all-trusted fallback, invalid entry falling back to RemoteAddr, no-XFF fallback, multiple header values, bracketed IPv6, and composition with TrustIPRange.
  • go test ./...: root package passes except 4 pre-existing environment failures (TestEchoStaticRedirectIndex, TestStartConfig_*) that fail identically on the clean tree; middleware fully passes. gofmt and go vet clean.

Prepared with AI assistance.

ExtractIPFromXFFHeader scans the X-Forwarded-For chain from the right,
returning the first untrusted IP. That stops at the public egress IP of
edge proxies such as Azure Front Door instead of reaching the client.
XFFLeftmost() opts into scanning from the left, returning the first
untrusted IP from that direction, while all existing trust options keep
applying.

Only use it when the outermost proxy strips incoming X-Forwarded-For
headers and is the sole writer of the chain; otherwise the leftmost
entry is client-controlled and can be spoofed. Default behavior is
unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

azure front door x-forwaded-for

1 participant