Obter o endereço IP dos visitantes usando o Flask for Python

220

Estou criando um site no qual os usuários podem fazer logon e baixar arquivos, usando a microestrutura Flask (baseada em Werkzeug ) que usa Python (2.6 no meu caso).

Preciso obter o endereço IP dos usuários quando eles efetuam logon (para fins de log). Alguém sabe como fazer isso? Certamente existe uma maneira de fazê-lo com Python?

Jon Cox
fonte

Respostas:

295

Consulte a documentação sobre como acessar o objeto de solicitação e, em seguida, começa a partir deste mesmo objeto Request, o atributo remote_addr.

Exemplo 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 mais informações, consulte a documentação do Werkzeug .

Tarântula
fonte
1
Algumas vezes, pode ser útil: request.access_route [0]
Jonathan Prates
46
Quanto ao nginx, ele envia o endereço IP real sob, HTTP_X_FORWARDED_FORportanto, certifique-se de não acabar com o host local para cada solicitação.
Rasty Turek
95

Os proxies podem tornar isso um pouco complicado, verifique o ProxyFix ( Flask docs ) se você estiver usando um. Dê uma olhada no request.environseu ambiente particular. Com o nginx, algumas vezes, faço algo assim:

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

Quando proxies, como nginx, encaminham endereços, geralmente incluem o IP original em algum lugar nos cabeçalhos da solicitação.

Atualização Veja a implementação do flask-security . Mais uma vez, revise a documentação sobre o ProxyFix antes de implementar. Sua solução pode variar de acordo com o seu ambiente específico.

Stephen Fuhry
fonte
2
Isso funciona quando você define os campos apropriados na configuração do seu proxy reverso. Utilizado na produção.
27515 drahnr
3
@ drahnr sim, de fato. O código acima funciona se, por exemplo, em nginx você definir: proxy_set_header X-Real-IP $ remote_addr;
pors
@pors - funciona. Eu tenho as mesmas configurações no meu nginx conf como você. mas ainda não entendo por que o código: request.headers.get ('X-Real-IP', request.remote_addr) não funciona. Note que, intuitivamente, eu pegaria o valor dos cabeçalhos e usaria o nome 'X-Real-IP', pois é assim que o meu nginx conf é.
Perdido # 21/15
82

Na verdade, o que você encontrará é que, ao simplesmente obter o seguinte, você obterá o endereço do servidor:

request.remote_addr

Se você deseja o endereço IP do cliente, use o seguinte:

request.environ['REMOTE_ADDR']
Chiedo
fonte
4
Só se você estiver atrás de um proxy reverso, não?
Ry-
3
@minitech Eu diria que seu código não deve se importar se você está atrás de um proxy ou não. Se essa opção funcionar de maneira confiável, independentemente do proxy reverso e a outra supor que você não está atrás de um proxy reverso, isso deve ser preferido. (Eu testar isso se eu poderia facilmente configurar um proxy reverso, mas que levaria mais tempo do que eu tenho no momento.)
jpmc26
@ jpmc26: Não vejo razão para que funcione. request.remote_addrsoa como uma propriedade que deve obter um endereço remoto, dependendo se o proxy reverso é confiável.
Ry-
3
Usando mod_wsgi, request.remote_addr retornava o endereço dos servidores sempre. request.environ ['REMOTE_ADDR'] me deu o endereço IP público do cliente. Talvez esteja faltando alguma coisa?
Chiedo 4/08/2014
@ jpmc26 Você freqüentemente fazer necessidade de cuidar se você estiver atrás de um proxy remoto. Se você for, o IP que se conecta a você será do servidor proxy remoto e você precisará confiar nos cabeçalhos adicionados para obter o IP do cliente original. Caso contrário , esses cabeçalhos normalmente não estarão presentes e você desejará usar o IP da conexão como o IP do cliente. E você não pode necessariamente verificar o cabeçalho e retornar ao IP da conexão se ele não estiver presente, porque, se você não estiver atrás de um proxy reverso, um cliente poderá falsificar seu IP, o que, em muitas circunstâncias, será um problema de segurança .
Mark Amery
28

O endereço IP do usuário pode ser recuperado usando o seguinte trecho:

from flask import request
print(request.remote_addr)
davidg
fonte
3
Isso não é verdade se o aplicativo estiver sendo executado atrás de um servidor proxy como o nginx . O que geralmente está em produção.
Datashaman
17

Eu tenho o Nginx e com o Nginx Config abaixo :

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

solução @ tirtha-r funcionou para mim

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

Minha solicitação e resposta:

curl -X GET http://test.api

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

O código abaixo sempre fornece o IP público do cliente (e não um IP privado atrás de um 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
fonte
Esta resposta, juntamente com a alteração da minha configuração do nginx, de acordo com este blog, funcionou para mim. 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))
Pegasus
fonte
Retorna 127.0.0.1devido a proxy, não muito útil.
Uri Goren 07/07
3

Se você usar o Nginx atrás de outro balanceador, por exemplo, o AWS Application Balancer, HTTP_X_FORWARDED_FOR retornará uma lista de endereços. Pode ser corrigido assim:

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
fonte
1

Se você estiver usando o ambiente Gunicorn e Nginx, o seguinte modelo de código funcionará para você.

addr_ip4 = request.remote_addr
Jyotiprakash panigrahi
fonte
0

Isso deve fazer o trabalho. Ele fornece o endereço IP do cliente (host remoto).

Observe que esse código está sendo executado no lado do servidor.

from mod_python import apache

req.get_remote_host(apache.REMOTE_NOLOOKUP)
Raviv
fonte