2009-10-26 12 views
9

Dostałem prostą konfigurację z nginxem dla statycznych nośników i równoważenia obciążenia oraz tornada jako serwera dla django (4 uruchomione serwery). Mój problem jest REMOTE_ADDR nie uzyskiwanie przekazywane do django tak Dostaję KeyError:REMOTE_ADDR nie jest wysyłany do Django przy użyciu nginx & tornado

article.ip = request.META['REMOTE_ADDR']

Zdalny adres jest uzyskiwanie wysłana przez co dzięki nginx.conf X-real-IP (HTTP_X_REAL_IP):

location/{ 
     proxy_pass_header Server; 
     proxy_set_header Host $http_host; 
     proxy_redirect false; 
     proxy_set_header X-Real-IP $remote_addr; 
     proxy_set_header X-Scheme $scheme; 
     proxy_pass http://frontends; 
    } 

jak HTTP jest dołączany do klawisza META nie mogę po prostu zrobić proxy_set_header REMOTE_ADDR $ REMOTE_ADDR. Co mogę zrobić, to przeczytać X-Real-IP, jeśli nie ma zdalnego klucza addr, ale jestem ciekawy, czy istnieje mądrzejsze rozwiązanie.

Dzięki!

+0

To rozwiązanie nie jest prawidłowa, ale dodaje się do pośredniej django który okazał HTTP_X_REAL_IP do REMOTE_ADDR. – Nixarn

+0

Te oświadczenia pomogą Ci: proxy_redirect off; proxy_set_header X-Real-IP $ remote_addr; \t \t proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; \t proxy_set_header X-Scheme $ scheme; – glarrain

Odpowiedz

11

Spróbuj tego:

location/{ 
    proxy_pass http://frontends; 
    proxy_pass_header Server; 
    proxy_redirect off; 
    proxy_set_header Host $http_host; 
    proxy_set_header X-Real-IP $remote_addr; 
    proxy_set_header X-Scheme $scheme; 
    proxy_set_header REMOTE_ADDR $remote_addr; 
} 

Wystarczy dodać proxy_set_header REMOTE_ADDR i powinno być dobrze.

wypróbowane:

  • Django 1.5.4
  • Nginx 1.4.3
  • Tornado 2.2.1
+0

według tego: https: //easyengine.io/tutorials/nginx/forwarding-visitors-real-ip/ wewnątrz backend-nginx conf: lokalizacja ~ \ .php $ { fastcgi_param REMOTE_ADDR $ http_x_real_ip; # ... inne zasady } – Amini

5

Mam podobne ustawienia. Po umieszczeniu nginxa przed apache zauważyłem, że adres IP w dziennikach apache był zawsze 127.0.0.1. Instalacja "libapache2-mod-rpaf" najwyraźniej rozwiązała problem. Nie mam pojęcia, czy twój problem jest związany.

+0

Ah dzięki, ale w ogóle nie używam Apache do tego projektu. – Nixarn

+0

oops, oczywiście, przepraszam za to – asciitaxi

+0

Dziękuję za odpowiedź. BTW: Pomaga to również oprogramowaniu PHP, które opiera się na $ _SERVER ['REMOTE_ADDR'], który teraz zawiera również prawdziwy zdalny adres IP. – Leif

0

Nie, to not possible przekazywać na remote_addr. Tak więc jedynym rozwiązaniem, które znam, jest użycie X-Real-IP lub X-Forwarded-For i upewnienie się, że backend obsługuje je poprawnie.

Edycja: dotyczy to fastcgi_pass, nie regularny nginx proxy_pass

+0

Nie możliwe? @ Juande's rozwiązanie działa całkiem dobrze dla mnie. –

+0

Dla programu obsługi fastcgi, tak. Ale pytanie dotyczyło serwera proxy nginx. – windyjonas

+1

Ups, powinienem był przeczytać bliżej - 'proxy_pass' nie jest' fastcgi_pass'. Nie mogę uchylić mojej zgody, chyba że edytujesz swoją odpowiedź. :/Jeśli chciałbyś go edytować, byłbym szczęśliwy, gdyby zamiast tego wziął udział w przegrywaniu. –

14

Oto jak rozwiązać ten problem. Za pomocą tego oprogramowania pośredniego:

class SetRemoteAddrMiddleware(object): 
    def process_request(self, request): 
     if not request.META.has_key('REMOTE_ADDR'): 
      try: 
       request.META['REMOTE_ADDR'] = request.META['HTTP_X_REAL_IP'] 
      except: 
       request.META['REMOTE_ADDR'] = '1.1.1.1' # This will place a valid IP in REMOTE_ADDR but this shouldn't happen 

Mam nadzieję, że pomoże!

+2

Jedynym problemem jest to, że jeśli po cichu zerwiesz błąd, odkryjesz ten źle skonfigurowany serwer WWW znacznie później (z potencjalnie utraconymi informacjami lub użytkownikami, którzy nie mogą się zalogować). Moja sugestia polegałaby na niepowodzeniu lub przynajmniej zarejestrowaniu błędu. –

+2

Niemal zawsze nie chcesz "wypróbować/poza:' 'bez wyjątku typu w CPython 2.x, ponieważ to również złapie SystemExit, KeyboardInterrupt i GeneratorExit - są to wszelkiego rodzaju błędy, które lepiej zostawić w spokoju lub w rzadkich przypadkach, złap je osobno. Szczególnie w tym przypadku należy złapać KeyError. Ale możesz jeszcze bardziej uprościć cały ten kod: 'request.META.setdefault ('REMOTE_ADDR', request.META.get ('HTTP_X_REAL_IP', '1.1.1.1'))' – temoto

+0

Ładne rozwiązanie, ale pamiętaj has_key() został usunięty w Pythonie 3.x. Użyj: jeśli nie request.META.get ('REMOTE_ADDR', Brak): – Robert

5

Dodaj "fastcgi_param REMOTE_ADDR $ remote_addr;" do pliku nginx.conf:

location/{ 
    # host and port to fastcgi server 
    fastcgi_pass 127.0.0.1:8801; 
    fastcgi_param PATH_INFO $fastcgi_script_name; 
    fastcgi_param REQUEST_METHOD $request_method; 
    fastcgi_param QUERY_STRING $query_string; 
    fastcgi_param CONTENT_TYPE $content_type; 
    fastcgi_param CONTENT_LENGTH $content_length; 
    fastcgi_pass_header Authorization; 
    fastcgi_intercept_errors off; 
    ... 
    # Add this line! 
    fastcgi_param REMOTE_ADDR $remote_addr; 
    ... 
} 

Źródło: how to nginx virtual servers + fcgi for django?

+0

Działa to doskonale dla 'fastcgi_pass' (thanks!), Ale nie będzie działać dla' proxy_pass', który jest konfiguracją OP (patrz odpowiedź @windyjonas). –

+1

Co powiecie na "fastcgi_param REMOTE_ADDR $ http_x_real_ip;'? Jeśli X-Real-IP jest dostępny dla nginx, może być użyty do przekazania jako fastcgi_param. To wyeliminuje konieczność wprowadzania zmian w kodach źródłowych aplikacji. – rahul286

2

Dla mnie, stosując następujące pracował:

server { 
    listen 80; 
    server_name foo.bar.com; 
    location/{ 
     proxy_pass http://127.0.0.1:8000; 
     proxy_set_header X-Forwarded-For $remote_addr; 
    } 
} 

To działa z Django 1.4 (w szczególności localshop).

Powiązane problemy