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
yHTTP_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.