设为首页 收藏本站
查看: 1558|回复: 0

[经验分享] nginx做负载CDN加速获取端真实ip

[复制链接]

尚未签到

发表于 2018-11-13 08:23:03 | 显示全部楼层 |阅读模式
  nginx做负载CDN加速获取端真实ip在不用cdn的情况下,nginx做负载获取真实ip时,nginx配置如下:Java代码 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 然后后端服
  nginx做负载CDN加速获取端真实ip   在不用cdn的情况下,nginx做负载获取真实ip时,nginx配置如下:   Java代码   proxy_set_header        Host            $host;   proxy_set_header        X-Real-IP       $remote_addr;   proxy_set_header        X-Forwarded-For$proxy_add_x_forwarded_for;     然后后端服务器获取ip代码:   Java代码   String address = request.getHeader("X-Forwarded-For");   if (address != null && address.length() > 0           && !"unknown".equalsIgnoreCase(address)) {       return address;    www.cit.cn   }   address = request.getHeader("Proxy-Client-IP");   if (address != null && address.length() > 0           &&!"unknown".equalsIgnoreCase(address)) {       return address;   }   address = request.getHeader("WL-Proxy-Client-IP");   if (address != null&& address.length() > 0           && !"unknown".equalsIgnoreCase(address)) {       return address;   }   return request.getRemoteAddr();   这样就能获取到真实的IP,服务器测试一下:
  不加cdn,获取得IP:123.116.126.51(我当前客户端机器的真实IP) 然后加上加了cdn后,后去到的IP:123.116.126.51, 202.108.251.166(hosts指向cdn的ip) 即:client 真实IP,代理IP,google之, X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项 。
  标准格式如下: X-Forwarded-For: client1, proxy1, proxy2 从标准格式可以看出,X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡的ip地址,经过几个就会出现几个。   当Nginx设置X-Forwarded-For等于$proxy_add_x_forwarded_for后会有两种情况发生   www.cit.cn   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,CDN的ip“如果是这种情况的话,那后端的程序通过X-Forwarded-For获得客户端IP,则取逗号分隔的第一项即可。   这个比较头疼,如果只想获取客户端真实ip,那么只能修改我们后端代码,如果有多个,那么取第一个。这不是我想要的, 那么怎么样才能不修改就能真实IP呢? 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或者干脆不设置!   上面这段话的意思是我们不加 $proxy_add_x_forwarded_for, 但是这样不在cdn的情况下去会取不到真实IP,有没有一个两全齐美的方法呢? 经过几种配置之后,发现做如下配置:   Java代码    www.cit.cn   proxy_set_header X-Forwarded-For  $http_x_forwarded_for;  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;         这样配置第一次获取 $http_x_forwarded_for,如果不存在,那么获取$proxy_add_x_forwarded_for。 这样不管是否在cdn环境,都可以获得一个客户端IP。   (注:多层代理未测试)     作者 lavafree
  使用了$http_x_forwarded_for后,测试nginx配置时可能报
  nginx:[warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
  nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
  解决方法:
  在http {}时增加
  proxy_headers_hash_max_size 2048;
  proxy_headers_hash_bucket_size 256;
  oxy_set_headerThis 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-ForX-Forwarded-For: client1, proxy1, proxy2

  The X-Forwarded-For (XFF) HTTP header is a de facto standard for>  这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,
  每次经过proxy转发都会有记录,格式就是client1, proxy1, proxy2,以逗号隔开各个地址
  由于他是非rfc标准,所以默认是没有的,需要强制添加
  在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip
  └(^o^)┘
  下面来分析请求头到达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
  
  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最后的值。
  特别说明:
  a、Fikker 通过 HTTP 头传递用户 IP 地址给源站,例如:X-Forwarded-For: 21.23.44.78 。
  b、如出现多个 IP 时,例如:X-Forwarded-For: 21.23.44.78; 156.24.66.231,表明用户请求经过多次 Fikker 转发,这时有效起始地址为第一个,即 21.23.44.78 。
  asp 获得用户 IP 代码举例:
   0Then
  strIPAddr = Request.ServerVariables("REMOTE_ADDR")
  ElseIf InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ",") > 0 Then
  strIPAddr= Mid(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), 1, InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ",")-1)
  ElseIf InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ";") > 0 Then
  strIPAddr= Mid(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), 1, InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ";")-1)
  Else
  strIPAddr = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
  End If
  getIP = Trim(Mid(strIPAddr, 1, 30))
  End Function
  ip=getIP()
  response.write(ip)
  %>
  java 获得用户 IP 代码举例:
  public String getRemortIP(HttpServletRequest request)
  {
  if (request.getHeader("X-Forwarded-For") == null)
  {
  return request.getRemoteAddr();
  }
  return request.getHeader("X-Forwarded-For");  /* 多个 IP 列表时, 则取第一个! */
  }
  asp.net 获得用户 IP 代码举例:
  void getSourceIP()
  {
  string SourceIP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; /* 获得用户 IP 地址 */
  if (string.IsNullOrEmpty(SourceIP))
  {
  SourceIP = Request.ServerVariables["REMOTE_ADDR"]; /* 兼容已有程序 */
  }
  Response.Write(SourceIP);
  }
  php 获得用户 IP 代码举例:
  function getRemortIP()
  {
  if (!isset($_SERVER["HTTP_X_FORWARDED_FOR"])) /* 存在 X-Forwarded-For 吗? */
  {
  return $_SERVER["REMOTE_ADDR"];
  }
  return $_SERVER["HTTP_X_FORWARDED_FOR"]; /* 返回用户 IP */
  }
  echo getRemortIP();


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-634326-1-1.html 上篇帖子: Nginx+tomcat7的负载均衡和动静分离配置 下篇帖子: nginx访问控制 if多条件判断
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表