Search This Blog

Tuesday, October 16, 2012

reverse proxy - nginx real_ip_header and X-Forwarded-For seems wrong - Server Fault

reverse proxy - nginx real_ip_header and X-Forwarded-For seems wrong - Server Fault:


I believe the key to solving X-Forwarded-For woes when multiple IPs are chained is the recently introduced configuration option, real_ip_recursive (added in nginx 1.2.1 and 1.3.0). From the nginx realip docs:
If recursive search is enabled, an original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field.
nginx was grabbing the last IP address in the chain by default because that was the only one that was assumed to be trusted. But with the new real_ip_recursive enabled and with multipleset_real_ip_from options, you can define multiple trusted proxies and it will fetch the last non-trusted IP.
For example, with this config:
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
And an X-Forwarded-For header resulting in:
X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1
nginx will now pick out 123.123.123.123 as the client's IP address.
As for why nginx doesn't just pick the left-most IP address and requires you to explicitly define trusted proxies, it's to prevent easy IP spoofing.
Let's say a client's real IP address is 123.123.123.123. Let's also say the client is up to no good, and they're trying to spoof their IP address to be 11.11.11.11. They send a request to the server with this header already in place:
X-Forwarded-For: 11.11.11.11
Since reverse proxies simply add IPs to this X-Forwarded-For chain, let's say it ends up looking like this when nginx gets to it:
X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1
If you simply grabbed the left-most address, that would allow the client to easily spoof their IP address. But with the above example nginx config, nginx will only trust the last two addresses as proxies. This means nginx will correctly pick 123.123.123.123 as the IP address, despite that spoofed IP actually being the left-most.

No comments:

Post a Comment