2012-02-21 32 views
5

Tengo una aplicación que utiliza la Pirámide request.environ['REMOTE_ADDR'] en algunos lugares.¿Cómo obtener la IP real de un cliente en un servidor de pirámide detrás de un proxy Nginx

La aplicación es servida por Python en Pegar en el puerto 6543 y un servidor Nginx escuchando en el puerto 80 es el reenvío de peticiones al servidor Pegar.

La configuración nginx está inspirado en el libro de cocina Pyramid:

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; 

    } 

En la aplicación de la pirámide la request.environ variable de [ 'REMOTE_ADDR'] es ahora siempre igual a 127.0.0.1. Veo algunas estrategias para resolver este problema, pero no sé si hay una manera recomendada de hacerlo.

Aquí es lo que estoy considerando:

  • añadir un suscriptor NewRequest que sustituye request.environ [ 'REMOTE_ADDR'] si es necesario:

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

  • utilizan un middleware WSGI para modificar request.environ antes de golpear la capa de Pyramid.

  • algo más

¿Qué estrategia que utiliza para implementar aplicaciones de la pirámide? ¿Qué pasará si tengo dos proxys nginx? (el primero que sirve la LAN y el segundo una máquina directamente conectada a internet).

Respuesta

6

Si utiliza el paste.deploy.config.PrefixMiddleware en su WSGI tubería a través de use = egg:PasteDeploy#prefix, se traducirá automáticamente X-Forwarded-For en REMOTE_ADDR. También es ideal para otras propiedades de su proxy inverso, por ejemplo, traducirá X-Forwarded-Proto en wsgi.url_scheme para garantizar que si el usuario visita https, las URL generadas también sean https.

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

+0

Debo haberme perdido algo porque primero probé con PrefixMiddleware como se sugiere en el libro de cocina, pero no funcionó. Obviamente necesito probarlo de nuevo. – ascobol

+0

bien, resulta que olvidé insertar la sección [pipeline: main]. Todo funciona bien – ascobol

-2

en 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; 
     } 

en php que hago:

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

quizás en Python es similar, $ ip es su IP real

2

que usar servidor GEvent detrás de Nginx y utilizo request.client_addr para obtener la dirección IP de un cliente.

1

Si usted no tiene un pipline WSGI, o si no desea utilizar paste, a continuación, agregar un controlador de eventos:

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

El controlador de eventos puede leer como:

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) 

y hacer Asegúrese de que su proxy establezca los encabezados

Cuestiones relacionadas