您的位置:首页 > 运维架构 > Nginx

NGINX proxy_set_header和X-Forwarded-For问题

2012-09-12 23:31 856 查看
Proxy_set_header This directive allows to redefine and to add some request header lines which will be transferred to the proxied server.

这个不是change而是add,我了割草....我分析了好久日志才发现,然后对照官网,果不其然

ex:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,由于默认是空,所以也可以理解为change,但是切记不要搞乱.

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

The X-Forwarded-For (XFF) HTTP header is a de facto standard for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer. This is a non-RFC-standard request header which was introduced by the Squid caching proxy server's developers.

这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,

每次经过proxy转发都会有记录,格式就是client1, proxy1, proxy2,以逗号隔开各个地址

由于他是非rfc标准,所以默认是没有的,需要强制添加

在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip.

下面来分析请求头到达Nginx负载均衡服务器的情况;在默认情况下,Nginx并不会对X-Forwarded-For头做任何的处理,除非用户使用proxy_set_header 参数设置:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For"与$remote_addr,它们用逗号分开.如果没有"X-Forwarded-For" 请求头,则$proxy_add_x_forwarded_for等于$remote_addr。$remote_addr变量的值是客户端的IP.



当Nginx设置X-Forwarded-For等于$proxy_add_x_forwarded_for后会有两种情况发生


1、如果从CDN过来的请求没有设置X- Forwarded-For头(通常这种事情不会发生),而到了我们这里Nginx设置将其设置为$proxy_add_x_forwarded_for 的话,X-Forwarded-For的信息应该为CDN的IP,因为相对于Nginx负载均衡来说客户端即为CDN,这样的话,后端的web程序时死活 也获得不了真实用户的IP的。





2、CDN设置了X-Forwarded-For,我们这里又设置了一次,且值为$proxy_add_x_forwarded_for的话,那么X-Forwarded-For的内容变成 ”客户端IP,Nginx负载均衡服务器IP“如果是这种情况的话,那后端的程序通过X-Forwarded-For获得客户端IP,则取逗号分隔的第一项即可。

如上两点所说,如果我们知道了CDN设置了X-Forwarded-For信息,且只有客户端真实的IP的话,那么我们的Nginx负载均衡服务器可以不必理会该头,让它默认即可。

其实Nginx中还有一个$http_x_forwarded_for变量,这个变量中保存的内容就是请求中的X-Forwarded-For信息。如果后端获得X-Forwarded-For信息的程序兼容性不好的话(没有考虑到X-Forwarded-For含有多个IP的情况),最好就不要将X-Forwarded-For设置为 $proxy_add_x_forwarded_for。应该设置为$http_x_forwarded_for或者干脆不设置!

Code block








测试环境: nginx+resin

IP: 内网:172.16.100.10

客户端IP:123.123.123.123

测试页面: test.jsp

<%

out.println("x-forwarded-for: " + request.getHeader("x-forwarded-for"));

out.println("remote hosts: " + request.getRemoteAddr());

%>

nginx 配置一

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

wget测试

wget -O aa --header="X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"

页面返回结果:

x-forwarded-for: 192.168.0.1, 123.123.123.123

remote hosts: 172.16.100.10

curl测试

curl -H "X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"

x-forwarded-for: 192.168.0.1, 123.123.123.123

remote hosts: 172.16.100.10

nginx 配置二

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

wget测试:

wget -O aa --header="X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"

页面返回结果:

x-forwarded-for: 123.123.123.123

remote hosts: 172.16.100.10

curl测试

curl -H "X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"

x-forwarded-for: 123.123.123.123

remote hosts: 172.16.100.10

测试结果:

1、配置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

增加了一个真实ip X-Forwarded-For,并且顺序是增加到了“后面”。

2、配置 proxy_set_header X-Forwarded-For $remote_addr;

清空了客户端伪造传入的X-Forwarded-For,

保证了使用request.getHeader("x-forwarded-for")获取的ip为真实ip,

或者用“,”分隔,截取X-Forwarded-For最后的值。

参考:

http://hi.baidu.com/daizhongxian/blog/item/e074002c6bace6e28b13994d.html

http://en.wikipedia.org/wiki/X-Forwarded-For

http://wiki.nginx.org/NginxHttpProxyModule#proxy_set_header

http://wiki.nginx.org/NginxHttpLogModule

http://2hei.net/mt/2010/03/nginx-x-forwarded-for.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: