在nginx / flask应用程序中获取客户端IP地址

时间:2019-02-22 16:30:22

标签: python nginx flask uwsgi

这个问题似乎经常被问到,但是我没有找到解决我所遇到问题的好方法。

我在nginx后面有一个flask应用程序。该应用程序和nginx通过uwsgi Unix套接字进行通信。该应用程序具有一个通过Route53公开的公开端点。它还通过AWS API Gateway公开。双重曝光的原因是该应用程序正在替换现有的Lambda解决方案。使用API​​网关,我可以支持旧式请求,直到它们可以过渡到新的公开端点。关于我的应用程序的另一个事实是,它在负载均衡器后面的Kubernetes容器中运行。

我需要访问发出请求的客户端的IP地址,以便可以使用geoIP查找并排除美国以外(GDPR)用户的数据收集。在进入应用程序的两条路径中,我有两种不同的方式来获取IP地址。

从API网关命中终结点

当我通过传统路径进入时,会得到一个X-Forwarded-For,但是我只看到注册到Amazon的IP地址。我使用的是列表中的第一个,但是我只看到一个或两个不同的IP地址。这是一个测试环境,也许是正确的,但是我不这样认为,因为当我从本地浏览器中访问它时,找不到我的IP。

直接击中终点:

在这种情况下,“ X-Forwarded-For”列表中没有数据,并且我可以找到的唯一IP地址是request.remote_addr。不幸的是,这仅具有容器或负载平衡器的IP地址。我不确定哪个是同一个类,但是两者都不匹配。无论如何,它绝对不是客户端IP地址。我在nginx中找到了描述可用变量(包括$ realip_remote_addr)的文档。但是,当我记录该值时,它与remote_addr相同。

以下是我用来获取remote_addr的代码:

def remote_addr(self, request):
    x_forwarded_for = request.headers.get("X-Forwarded-For")
    if x_forwarded_for:
        ip_list = x_forwarded_for.split(",")
        return ip_list[0]
    else:
        return request.remote_addr

如果有帮助,这是我的Nginx服务器配置:

server {
  listen 8443 ssl;
  ssl_certificate /etc/certs/cert;
  ssl_certificate_key /etc/certs/key;
  ssl_dhparam /etc/certs/dhparam.pem;
  ssl_protocols       TLSv1.2;
  ssl_prefer_server_ciphers   on;
  ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA HIGH !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
  server_tokens off;


  location = /log {
    limit_except POST {
      deny all;
    }
    include uwsgi_params;
    uwsgi_pass unix:///tmp/uwsgi.sock;
  }

  location = /ping {
    limit_except GET {
      deny all;
    }
    include uwsgi_params;
    uwsgi_pass unix:///tmp/uwsgi.sock;
  }

  location = /health-check {
    return 200 '{"response": "Healthy"}';
  }

  location /nginx_status {
    stub_status;
  }
}

我花了整整一天的时间试图解决这个问题。我确信该解决方案是微不足道的,很可能是由于缺乏使用nginx的知识/经验造成的。

0 个答案:

没有答案