场景:
用户认证接口:根据客户端IP和port,进行IP反查和端口范围确认,如符合则用户认证通过。
当前使用的是Nginx负载均衡,从客户端到Nginx端 ip和port都对,从Nginx到应有服务器上-port端口变成很奇怪的端口号。
疑问:Nginx往应有服务器上 是如何 传递 客户端IP和port 参数的呢?
请看 Nginx proxy_set_header:
Nginx proxy_set_header
允许重新定义或添加字段传递给代理服务器的请求头。该值可以包含文本、变量和它们的组合。在没有定义proxy_set_header时会继承之前定义的值。默认情况下,只有两个字段被重定义:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
如果启用缓存,来自之前请求的头字段“If-Modified-Since”, “If-Unmodified-Since”, “If-None-Match”, “If-Match”, “Range”, 和“If-Range”将不会被代理服务器传递。
一个不会变化的“Host”头请求字段可通过如下方式被传递:
proxy_set_header Host $http_host;
然后,当字段不在请求头中就无法传递啦。在这种情况下,可通过设置Host变量,将需传递值赋给Host变量。
proxy_set_header Host $host; // 获取nginx配置中的server_name值
此外,服务器名称和端口一起通过代理服务器传递。
proxy_set_header Host $host:$proxy_port; // 获取nginx配置中的server_name值和listen 值
如果请求头的存在空的字段将不会通过代理服务器传递出去。
proxy_set_header Accept-Encoding"";
总结:proxy_set_header 就是可设置请求头-并将头信息传递到服务器端。不属于请求头的参数中也需要传递时重定义下就行啦。
测试 不设置 proxy_set_header
Nginx配置
#负载均衡
upstream test {
server 192.168.220.123:9099;
server 192.168.220.123:58080;
}
server {
listen 5800;
server_name 192.168.220.123;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://test;
}
测试jsp 想获取客户端IP、客户端port、代理服务器IP、代理服务器port
<%@page contentType="text/html; charset=UTF-8"trimDirectiveWhitespaces="true"%>
<%
String scheme = request.getScheme();
String serverName = request.getServerName();
String remoteName = request.getRemoteAddr();
String realIP = request.getHeader("X-Forwarded-For");
String realIP2 = request.getHeader("X-Real-IP");
String Host = request.getHeader("Host");
int port = request.getServerPort();
int portR = request.getRemotePort();
String requestURIC1 = scheme+"://"+realIP+":"+portR;
String requestURIC2 =scheme+"://"+realIP2+":"+portR;
String requestURIC3 = scheme+"://"+remoteName+":"+portR;
String requestURI =scheme+"://"+serverName+":"+port;
%>
客户端地址1:<%=requestURIC1%>
<br>
客户端地址2:<%=requestURIC2%>
<br>
客户端地址3:<%=requestURIC3%>
<br>
服务器地址1:<%=requestURI%>
<br>
服务器地址2:<%=Host%>
<br>
测试结果
客户端地址1:http://null:58828
客户端地址2:http://null:58828
客户端地址3:http://192.168.220.123:58828
服务器地址1:http://test:80
服务器地址2:test
Nginx日志
192.168.220.177 -20508---5800 [25/Aug/2016:16:34:13 +0800] "GET/docs/test.jsp HTTP/1.1" 200 223 "-" "Mozilla/5.0 (WindowsNT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106Safari/537.36" "-"
其中客户端IP不能获取到,而通过request.getRemoteAddr();获取的IP是代理服务器IP,而不是客户端IP,而在nginx中$remote_addr变量的值是客户端的IP,可见remoteaddr没有传递。
而server_port值也不对,当前值为5800,当前打印出的是80。
而当前代理为http://test所有通过host得到的是test。
客户端port也获取不到值为20508,可传给应用的是58828
测试 设置proxy_set_header
Nginx 配置
upstream test {
server 192.168.220.123:9099;
server 192.168.220.123:58080;
}
server {
listen 5800;
server_name 192.168.220.123;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://test;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
测试页面改成:
<%@page contentType="text/html; charset=UTF-8"trimDirectiveWhitespaces="true"%>
<%
String scheme = request.getScheme();
String serverName = request.getServerName();
String remoteName = request.getRemoteAddr();
String realIP = request.getHeader("X-Forwarded-For");
String realIP2 = request.getHeader("X-Real-IP");
String Host = request.getHeader("Host");
int port = request.getServerPort();
int portR = request.getRemotePort();
String portR2 = request.getHeader("X-Real-Port");
String requestURIC1 = scheme+"://"+realIP+":"+portR;
String requestURIC2 = scheme+"://"+realIP2+":"+portR;
String requestURIC3 =scheme+"://"+remoteName+":"+portR;
String requestURI =scheme+"://"+serverName+":"+port;
%>
客户端地址1:<%=requestURIC1%>
<br>
客户端地址2:<%=requestURIC2%>
<br>
客户端地址3:<%=requestURIC3%>
<br>
服务器地址1:<%=requestURI%>
<br>
服务器地址2:<%=Host%>
<br>
客户端port2:<%=portR2%>
<br>
测试结果:
客户端地址1:http://192.168.220.177:21548
客户端地址2:http://192.168.220.177:21548
客户端地址3:http://192.168.220.123:21548
服务器地址1:http://192.168.220.123:5800
服务器地址2:192.168.220.123:5800
客户端port2:20604
Nging日志:
192.168.220.177 -20604---5800 [25/Aug/2016:16:38:42 +0800] "GET/docs/test.jsp HTTP/1.1" 200 275 "-" "Mozilla/5.0 (WindowsNT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106Safari/537.36" "-"
除request.getRemoteAddr();获取的值不对外,其他值都是对的。
getRemoteAddr获取的是代理的请求地址。
因重定义了host,所以test值被改写成代理服务器IP。
因重定义了X-Real-PORT-并传递$remote_port,客户端port也获取正确啦。
弄清楚是怎么传值的,正确的使用Nginx又向前进了一步。
本文出自 “IT技术解决方案” 博客,请务必保留此出处http://wyait.blog.51cto.com/12674066/1907123
原文地址:http://wyait.blog.51cto.com/12674066/1907123