python flask webfaction

python - Flask request.remote_addr está mal en webfaction y no muestra la IP del usuario real



(5)

Acabo de implementar una aplicación Flask en Webfaction y he notado que request.remote_addr siempre es 127.0.0.1 . que por supuesto no es de mucha utilidad.

¿Cómo puedo obtener la dirección IP real del usuario en Flask en Webfaction?

¡Gracias!


Middleware werkzeug

La documentación de Flask es bastante específica sobre la configuración recomendada del servidor proxy inverso :

Si implementa su aplicación utilizando uno de estos servidores [WSGI] detrás de un proxy HTTP [inverso], deberá volver a escribir algunos encabezados para que la aplicación funcione [correctamente]. Los dos valores problemáticos en el entorno de WSGI por lo general son REMOTE_ADDR y HTTP_HOST ... Werkzeug entrega un reparador que solucionará algunas configuraciones comunes, pero es posible que desee escribir su propio middleware WSGI para configuraciones específicas.

Y también sobre la consideración de seguridad:

Tenga en cuenta que es un problema de seguridad utilizar un middleware de este tipo en una configuración no proxy porque confía ciegamente en los encabezados entrantes que pueden ser falsificados por clientes malintencionados.

El código sugerido (que instala el middleware) que hará que request.remote_addr devuelva la dirección IP del cliente es:

from werkzeug.contrib.fixers import ProxyFix app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=1)

Nota num_proxies que es 1 por defecto. Es el número de servidores proxy frente a la aplicación .

El código real es el siguiente (el werkzeug==0.14.1 en el momento de la escritura):

def get_remote_addr(self, forwarded_for): if len(forwarded_for) >= self.num_proxies: return forwarded_for[-self.num_proxies]

Webaccion

La documentación de REMOTE_ADDR sobre Acceso a REMOTE_ADDR dice:

... la dirección IP está disponible como la primera dirección IP en la lista separada por comas en el encabezado HTTP_X_FORWARDED_FOR .

No dicen lo que hacen cuando la solicitud de un cliente ya contiene X-Forwarded-For encabezado X-Forwarded-For , pero, siguiendo el sentido común, asumo que lo reemplazan. Por lo tanto, para Webfaction, num_proxies debe establecer en 0 .

Nginx

Nginx es más explícito sobre su $proxy_add_x_forwarded_for :

el campo de encabezado de solicitud de cliente "X-Forwarded-for" con la variable $remote_addr adjunta, separada por una coma. Si el campo "X-Forwarded-for" no está presente en el encabezado de la solicitud del cliente, la variable $proxy_add_x_forwarded_for es igual a la variable $remote_addr .

Para Nginx delante de la aplicación, num_proxies debe dejarse en el valor predeterminado 1 .


El problema es que probablemente hay algún tipo de proxy frente a Flask. En este caso, la dirección IP "real" a menudo se puede encontrar en los request.headers[''X-Forwarded-For''] de request.headers[''X-Forwarded-For''] .


Puede usar request.access_route para acceder a la lista de ip:

if len(request.access_route) > 1: return request.access_route[-1] else: return request.access_route[0]

Actualizar:

Puedes escribir esto:

return request.access_route[-1]


Reescribiendo la respuesta de los Ignas:

headers_list = request.headers.getlist("X-Forwarded-For") user_ip = headers_list[0] if headers_list else request.remote_addr

Recuerda leer la publicación de Eli sobre consideraciones de suplantación de identidad.


Si hay un proxy frente a Flask, entonces algo como esto obtendrá la IP real en Flask:

if request.headers.getlist("X-Forwarded-For"): ip = request.headers.getlist("X-Forwarded-For")[0] else: ip = request.remote_addr

Actualización: Muy buen punto mencionado por Eli en su comentario. Podría haber algunos problemas de seguridad si simplemente usas esto. Lea la publicación de Eli para obtener más detalles.