2012-02-21 11 views
5

Ho un'applicazione Pyramid che utilizza request.environ['REMOTE_ADDR'] in alcuni punti.Come ottenere l'IP reale di un client in un server piramidale dietro un proxy nginx

L'applicazione è servita da Python Paste sulla porta 6543 e un server nginx in ascolto sulla porta 80 sta inoltrando le richieste al server Paste.

La configurazione nginx è ispirato al libro di cucina Piramide:

server { 

    listen 80; ## listen for ipv4 
    listen [::]:80 default ipv6only=on; ## listen for ipv6 

    server_name localhost; 

    access_log /var/log/nginx/localhost.access.log; 

    location/{ 

     proxy_set_header  Host $host; 
     proxy_set_header  X-Real-IP $remote_addr; 
     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for; 
     proxy_set_header  X-Forwarded-Proto $scheme; 
     proxy_pass http://127.0.0.1:6543; 

    } 

Nell'applicazione Piramide del request.environ variabile [ 'REMOTE_ADDR'] è ora sempre uguale a 127.0.0.1. Vedo alcune strategie per risolvere questo problema, ma non so se esiste un modo consigliato per farlo.

Ecco quello che sto valutando:

  • aggiungere un abbonato NewRequest che sostituisce request.environ [ 'REMOTE_ADDR'], se necessario:

    if 'HTTP_X_REAL_IP' in event.request.environ: event.request.environ['REMOTE_ADDR'] = event.request.environ['HTTP_X_REAL_IP']

  • utilizzare un middleware WSGI per modificare request.environ prima di colpire il livello Pyramid.

  • qualcos'altro

Quale strategia si usa per la distribuzione di applicazioni piramide? Cosa succede se ho due proxy nginx? (il primo serve la LAN e un secondo uno una macchina collegata direttamente a Internet).

risposta

6

Se si utilizza il paste.deploy.config.PrefixMiddleware nel WSGI pipeline via use = egg:PasteDeploy#prefix, tradurrà automaticamente X-Forwarded-For in REMOTE_ADDR. È ottimo anche per altre proprietà del proxy inverso, ad esempio tradurrà X-Forwarded-Proto in wsgi.url_scheme per garantire che se l'utente visita https, gli URL generati siano anche https.

http://pythonpaste.org/deploy/class-paste.deploy.config.PrefixMiddleware.html

+0

Devo aver perso qualcosa perché ho provato per la prima volta con PrefixMiddleware come suggerito nel ricettario ma non ha funzionato. Ho davvero bisogno di provarlo di nuovo. – ascobol

+0

ok si scopre che ho dimenticato di inserire la sezione [pipeline: main]. Tutto funziona bene – ascobol

-2

in nginx:

location/{ 
    proxy_pass http://yourapp; 
     proxy_redirect  off; 
     proxy_set_header Host    $host; 
     proxy_set_header X-Real-IP  $remote_addr; 
     proxy_set_header X-Forwarded-For $remote_addr; 
     } 

in php che faccio:

 if($_SERVER["HTTP_X_FORWARDED_FOR"]){ 
     $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; 
    }else{ 
     $ip = $_SERVER["REMOTE_ADDR"]; 
     } 

forse in Python è simile, $ ip è il tuo IP reale

2

ho utilizzare il server gevent dietro nginx e io uso request.client_addr per ottenere l'indirizzo IP di un cliente.

1

Se non si dispone di un pipline WSGI, o non si desidera utilizzare paste, quindi aggiungere un gestore di eventi:

config.add_subscriber(reverseProxyProtocolCorrection,'pyramid.events.NewRequest') 

Il gestore di eventi in grado di leggere come:

def reverseProxyProtocolCorrection(event): 
    event.request.scheme = 'https' if event.request.headers['X-Forwarded-Proto']=='https' else 'http' 
    event.request.remote_addr=parseXForward(event.request.headers['X-Forwarded-For'],event.request.remote_addr) 

e fare sicuro che il tuo proxy imposta le intestazioni