How to Verify a Reverse Proxy Is Sending the Correct Client IP

Eva Wong is the Technical Writer and resident tinkerer at ZimaSpace. A lifelong geek with a passion for homelabs and open-source software, she specializes in translating complex technical concepts into accessible, hands-on guides. Eva believes that self-hosting should be fun, not intimidating. Through her tutorials, she empowers the community to demystify hardware setups, from building their first NAS to mastering Docker containers.

Verify client IP forwarding by comparing a known external source with every proxy header and the backendโ€™s final parsed address.

A reverse proxy terminates the client connection, so the backend normally sees the proxyโ€™s socket address unless the proxy passes trusted request metadata. The test must distinguish the direct peer address from Forwarded, X-Forwarded-For, and X-Real-IP, document every trusted hop, and prove that an internet client cannot spoof the value used for logs, rate limits, or access control.

Create a Known Client-IP Test From Outside the Home

Use a device on mobile data or another external network and record its public IPv4 or IPv6 address immediately before the request. Send a unique path, query value, or timestamp through the public reverse proxy.

MDN describes X-Forwarded-For as a de facto header for preserving the originating client address across proxy connections.

Collect the edge proxy log, any intermediate proxy log, and the backend application log for that one request. Without a known source and correlated timestamp, multiple concurrent users can make the header chain ambiguous.

Record the Socket Peer and Every Forwarded Header

At the backend, log the direct TCP peer address separately from Forwarded, X-Forwarded-For, X-Real-IP, and any CDN-specific client header. Do not overwrite the raw values during the first test.

A practical analysis of โ€œrealโ€ client IP handling warns that accuracy depends on how the proxy sets or appends headers and whether earlier values can be spoofed. The entire proxy trust model must match the actual network architecture.

The backend socket peer should equal the immediate trusted proxy, while the selected client address should equal the external test device. If the backend logs only the proxy address, header creation or parsing is missing.

Verify How Each Proxy Adds or Replaces the Header

Inspect every hop from CDN or tunnel to edge proxy, internal proxy, and application. Record whether each hop appends to an existing list, replaces untrusted input, or passes the header unchanged.

Sling Academy explains that NGINX can set X-Real-IP from the immediate connection and append a chain with proxy_add_x_forwarded_for.

Configure the first trusted edge to remove or replace client-supplied forwarding headers, then append addresses at controlled internal hops. Avoid blindly accepting the leftmost or rightmost value without defining how many proxies are trusted.

Configure the Backend to Trust Only Known Proxy Addresses

Set the application or web serverโ€™s trusted-proxy list to the exact reverse-proxy addresses or controlled subnets. Confirm that direct connections from ordinary LAN or internet clients are not treated as trusted header sources.

Ip2Geoโ€™s explanation notes that the application connection originates from the load balancer or reverse proxy and that parsing the original IP safely requires a trusted-hop rule rather than accepting arbitrary input.

If the proxy address changes because of containers, overlay networks, or a CDN, document the supported range and update it deliberately. Do not trust all private addresses merely because the proxy currently uses one.

Run a Spoofed-Header Test

From the external test device, send a forged X-Forwarded-For or Forwarded value while connecting through the real proxy. Compare the raw incoming header, normalized proxy header, and backend-selected client address.

The correct result is that the trusted edge replaces or safely appends to untrusted input and the backend selects the address based on the documented trusted-hop count. A forged address must not become the value used for authentication or allowlisting.

Repeat a direct-to-backend test from a LAN segment if that port is reachable. The backend should ignore forwarded headers from an untrusted direct client and record the actual socket peer.

Validate IPv4, IPv6, and Multi-Proxy Paths

Repeat the test through IPv4 and IPv6, through the normal public hostname, and through any CDN, tunnel, or secondary proxy used in production. Confirm logs preserve valid address formats and do not truncate the chain.

The ZimaSpace guide to reverse-proxy request identity provides the surrounding context for why correct forwarded values matter beyond logging.

The proxy is verified only when the known source matches the parsed client IP, trusted proxies remain visible in the raw chain, spoof attempts fail, and security controls use the normalized value consistently. Recheck after adding a CDN, tunnel, or another proxy hop.

Support & Tips

More to Read

Get More Builds Like This

Stay in the Loop

Get updates from Zima - new products, exclusive deals, and real builds from the community.

Stay in the Loop preferences

We respect your inbox. Unsubscribe anytime.