Information Security 7 min read

Troubleshooting X-Forwarded-For Null Issue with Tomcat Behind Nginx Over HTTPS

When switching from HTTP to HTTPS, Tomcat fails to retrieve the client IP via X-Forwarded-For because of RemoteIpValve configuration and Nginx proxy settings, leading to null values and requiring adjustments in server.xml and Nginx headers to correctly propagate the original client IP.

58 Tech
58 Tech
58 Tech
Troubleshooting X-Forwarded-For Null Issue with Tomcat Behind Nginx Over HTTPS

Problem Description

58 sites accessed via HTTP use Tomcat's X-Forwarded-For header to obtain the real client IP. After switching to HTTPS, Tomcat cannot retrieve the client IP; X-Forwarded-For becomes null.

Investigation

The client request passes through a unified Nginx proxy layer that terminates SSL; Nginx forwards the request to Tomcat using HTTP. Both HTTP and HTTPS Nginx configurations pass X-Forwarded-For, but some back‑ends receive null.

It was discovered that the null value is caused by an additional configuration in Tomcat's server.xml :

<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>

This Valve forwards the original protocol (HTTPS) via X-Forwarded-Proto so that Tomcat knows the request was originally HTTPS.

To support this, Nginx was configured with:

proxy_set_header HTTPS-Tag "HTTPS"; # mark HTTPS
proxy_set_header X-Forwarded-Proto $scheme; # pass protocol

During the 58‑site HTTPS migration, the default template added this Valve to every server.xml, causing the X‑Forwarded‑For value to become null for some sites.

Root Cause

RemoteIpValve removes trusted/internal IPs from X‑Forwarded‑For and assigns the remaining original client IP to Tomcat's remoteaddr variable. Consequently, the X‑Forwarded‑For header appears null because the IP has been moved to remoteaddr .

Solution

Customize server.xml per service and include the configuration only in full‑package deployments to avoid unwanted default injection.

Keep the standard Valve configuration in the template when needed:

<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>

3. Enhance Nginx to pass both X-Forwarded-For and X-Real-IP so back‑ends can choose the appropriate header:

#### Get User IP ####
set $remote_address $http_x_forwarded_for;
if ($remote_address !~ "[0-9]") { set $remote_address $remote_addr; }
location / {
proxy_pass http://$host_pass;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_address;
proxy_set_header X-Real-IP $remote_address;
proxy_set_header HTTPS-Tag "HTTP";
proxy_set_header X-Forwarded-Proto $scheme;
}

Further Considerations

Can X‑Forwarded‑For reliably provide the true client IP? While it works for analytics and region detection, the header can be forged, making it unsuitable for security‑critical risk control. In such cases, use the actual IP of the Nginx proxy (or a trusted internal IP) for enforcement.

Typical backend needs for client IP include user statistics, geographic determination, and risk control. For risk control, rely on the real connection IP rather than a potentially spoofed X‑Forwarded‑For value.

Nginx Header Configuration Summary

• proxy_set_header X-Forwarded-For $remote_addr; – passes the client IP directly.

• proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; – appends the proxy IP to the existing header.

• proxy_set_header X-Real-IP $proxy_add_x_forwarded_for; – provides an additional reliable IP header.

nginxTomcatHTTPSbackend configurationIP SpoofingRemoteIpValveX-Forwarded-For
58 Tech
Written by

58 Tech

Official tech channel of 58, a platform for tech innovation, sharing, and communication.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.