其实这个问题在Nginx + uwsgi + django 上是不存在的,因为nginx 与uwsgi链接是可以通过sock文件的,而nginx + flask 只能通过普通的反向代理。

所以就会出现一个nginx 反向代理常见的问题,实际对flask 发起的请求是由ningx完成,所以获取到的ip是服务器本机的地址,甚至是机器的内网地址。

uwsgi+nginx+django

我们先来看看uwsgi+nginx+django是如何获取用户ip的:

 try:
	real_ip = request.META['HTTP_X_FORWARDED_FOR']
	if len(real_ip) > 1:
	ip = real_ip.split(",")[0]
except:
	try:
		ip = request.META['REMOTE_ADDR']
	except:
		ip = "0.0.0.0" 

 flask

我们再来看下如果不用nginx,flask本身获取用户ip的常用方法:

代码结构同上,只是flask中单独作为变量

from flask import request
ip = request.remote_addr
ip = request.http_x_forwarded_for

Nginx + Flask + gunicorn

我们首先要在nginx配置中添加HTTP_X_FORWARDED_FOR 头,用nginx自身的获取ip模块赋值

所以我们可以在nginx配置的server上添加:

 
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
server {
        listen  80;
……
……
 

那么flask中就可以获取headers中的X-Forwarded-For即可,代码如下:


real_ip = request.headers['X-Forwarded-For']
if len(real_ip.split(',')) > 1:
	ip = real_ip.split(",")[1]
else:
	ip = real_ip  

配置好后可以看到nginx对flask的请求,已经带上了X-Forwarded-For

那么有安全经验的朋友可能会想到X-Forwarded-For头是可以伪造的,那我们来伪造看下nginx的请求会变成什么,

可以看到伪造的8.8.8.8,但同时也可以看到真实的ip,但这个真是ip是抹不掉的,所以我们截取下最后的ip即可

以上,可见这种方法还是安全可行的。