Real client IP, path base and Host through a reverse proxy
Forward X-Forwarded-For/Proto/Prefix and Host correctly, trust only the proxy, and stop redirect loops and wrong absolute URLs.
- Build
- 26100.33650
- Edition
- Standard / Datacenter
- Architecture
- x64
- Support
- Documentation (E1)
- Evidence
- E1Official documentation
- Verified
- 2026-10-29
- Page type
- Task
The short answer
Section titled “The short answer”A reverse proxy must tell the app:
- who the client is:
X-Forwarded-For(or RFC 7239Forwarded); - which scheme:
X-Forwarded-Proto; - which host: preserve
Host; - which path prefix:
X-Forwarded-Prefixwhen the app is mounted under/app.
And the app must trust these headers only from the proxy.
location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host;}For a path-mounted app:
location /app/ { proxy_pass http://127.0.0.1:3000/; proxy_set_header X-Forwarded-Prefix /app;}The trailing slash on proxy_pass strips /app/; the prefix header tells the app how to generate links.
IIS ARR
Section titled “IIS ARR”- Preserve
Hostin the farm/proxy settings. - Forward
X-Forwarded-For/X-Forwarded-Proto. - If the app is under a path, set
X-Forwarded-Prefixvia URL Rewrite server variables. - Do not rewrite
Hosttolocalhostunless the app is configured for it.
App trust
Section titled “App trust”Express:
app.set('trust proxy', 1);ASP.NET Core:
app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto});Configure known proxies/networks; the default often trusts only loopback. Do not trust all proxies on a public host.
Redirect loops
Section titled “Redirect loops”Symptom: browser bounces between http and https, or redirects to localhost.
Causes:
- proxy sends
X-Forwarded-Proto: httpafter TLS termination; - app ignores the header and redirects to HTTPS;
- proxy rewrites
Hostto an internal name; - canonical-host rule catches the health check.
Fix the header/trust boundary, not by disabling HTTPS redirects globally.
Verify
Section titled “Verify”curl.exe -I -H "X-Forwarded-Proto: https" https://lab.example/curl.exe -H "Host: app.example" http://127.0.0.1:3000/whoamiThe app should report the public scheme/host and the real client IP, and redirects should use the public name.
Lab boundary
Section titled “Lab boundary”E1. The lab ran Nginx/IIS without a multi-hop proxy; the headers are the configuration to validate with a real upstream on Server 2025.