Obtenga la dirección IP de los visitantes que usan Flask for Python

220

Estoy creando un sitio web donde los usuarios pueden iniciar sesión y descargar archivos, utilizando el micro marco Flask (basado en Werkzeug ) que utiliza Python (2.6 en mi caso).

Necesito obtener la dirección IP de los usuarios cuando inician sesión (para fines de registro). ¿Alguien sabe como hacer esto? ¿Seguramente hay una manera de hacerlo con Python?

Jon Cox
fuente

Respuestas:

295

Consulte la documentación sobre cómo acceder al objeto Solicitud y luego obtener de este mismo objeto Solicitud, el atributo remote_addr.

Ejemplo de código

from flask import request
from flask import jsonify

@app.route("/get_my_ip", methods=["GET"])
def get_my_ip():
    return jsonify({'ip': request.remote_addr}), 200

Para obtener más información, consulte la documentación de Werkzeug .

Tarántula
fuente
1
Algunas veces, puede ser útil: request.access_route [0]
Jonathan Prates
46
En cuanto a nginx, envía la dirección IP real debajo, HTTP_X_FORWARDED_FORasí que asegúrese de no terminar con localhost para cada solicitud.
Rasty Turek
95

Los proxies pueden hacer que esto sea un poco complicado, asegúrate de revisar ProxyFix ( Flask docs ) si estás usando uno. Eche un vistazo a request.environsu entorno particular. Con nginx a veces haré algo como esto:

from flask import request   
request.environ.get('HTTP_X_REAL_IP', request.remote_addr)   

Cuando los servidores proxy, como nginx, reenvían direcciones, generalmente incluyen la IP original en algún lugar de los encabezados de solicitud.

Actualización Consulte la implementación de seguridad del matraz . Nuevamente, revise la documentación sobre ProxyFix antes de implementar. Su solución puede variar según su entorno particular.

Stephen Fuhry
fuente
2
Esto funciona cuando configura los campos apropiados en la configuración de su proxy inverso. Utilizado en producción.
drahnr
3
@drahnr sí, de hecho. El código anterior funciona si, por ejemplo, en nginx establece: proxy_set_header X-Real-IP $ remote_addr;
pors
@pors: funciona. Tengo la misma configuración en mi nginx conf que tú. pero todavía no entiendo por qué el código: request.headers.get ('X-Real-IP', request.remote_addr) no funciona. Tenga en cuenta que, intuitivamente, obtendría el valor de los encabezados y usaría el nombre 'X-Real-IP', ya que así es mi nginx conf.
lostdorje
82

En realidad, lo que encontrará es que al obtener lo siguiente obtendrá la dirección del servidor:

request.remote_addr

Si desea la dirección IP del cliente, use lo siguiente:

request.environ['REMOTE_ADDR']
Chiedo
fuente
44
Solo si estás detrás de un proxy inverso, ¿no?
Ry-
3
@minitech Yo diría que a tu código no le importa si estás detrás de un proxy o no. Si esta opción funciona de manera confiable independientemente del proxy inverso y la otra asume que no está detrás de un proxy inverso, entonces debería preferirse. (Probaría esto si pudiera configurar fácilmente un proxy inverso, pero eso tomaría más tiempo del que tengo en este momento).
jpmc26
@ jpmc26: No veo ninguna razón por la que debería funcionar. request.remote_addrsuena como una propiedad que debería obtener una dirección remota dependiendo de si el proxy inverso es confiable.
Ry-
3
Usando mod_wsgi, request.remote_addr devolvió la dirección del servidor cada vez. request.environ ['REMOTE_ADDR'] me consiguió la dirección IP pública del cliente. Tal vez me estoy perdiendo algo?
Chiedo
@ jpmc26 Con frecuencia se hace necesario importa si estás detrás de un proxy remoto. Si es así, la IP que se conecta a usted será del servidor proxy remoto y deberá confiar en los encabezados que agrega para obtener la IP del cliente original. Si usted es no , esas cabeceras normalmente no estarán presentes, y usted desee utilizar la conexión IP como la dirección IP del cliente. Y no se puede comprobar necesariamente sólo para la cabecera y caer de nuevo a la IP de conexión si no está presente, porque entonces si estás no detrás de un proxy inverso que un cliente puede suplantar su IP, que en muchas circunstancias será un problema de seguridad .
Mark Amery
28

La dirección IP del usuario se puede recuperar con el siguiente fragmento:

from flask import request
print(request.remote_addr)
davidg
fuente
3
Esto no es cierto si la aplicación se ejecuta detrás de un servidor proxy como nginx . Que a menudo está en producción.
datashaman
17

Tengo Nginx y con la siguiente configuración de Nginx :

server {
    listen 80;
    server_name xxxxxx;
    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://x.x.x.x:8000;
        }
}

La solución @ tirtha-r funcionó para mí

#!flask/bin/python
from flask import Flask, jsonify, request
app = Flask(__name__)

@app.route('/', methods=['GET'])
def get_tasks():
    if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
        return jsonify({'ip': request.environ['REMOTE_ADDR']}), 200
    else:
        return jsonify({'ip': request.environ['HTTP_X_FORWARDED_FOR']}), 200

if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0', port=8000)

Mi solicitud y respuesta:

curl -X GET http://test.api

{
    "ip": "Client Ip......"
}
Soli
fuente
13

El siguiente código siempre proporciona la IP pública del cliente (y no una IP privada detrás de un proxy).

from flask import request

if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
    print(request.environ['REMOTE_ADDR'])
else:
    print(request.environ['HTTP_X_FORWARDED_FOR']) # if behind a proxy
Tirtha R
fuente
Esta respuesta junto con el cambio de mi configuración nginx de acuerdo con este blog funcionó para mí. calvin.me/forward-ip-addresses-when-using-nginx-proxy
Romano Vacca
7

httpbin.org usa este método:

return jsonify(origin=request.headers.get('X-Forwarded-For', request.remote_addr))
Pegaso
fuente
Devoluciones 127.0.0.1debido a proxy, no muy útil.
Uri Goren
3

Si usa Nginx detrás de otro equilibrador, por ejemplo AWS Application Balancer, HTTP_X_FORWARDED_FOR devuelve una lista de direcciones. Se puede arreglar así:

if 'X-Forwarded-For' in request.headers:
    proxy_data = request.headers['X-Forwarded-For']
    ip_list = proxy_data.split(',')
    user_ip = ip_list[0]  # first address in list is User IP
else:
    user_ip = request.remote_addr  # For local development
Vlad
fuente
1

Si está utilizando el entorno Gunicorn y Nginx, la siguiente plantilla de código funciona para usted.

addr_ip4 = request.remote_addr
Jyotiprakash panigrahi
fuente
0

Esto debería hacer el trabajo. Proporciona la dirección IP del cliente (host remoto).

Tenga en cuenta que este código se ejecuta en el lado del servidor.

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
raviv
fuente