Getting an IP Address in Django behind an Nginx Proxy

When running Django behind Nginx as a reverse proxy, the request.META['REMOTE_ADDR'] may store the proxy IP address (eg. 127.0.0.1) rather than the client's IP address. To get the client's IP address in Django, you can set the X-Forwarded-For HTTP header in your nginx proxy configuration:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

And then access it in Django with request.META['HTTP_X_FORWARDED_FOR']:

ip = request.META['HTTP_X_FORWARDED_FOR']

You would use request.META['HTTP_X_FORWARDED_FOR'] only when running Django behind a reverse proxy where you know that your server is setting the value and it is not being sent in the request. Therefore, getting the IP from request.META['HTTP_X_FORWARDED_FOR'] vs request.META['REMOTE_ADDR'] must be determined at the project-level and not within a reusable app.

So, if you don't want your reusable apps using conditionals to determine where to get the IP address, what do you do? Well, I use a variation of the infamous SetRemoteAddrFromForwardedFor middleware. Once upon a time, Django shipped with this middleware to set the value of request.META['REMOTE_ADDR'] to request.META['HTTP_X_FORWARDED_FOR'] if it exists. It was removed in Django 1.2 as it was deemed too easy to be used incorrectly.

I create XForwardedForMiddleware and put it into middleware.py at the project-level.

class XForwardedForMiddleware():
    def process_request(self, request):
        if 'HTTP_X_FORWARDED_FOR' in request.META:
            request.META['REMOTE_ADDR'] = request.META['HTTP_X_FORWARDED_FOR']
        return None

With this middleware installed, reusable apps can simply use request.META['REMOTE_ADDR'] and be blissfully unaware of the fact that it's behind a proxy.

Did you enjoy Getting an IP Address in Django behind an Nginx Proxy? If you would like to help support my work, A donation of a buck or two would be very much appreciated.
blog comments powered by Disqus
Linux Servers on the Cloud IN MINUTES