Nginx's real_ip module allows you to set the $remote_addr variable based on values sent in particular header fields. It has a special understanding of the X-Forwarded-For header, and is able to use the right-most untrusted value in the header as the connecting IP address.

I'd like to use the real_ip module to set $remote_addr to the connecting IP address. The problem I have is that I know how many hops back from the end of the X-Forwarded-For to look at, but not the IP address of the proxies in between. As I understand it, that means that I can't use set_real_ip_from to specify the proxy's IP address.

What I would like to be able to do is to configure nginx to choose the second to last address in the list as the $remote_addr. It seems as if the real_ip module only works if you have infrastructure where you know the IP addresses of your proxies.

Is there a way to do this with the real_ip module? I've worked up a regex based solution, but I would prefer to use the real_ip module if it is possible.

I don't think this is a dupe of nginx real_ip_header and X-Forwarded-For seems wrong or similar questions. To restate the issue:

  • I know how many hops from the end the connecting IP address will be.
  • I don't know the trusted IP addresses for intermediary proxies between the connecting IP and my server, so I can't use set_real_ip_from.

More details on the specifics:

I am running nginx inside Google Cloud, behind the Google Cloud HTTP Load Balancer. Google Cloud uses the X-Forwarded-For header to indicate the entry point to Google Cloud's network. I know that the second to last value in the X-Forwarded-For list is the one that I want, but I don't know what the IP address of the last value (the proxy) will be. Even if I could enumerate all of Google Cloud's address space for proxies (it's not specified that GCLB only operates inside GCP's address space), that would open it up for any other users that can get a server inside that address space.

  • One problem is this: You cannot trust any of the entries in X-Forwarded-For except the ones you control and manage. These headers can be forged. From your question I don't understand what problem you are trying to solve. I just see a technique to process the X-Forwarded-For headers to get an IP address and not the end result that you are seeking. Jan 8 '19 at 0:06
  • I'm trying to use the Nginx real_ip module to set $remote_addr from an X-Forwarded-For header. I can trust the last two entries in the header, but don't know what the IP of the last entry in the header (the proxy) will be. If I don't know the proxy's IP address, I can't use set_real_ip_from. Jan 8 '19 at 22:31
  • This question seems to be already addressed on the following post: serverfault.com/questions/314574/… Jan 18 '19 at 9:33
  • @JoseAntonio I don't think so? Whether real_ip_recursive is on or off, both options require setting a trusted IP address for them to work correctly. Jan 20 '19 at 0:17

This can't be done with the ngx_http_realip_module itself, given that as specified in real_ip_recursive's description, only the last address in the header field (ie. your GFE's, when set to off) or the last untrusted address (ie. the client's address, when set to on) will be matched to replace $remote_addr, so even if you got the previous proxy's address from $http_x_forwarded_for with string manipulation and set $set_real_ip_from to it, the module wouldn't change $remote_addr.

Therefore, it looks like you will have to resort to manually redefining $remote_addr yourself with a regular expression as you mentioned, or use another module.

With that said, it might be worth noting that your Load Balancer's GFE address should always match the or CIDRs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.