3

I use a lighttpd reverse proxy to serve django with gunicorn. Now this config worked:

proxy.server = ("" => ( "" => (
    "host" => "127.0.0.1",
    "port" => 8000,
)))

Now i moved the gunicorn into a container and use:

proxy.server = ("" => ( "" => (
    "host" => "192.168.1.2",
    "port" => 8000,
)))

Now every request has the ip 192.168.1.1 as seen by gunicorn. I would understand, if the reverse proxy obfuscates the real IP, but why did it work with localhost then?

for both i get

X-Forwarded-For: client-ip
X-Host: the.domain
X-Forwarded-Proto: http

where the client-ip is public ip space.

the requests comes from

host:

nc: connect to 127.0.0.1 8000 from localhost (127.0.0.1) 44953 [44953]

container:

nc: connect to 192.168.1.2 8000 from host (192.168.1.1) 60027 [60027]

the container itself has ip 192.168.1.2, the host-bridge has 192.168.1.1 and the routes inside the container are:

default via 192.168.1.1 dev eth0 
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.2

the host has:

192.168.1.0/24 dev bridge  proto kernel  scope link  src 192.168.1.1

EDIT: The X-Forwarded-For was the same for both requests. (Tested with nc -vlp 8000).

Reaces
  • 5,597
  • 4
  • 38
  • 46
allo
  • 1,620
  • 2
  • 22
  • 39

1 Answers1

4

My bet? lighttpd is adding an X-Forwarded-For header, and Django has something hardcoded somewhere to know that 127.0.0.1 is unlikely to be the real remote IP address if that header's present.

You should verify that the X-Forwarded-For header is present, then get Django to use that as the remote address (looks like the way to do that is here).

Shane Madden
  • 114,520
  • 13
  • 181
  • 251
  • i added some more info. The X-Forwarded-For header seems correct, but its still not working. In both cases it should not be able to get ip info from the reverse proxy, so it must use the X-Forwarded-For header. – allo Jan 13 '15 at 00:40
  • @allo Right - in a default config, the application won't just blindly trust an `X-Forwarded-For` header, as that would be a security problem (clients can send whatever, the header should only be trusted from trusted proxies). Configuration in Django will be needed before it'll trust the `X-Forwarded-For` that lighttpd is sending. – Shane Madden Jan 13 '15 at 00:42
  • okay, corrected the question again. you may be right, as server/client are 127.0.0.1 for the host scenario. – allo Jan 13 '15 at 00:46
  • http://gunicorn-docs.readthedocs.org/en/latest/deploy.html says this, too. But ``--forwarded-allow-ips=real-ip`` and ``--forwarded-allow-ips='*'`` do not work for me. – allo Jan 13 '15 at 01:02
  • 1
    Indeed, Django determines the real ip, and the ip determined by django is even logged in the gunicorn accesslog. I am using now a Middleware for the ip and it works: http://www.micahcarrick.com/django-ip-address-behind-nginx-proxy.html – allo Jan 13 '15 at 17:07