Nginx proxy_set_header 理解

Stella981
• 阅读 1020

用户认证接口:根据客户端IP和port,进行IP反查和端口范围确认,如符合则用户认证通过。
当前使用的是Nginx负载均衡,从客户端到Nginx端 ip和port都对,从Nginx到应有服务器上-port端口变成很奇怪的端口号。真是遇到的问题,登录页的ip和port在登录验证没有问题,但在登录完成后跳转的时候,端口号发生了变化。跟nginx服务器的监听端口相同了。(注:除了部署的Nginx服务器,应该还有一个前端的nginx,这是我没有接触到的部分。)
疑问: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”头请求字段可通过如下方式被传递:

我的项目就使用了这个参数设置,请求的host的IP和PORT没变

proxy_set_header Host       $http_host;

然后,当字段不在请求头中就无法传递啦。在这种情况下,可通过设置Host变量,将需传递值赋给Host变量。

proxy_set_header Host       $host;

此外,服务器名称和端口一起通过代理服务器传递。

proxy_set_header Host       $host:$proxy_port;

如果请求头的存在空的字段将不会通过代理服务器传递出去。

proxy_set_header Accept-Encoding "";

总结:proxy_set_header 就是可设置请求头-并将头信息传递到服务器端。不属于请求头的参数中也需要传递时 重定义下就行啦。

  1. 测试 不设置 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 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36" "-"
    

    其中客户端IP不能获取到,而通过request.getRemoteAddr();获取的IP是代理服务器IP,而不是客户端IP,而在nginx中$remote_addr变量的值是客户端的IP,可见remoteaddr没有传递。
    而server_port值也不对,当前值为5800,当前打印出的是80。
    而当前代理为http://test 所有通过host得到的是test。
    客户端port也获取不到值为20508,可传给应用的是58828

  2. 测试 设置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 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36" "-"
    

    除request.getRemoteAddr();获取的值不对外,其他值都是对的。
    getRemoteAddr获取的是代理的请求地址。
    因重定义了host,所以test值被改写成代理服务器IP。
    因重定义了 X-Real-PORT-并传递$remote_port,客户端port也获取正确啦。
    弄清楚是怎么传值的,正确的使用Nginx又向前进了一步。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这