1

I use nginx as a reverse proxy in front of our application web server (gunicorn; it's a Django app). Majority of the users hitting this web application are actually routed through a forward proxy.

Since requests pass through the forward proxy's servers, the IP address in these cases is always from proxy servers instead of from the original requestor. I want to rectify this situation.

All requests originating from the forward proxy contain a header via:proxy. In such requests, the original requestor IP is sent in a separate HTTP header field called X-IORG-FBS-UIP (and also X-FORWARDED-FOR).

My question is, how can I configure nginx such that it detects whether the request has via:proxy header, and if so, logs the original requestor IP from the X-IORG-FBS-UIP header? An illustrative example would be great; thanks in advance! My nginx is v 1.4.6


Note that I do not have the IP ranges used by the forward proxy. If I did, one way to solve this problem would been setting up etc/nginx/conf.d/proxies_acl.conf with:

set_real_ip_from 1.2.3.0/22;
set_real_ip_from 23.22.20.0/22;
real_ip_header X-IORG-FBS-UIP;

2 Answers 2

3

Try this. Interested to hear if it works. If you have any clients that aren't translated it would break that.

set_real_ip_from 0.0.0.0/0;
real_ip_header X-IORG-FBS-UIP;

Your set_real_ip_from and real_ip_header statements above are the standard way to do this. The only difference between your situation and what most people have is you don't know the IP address of the proxies. 0.0.0.0/0 means "every IP address", so the statements above say "for every request, get the client IP for the logs from the X-IORG-FBS-UIP header". My guess is if that header doesn't exist it will use the actual IP.

In most cases you can get the IP addresses of the proxies. AWS, CloudFlare, etc. Why don't you know the IPs of your proxies?

I also note you asked an almost identical question a couple of months ago, and accepted the answer. If someone doesn't answer your question, don't mark it as the answer.

Requested Alternate method - DOES NOT WORK

You asked for an alternate method based on the presence of the via:proxy header. I don't believe this is possible. I wrote this

if ($http_X_via:proxy) {
  set_real_ip_from $remote_addr;
  real_ip_header X-IORG-FBS-UIP;
}

But it fails. Nginx says set_real_ip_from can't go inside an if block. This means you have to know your IPs in advance, or use my other solution above.

7
  • Hmm, care to elaborate a bit? I guess I'm new to this; thus not seeing what this would do and how to test it. Apr 22, 2017 at 0:51
  • Answer edited. Let me know if you have more questions.
    – Tim
    Apr 22, 2017 at 1:18
  • The identical question's answer assumed I'll know the IP address ranges from the proxy. The forward proxy doesn't reveal their ranges, but their support has suggested I use the via:proxy header to do this. Should I just press them that it can't be done unless we know their IP ranges? Apr 22, 2017 at 13:21
  • And actually, why is it difficult to use the existence of the via:proxy header in the first place to achieve the desired affect? That too is a question. Apr 22, 2017 at 16:27
  • 1
    I don't think alternate method is possible. See edited answer.
    – Tim
    Apr 22, 2017 at 20:41
0

There's a good reason for specifying the proxy's IP address. Anyone can send proxy headers to your server, with "real ip" set to some arbitrary IP address, opening potential security holes if you rely on the address passed in these headers. That's why the real_ip module is configured to have you specify trusted forward proxies.

If your goal is simply to have nginx log the supposed real ip, you don't need to change the requestor's IP. You only need to log what's in headers X-IORG-FBS-UIP and X-FORWARDED-FOR. As described here, you can configure the nginx logger to capture X-FORWARDED-FOR like so:

add the following line in your general nginx.conf in the http {} section.

log_format main '$http_x_forwarded_for - $remote_user [$time_local] '
  '"$request" $status $body_bytes_sent "$http_referer" '
  '"$http_user_agent"' ;

I think adding a second logger directive for X-IORG-FBS-UIP will allow you to handle both. More on configuring the nginx logger here.

5
  • Currently, I'm using $remote_addr in the log_format directive in my nginx.conf. Would replacing that with $http_x_forwarded_for work for all requests, whether they originate from the forward proxy or not? The ma.ttias.be link you've shared is for a situation where all your traffic is behing a proxy (e.g. a caching engine like Varnish). What happens to those requests that weren't being a proxy? Apr 22, 2017 at 16:01
  • That depends on what you mean by "works". I'd need a more complete description of your logging requirements to answer that. Looks like you've settled on a different direction though that's not limited to logging. Good luck. Apr 23, 2017 at 18:33
  • No, logging intrigues me too. By works I mean requests that are not coming via the forward proxy, would $http_x_forwarded_for correctly log their origin IPs as well? Apr 23, 2017 at 22:13
  • You can definitely capture all the IP information in a log entry. You can also re-map data conditionally in nginx logs. Lots of things you can do...just depends on what you want. Your question here was, "How do I log...", not "How can I convert...", but you then accepted a "How to convert" solution, so it's not clear what you're looking for. If you want to know how to log without converting, you might consider posting a question along the lines of, "I want to log and I want the log entries to look like this: xxxx. How can I generate that log entry when the proxying IP is unknown?" Apr 23, 2017 at 22:44
  • This logging is fine for access log, but doesn't help for the error log. real_ip sounds OK, but may have ramifications such as existing code that checks which server forwarded the request.
    – Nate
    Feb 7, 2023 at 17:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .