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;
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. – Hassan Baig Apr 22 '17 at 0:51
  • Answer edited. Let me know if you have more questions. – Tim Apr 22 '17 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? – Hassan Baig Apr 22 '17 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. – Hassan Baig Apr 22 '17 at 16:27
  • 1
    I don't think alternate method is possible. See edited answer. – Tim Apr 22 '17 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.

4
  • 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? – Hassan Baig Apr 22 '17 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. – Diogenes deLight Apr 23 '17 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? – Hassan Baig Apr 23 '17 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?" – Diogenes deLight Apr 23 '17 at 22:44

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.