Reverse Proxies#

The Curity Identity Server can be deployed behind a reverse proxy. When it is, the address of the TCP connection is the proxy’s, not the client’s, so the client’s own address comes from the X-Forwarded-For request header.

The client address matters well beyond the logs. It may be used (when enabled) by DoS protection , by rate limits such as the number of emails allowed per client address, and by CIDR authenticator filters, among others. Establishing it incorrectly therefore affects security decisions, not only diagnostics.

Configuring the proxies#

List every proxy that may sit in the request path under white-listed proxies , as addresses, CIDR ranges or host names.

Every hop must be listed, not just the one nearest the client. The client is taken to be the last address in X-Forwarded-For that is not one of the listed proxies, so an unlisted intermediate proxy is reported as the client and every request appears to come from that same address.

On a dual-stack host, list every address a proxy may connect from. An IPv4 entry does not cover the corresponding IPv6 address: a proxy on the same host commonly connects over IPv6 loopback, so 127.0.0.1 and ::1 are both needed. Getting this wrong is silent — the header is simply ignored, and every client is reported as the proxy.

Keep the list as narrow as the topology allows. Anything listed here is trusted completely: it can report any client address it likes and the server will believe it. Prefer exact addresses to wide ranges wherever the addresses are stable.

Supported proxy setups#

Every proxy in the path must pass the client’s address on in X-Forwarded-For, appending it to the end of the chain. That is the only header read, so a proxy that conveys the address by some other means — the RFC 7239 Forwarded header, a vendor header such as X-Real-IP, or the PROXY protocol that L4 and transparent proxies use — has to be reconfigured to send X-Forwarded-For as well.

The chain may arrive as one header line or as several. Several lines are read as a single chain, in the order they arrived, so these two requests are equivalent:

X-Forwarded-For: 203.0.113.7, 10.0.1.1
X-Forwarded-For: 203.0.113.7
X-Forwarded-For: 10.0.1.1

Every proxy in the path must follow the same strategy: either they all append to a single header line, or they all add a line of their own. A mixture is what breaks. A proxy that merges its value into an earlier occurrence of the header and forwards the later ones unchanged leaves whatever the client sent at the end of the chain — and the end of the chain is where the client’s address is looked for.

Configuring the edge proxy to replace any incoming X-Forwarded-For with a single fresh header holding only the client’s address avoids the question entirely, and is the safest setup for that reason: nothing a client sends can survive it. Such a proxy must still be listed as a white-listed proxy for its header to be used at all.

Troubleshooting#

If clients are reported with the wrong address, add a logger for se.curity.identityserver.coreutils.http.ClientIpResolver at TRACE level in ${IDSVR_HOME}/etc/log4j2.xml, as described in Logging . Every request then logs the address that was established, the address of the immediate caller and the header entries it was derived from. This shows whether the header arrived, whether the caller was recognised as a proxy, and which entry was chosen.

These entries contain client IP addresses in full and are not masked. This TRACE log is intended for short diagnostic sessions rather than continuous operation.

Was this helpful?