Python 如何在nginx代理背后的金字塔服务器中获取客户机的真实IP
我有一个金字塔应用程序,在某些地方使用Python 如何在nginx代理背后的金字塔服务器中获取客户机的真实IP,python,deployment,nginx,pyramid,wsgi,Python,Deployment,Nginx,Pyramid,Wsgi,我有一个金字塔应用程序,在某些地方使用request.environ['REMOTE\u ADDR'] 该应用程序由端口6543上的Python Paste提供服务,在端口80上侦听的nginx服务器正在向Paste服务器转发请求 nginx配置的灵感来自金字塔食谱: server { listen 80; ## listen for ipv4 listen [::]:80 default ipv6only=on; ## listen for ipv6 ser
request.environ['REMOTE\u ADDR']
该应用程序由端口6543上的Python Paste提供服务,在端口80上侦听的nginx服务器正在向Paste服务器转发请求
nginx配置的灵感来自金字塔食谱:
server {
listen 80; ## listen for ipv4
listen [::]:80 default ipv6only=on; ## listen for ipv6
server_name localhost;
access_log /var/log/nginx/localhost.access.log;
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://127.0.0.1:6543;
}
在金字塔应用程序中,变量request.environ['REMOTE_ADDR']现在始终等于127.0.0.1。
我看到了一些解决这个问题的策略,但我不知道是否有推荐的方法
以下是我正在考虑的:
- 如有必要,添加一个新的request订阅服务器,以替换request.environ['REMOTE\u ADDR']:
如果event.request.environ中的“HTTP\u X\u REAL\u IP”: event.request.environ['REMOTE\u ADDR']=event.request.environ['HTTP\u X\u REAL\u IP']
- 在到达金字塔层之前,使用wsgi中间件修改request.environ
- 别的
location / {
proxy_pass http://yourapp;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
在php中,我会:
if($_SERVER["HTTP_X_FORWARDED_FOR"]){
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}else{
$ip = $_SERVER["REMOTE_ADDR"];
}
也许在python中类似,$ip是您真正的ip如果您通过
use=egg:PasteDeploy#prefix
在WSGI管道中使用paste.deploy.config.PrefixMiddleware
,它将自动将X-Forwarded-For
转换为REMOTE\u ADDR
。它还适用于反向代理的其他属性,例如,它将X-Forwarded-Proto
转换为wsgi.url\u scheme
,以确保如果用户使用https访问,则生成的url也是https
我使用nginx后面的gevent服务器,并使用
request.client\u addr
获取客户端的ip地址。如果您没有WSGI管道,或者不希望使用粘贴
,请添加事件处理程序:
config.add_subscriber(reverseProxyProtocolCorrection,'pyramid.events.NewRequest')
事件处理程序的读取方式如下:
def reverseProxyProtocolCorrection(event):
event.request.scheme = 'https' if event.request.headers['X-Forwarded-Proto']=='https' else 'http'
event.request.remote_addr=parseXForward(event.request.headers['X-Forwarded-For'],event.request.remote_addr)
并确保您的代理设置了标题我一定错过了什么,因为我第一次尝试使用PrefixMiddleware,正如烹饪书中建议的那样,但它不起作用。我显然需要再试一次。好吧,结果我忘记插入[pipeline:main]部分了。一切正常