Obtenez l'adresse IP des visiteurs utilisant Flask pour Python

220

Je crée un site Web où les utilisateurs peuvent se connecter et télécharger des fichiers, en utilisant le micro-framework Flask (basé sur Werkzeug ) qui utilise Python (2.6 dans mon cas).

J'ai besoin d'obtenir l'adresse IP des utilisateurs lorsqu'ils se connectent (à des fins de journalisation). Est-ce que quelqu'un sait comment faire ça? Il y a sûrement un moyen de le faire avec Python?

Jon Cox
la source

Réponses:

295

Consultez la documentation sur la façon d'accéder à l'objet de demande et obtenir de ce même objet de demande, l'attribut remote_addr.

Exemple de code

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

Pour plus d'informations, consultez la documentation Werkzeug .

Tarentule
la source
1
Parfois, cela peut être utile: request.access_route [0]
Jonathan Prates
46
Quant à nginx, il envoie la véritable adresse IP sous, HTTP_X_FORWARDED_FORalors assurez-vous de ne pas vous retrouver avec localhost pour chaque demande.
Rasty Turek
95

Les proxys peuvent rendre cela un peu délicat, assurez-vous de vérifier ProxyFix ( Flask docs ) si vous en utilisez un. Jetez un œil à request.environvotre environnement particulier. Avec nginx, je fais parfois quelque chose comme ça:

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

Lorsque des proxys, tels que nginx, des adresses de transfert, ils incluent généralement l'IP d'origine quelque part dans les en-têtes de demande.

Mise à jour Voir l'implémentation flask-security . Encore une fois, consultez la documentation sur ProxyFix avant de l'implémenter. Votre solution peut varier en fonction de votre environnement particulier.

Stephen Fuhry
la source
2
Cela fonctionne lorsque vous définissez les champs appropriés dans la configuration de votre proxy inverse. Utilisé en production.
drahnr
3
@drahnr oui en effet. Le code ci-dessus fonctionne si, par exemple, dans nginx, vous définissez: proxy_set_header X-Real-IP $ remote_addr;
2015
@pors - ça marche. j'ai les mêmes paramètres dans ma conf nginx que vous. mais je ne comprends toujours pas pourquoi le code: request.headers.get ('X-Real-IP', request.remote_addr) ne fonctionne pas. Remarque, intuitivement, j'obtiendrais la valeur des en-têtes et utiliserais le nom 'X-Real-IP' car c'est ainsi que ma conf nginx est.
lostdorje
82

En fait, ce que vous trouverez, c'est que lorsque vous obtenez simplement ce qui suit, vous obtiendrez l'adresse du serveur:

request.remote_addr

Si vous souhaitez l'adresse IP du client, utilisez les éléments suivants:

request.environ['REMOTE_ADDR']
Chiedo
la source
4
Seulement si vous êtes derrière un proxy inverse, non?
Ry-
3
@minitech Je dirais que votre code ne devrait pas se soucier de savoir si vous êtes derrière un proxy ou non. Si cette option fonctionne de manière fiable indépendamment du proxy inverse et que l'autre suppose que vous n'êtes pas derrière un proxy inverse, cela devrait être préféré. (Je testerais cela si je pouvais facilement configurer un proxy inverse, mais cela prendrait plus de temps que je n'en ai actuellement.)
jpmc26
@ jpmc26: Je ne vois aucune raison pour que cela fonctionne. request.remote_addrsonne comme une propriété qui devrait obtenir une adresse distante selon que le proxy inverse est approuvé ou non.
Ry-
3
À l'aide de mod_wsgi, request.remote_addr a renvoyé l'adresse du serveur à chaque fois. request.environ ['REMOTE_ADDR'] m'a obtenu l'adresse IP publique du client. Peut-être que je manque quelque chose?
Chiedo
@ jpmc26 Vous devez souvent faire attention si vous êtes derrière un proxy distant. Si vous l'êtes, alors l'adresse IP qui vous connectera sera celle du serveur proxy distant, et vous devrez vous fier aux en-têtes qu'il ajoute pour obtenir l'IP client d'origine. Si vous ne l' êtes pas , ces en-têtes ne seront généralement pas présents et vous voudrez utiliser l'IP de connexion comme IP client. Et vous ne pouvez pas nécessairement vérifier l'en-tête et revenir à l'IP de connexion s'il n'est pas présent, car si vous n'êtes pas derrière un proxy inverse, un client peut usurper son IP, ce qui dans de nombreuses circonstances sera un problème de sécurité .
Mark Amery
28

L'adresse IP de l'utilisateur peut être récupérée à l'aide de l'extrait de code suivant:

from flask import request
print(request.remote_addr)
davidg
la source
3
Ce n'est pas vrai si l'application s'exécute derrière un serveur proxy comme nginx . Ce qui est souvent en production.
datcha
17

J'ai Nginx et avec ci-dessous Nginx Config :

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 solution @ tirtha-r a fonctionné pour moi

#!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)

Ma demande et réponse:

curl -X GET http://test.api

{
    "ip": "Client Ip......"
}
Soli
la source
13

Le code ci-dessous donne toujours l'adresse IP publique du client (et non une adresse IP privée derrière 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
la source
Cette réponse ainsi que la modification de ma configuration nginx selon ce blog a fonctionné pour moi. calvin.me/forward-ip-addresses-when-using-nginx-proxy
Romano Vacca
7

httpbin.org utilise cette méthode:

return jsonify(origin=request.headers.get('X-Forwarded-For', request.remote_addr))
Pégase
la source
Retours en 127.0.0.1raison d'un proxy, pas très utiles.
Uri Goren
3

Si vous utilisez Nginx derrière un autre équilibreur, par exemple AWS Application Balancer, HTTP_X_FORWARDED_FOR renvoie la liste des adresses. Il peut être corrigé comme ça:

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
la source
1

Si vous utilisez l'environnement Gunicorn et Nginx, le modèle de code suivant fonctionne pour vous.

addr_ip4 = request.remote_addr
Jyotiprakash panigrahi
la source
0

Cela devrait faire l'affaire. Il fournit l'adresse IP du client (hôte distant).

Notez que ce code s'exécute côté serveur.

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
raviv
la source