如何从X-Forwarded-for nginx + Gunicorn获得第一个客户端ip?

时间:2015-11-20 03:36:04

标签: python http nginx flask gunicorn

使用nginx + Gunicorn部署一个烧瓶应用程序,我需要从访问者那里获得真正的ip。 (对于Gunicorn在nginx之后无法获得REMOTE-ADDR)我试图从X-Forwarede获取客户端ip:for:

client_ip = request.headers.getlist(" X-Forwarded-For")[0]

有时我会像这样正确得到client_ip:

  

x-forwarded-for:62.211.19.218

但有时候我得到的client_ip错了 - 加上代理ip地址(从一些不同的浏览器访问):

  

x-forwarded-for:62.211.19.218,177.168.159.85

当nginx将两个ip地址转发给App时,如何只获得第一个客户端ip(没有代理地址177.168.159.85)?

1 个答案:

答案 0 :(得分:4)

通常X-FORWARDED-FOR形式如下:

X-Forwarded-For: client1, proxy1, proxy2, ...

但请记住,您不应该信任X-Forwarded-For或任何其他标头值,因为它们可以被不受信任的代理或其他东西操纵......

如果您使用nginx作为反向代理,您还可以检查request.environ['HTTP_X_REAL_IP']

修改

根据flask documentationclient_ip = request.access_route[0]将是您的答案。它将返回X-FORWARDED-FOR中的IP地址。检查此wrekzeug/wrapper.py源代码

@cached_property
def access_route(self):
    """If a forwarded header exists this is a list of all ip addresses
    from the client ip to the last proxy server.
    """
    if 'HTTP_X_FORWARDED_FOR' in self.environ:
        addr = self.environ['HTTP_X_FORWARDED_FOR'].split(',')
        return self.list_storage_class([x.strip() for x in addr])
    elif 'REMOTE_ADDR' in self.environ:
        return self.list_storage_class([self.environ['REMOTE_ADDR']])
    return self.list_storage_class()

请注意,某些http服务器会将localhost或本地IP地址附加到access_route列表的第一项。