I'm working with Spring (Spring Web) and trying to determine the full chain of client IP addresses from a request. The code I'm using is based on Spring's ForwardedHeaderUtils. Currently, it only returns the first IP address from the X-Forwarded-For header.
Here's the relevant snippet from ForwardedHeaderUtils:
String forHeader = headers.getFirst("X-Forwarded-For");
if (StringUtils.hasText(forHeader)) {
// Currently extracting only the first IP
String host = StringUtils.tokenizeToStringArray(forHeader, ",")[0];
return InetSocketAddress.createUnresolved(host, port);
}
When I test this, the extracted IP is something like 192.168.1.*, which is the internal proxy or load balancer, not the actual client. I know the X-Forwarded-For header might contain multiple IPs, for example:
X-Forwarded-For: 192.168.1.5,203.0.113.5,203.0.113.10
My goal is to retrieve the full list of IP addresses and inspect them, not just the first one.
However, I’m wondering if there's a standard Spring utility or a best practice approach for doing this. Is the recommended method simply to parse the header manually if I need the full chain of IPs?
How can I properly retrieve all IP addresses from the X-Forwarded-For header rather than just the first one?
Is there a built-in Spring mechanism or a known approach for accessing the entire list of forwarded IP addresses?
I'm behind a load balancer and I trust that the X-Forwarded-For header is set correctly. I just want to analyze the chain of addresses. I’m using Spring Boot 3.x and Spring Framework 6.x.
Spring Boot’s behavior for handling forwarded headers such as X-Forwarded-For
depends on both the deployment environment and the server.forward-headers-strategy
setting:
When running on platforms like Cloud Foundry, Heroku, or Kubernetes, server.forward-headers-strategy
defaults to NATIVE. In this mode, the underlying web server (Tomcat, Jetty, etc.) manages the forwarded headers.
When running outside these environments, Spring Boot won’t manipulate these headers by default. It’s often recommended to configure your desired strategy explicitly to ensure predictable behavior.
NATIVE Mode (Handled by the Web Server):
If you rely on the web server to process forwarded headers, you can specify trusted proxies by setting a regular expression in the server.tomcat.remoteip.trusted-proxies
property. This approach allows the native server handling to consider multiple IP addresses from X-Forwarded-For, but the effective client IP might still be a single extracted value rather than the entire chain. If you want to dive deeper into the Tomcat handling here is the method manipulates the header.
FRAMEWORK Mode (Handled by Spring):
When you set server.forward-headers-strategy=FRAMEWORK
, Spring Boot injects a ForwardedHeaderFilter
into the application context. By default, this filter also focuses primarily on the first IP address. If you need all IP addresses, you can extend ForwardedHeaderFilter to implement custom logic and inject the custom filter to application context. In the custom filter manually retrieve the X-Forwarded-For header and discard unnecessary IPs in the list.
If you trust your load balancer or proxy and simply need to inspect all IPs in the forwarding chain, manual parsing provides the greatest flexibility.
Consider explicitly setting server.forward-headers-strategy
(e.g., FRAMEWORK or NATIVE) to avoid any unintended behavior and to make your application’s behavior more transparent.