zoukankan      html  css  js  c++  java
  • 取客户端IP的那些事

      1 外界流传的JAVA/PHP服务器端获取客户端IP都是这么取的:
      2 伪代码:
      3 1)ip = request.getHeader("X-FORWARDED-FOR")
      4     可伪造,参考附录A
      5 2)如果该值为空或数组长度为0或等于"unknown",那么:
      6 ip = request.getHeader("Proxy-Client-IP")
      7 3)如果该值为空或数组长度为0或等于"unknown",那么:
      8 ip = request.getHeader("WL-Proxy-Client-IP")
      9 4)如果该值为空或数组长度为0或等于"unknown",那么:
     10 ip = request.getHeader("HTTP_CLIENT_IP")
     11     可伪造
     12 5)如果该值为空或数组长度为0或等于"unknown",那么:
     13 ip = request.getRemoteAddr()
     14     可对于匿名代理服务器,可隐匿原始ip,参考附录B
     15  
     16 之所以搞这么麻烦,是因为存在很多种网络结构,如 Nginx+Resin、Apache+WebLogic、Squid+Nginx。下面挨个儿讲一下。
     17 郑昀 :△
     18 首先,明确一下,Nginx 配置一般如下所示:
     19               location / {
     20                        proxy_pass       http://yourdomain.com;
     21                        proxy_set_header   Host             $host;
     22                        proxy_set_header   X-Real-IP        $remote_addr;
     23                        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
     24               }
     25 注意看红色字体,这些配置与下面的闯关拿IP有关。
     26  
     27 ———————————————————————————————
     28 ——第一关|X-Forwarded-For :背景——
     29 这是一个 Squid 开发的字段,并非 RFC 标准。
     30 简称 XFF 头,只有在通过了 HTTP 代理或者负载均衡服务器时才会添加该项。在 Squid 开发文档中可以找到该项的详细介绍。
     31 XFF 格式如下:
     32 X-Forwarded-For: client1, proxy1, proxy2
     33 可以看出,XFF 头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡服务器的ip地址。
     34  
     35 ——第一关|X-Forwarded-For :场景=客户端--CDN--Nginx——
     36 当用户请求经过 CDN 后到达 Nginx 负载均衡服务器时,其 XFF 头信息应该为 “客户端IP,CDN的IP”。
     37 一般情况下CDN服务商出于自身安全考虑会将屏蔽CDN的ip,只保留客户端ip。
     38 那么请求头到达 Nginx 时:
     39 
     40     * 在默认情况下,Nginx 并不会对 XFF 头做任何处理
     41     * 
     42         * 此时 Nginx 后面的 Resin/Apache/Tomcat 通过 request.getHeader("X-FORWARDED-FOR") 获得的ip仍然是原始ip。
     43 
     44     * 当 Nginx 设置 X-Forwarded-For 等于 $proxy_add_x_forwarded_for 时:
     45     * 
     46         * 如果从CDN过来的请求没有设置 XFF 头(通常这种事情不会发生),XFF 头为 CDN 的ip
     47         * 
     48             * 此时相对于 Nginx 来说,客户端就是 CDN 
     49 
     50         * 如果 CDN 设置了 XFF 头,我们这里又设置了一次,且值为$proxy_add_x_forwarded_for 的话:
     51         * 
     52             * XFF 头为“客户端IP,Nginx负载均衡服务器IP”,这样取第一个值即可
     53             * 这也就是大家所常见的场景!
     54 
     55 
     56 
     57 综上所述,XFF 头在上图的场景,Resin 通过 request.getHeader("X-FORWARDED-FOR") 获得的ip字符串,做一个split,第一个元素就是原始ip。
     58 那么,XFF 头可以伪造吗?
     59  
     60 ——第一关|X-Forwarded-For :伪造——
     61 可以伪造。
     62 XFF 头仅仅是 HTTP Headers 中的一分子,自然是可以随意增删改的。如附录A所示。
     63 很多投票系统都有此漏洞,它们简单地取 XFF 头中定义的ip地址设置为来源地址,因此第三方可以伪造任何ip投票。
     64  
     65 ———————————————————————————————
     66 ——第二和第三关|Proxy-Client-IP/WL-Proxy-Client-IP :背景——
     67 Proxy-Client-IP 字段和 WL-Proxy-Client-IP 字段只在 Apache(Weblogic Plug-In Enable)+WebLogic 搭配下出现,其中“WL” 就是 WebLogic 的缩写。
     68 即访问路径是:
     69 Client -> Apache WebServer + Weblogic http plugin -> Weblogic Instances
     70 所以这两关对于我们来说仅仅是兼容而已,怕你突然把 Nginx+Resin 换成 Apache+WebLogic 。
     71 也可以直接忽略这两个字段。
     72  
     73 ———————————————————————————————
     74 ——第四关|HTTP-Client-IP :背景——
     75 HTTP_CLIENT_IP 是代理服务器发送的HTTP头。
     76 很多时候 Nginx 配置中也并没有下面这项:
     77 proxy_set_header HTTP_CLIENT_IP $remote_addr;
     78 所以本关也可以忽略。
     79 郑昀 :△
     80 ———————————————————————————————
     81 ——第五关| request.getRemoteAddr() :背景——
     82 从 request.getRemoteAddr() 函数的定义看:
     83     Returns the Internet Protocol (IP) address of the client or last proxy that sent the request. 
     84 实际上,REMOTE_ADDR 是客户端跟服务器“握手”时的IP,但如果使用了“匿名代理”,REMOTE_ADDR 将显示代理服务器的ip,或者最后一个代理服务器的ip。请参考附录B。 
     85  
     86 综上,
     87 java/php 里拿到的ip地址可能是伪造的或代理服务器的ip。
     88  
     89 郑昀 :△
     90 +++附录A XFF 与 Nginx 配置的测试用例+++
     91 测试环境: nginx+resin
     92 内网IP:172.16.100.10
     93 客户端IP:123.123.123.123
     94 
     95 测试页面: test.jsp
     96 <%
     97 out.println("x-forwarded-for: " + request.getHeader("x-forwarded-for"));
     98 out.println("remote hosts: " + request.getRemoteAddr());
     99 %>
    100 
    101 nginx 配置一
    102 proxy_set_header X-Real-IP $remote_addr;
    103 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    104  
    105 wget测试
    106 wget -O aa --header="X-Forwarded-For:192.168.0.1" "http://test.com/test.jsp"
    107 页面返回结果:
    108 x-forwarded-for: 192.168.0.1, 123.123.123.123
    109 remote hosts: 172.16.100.10
    110  
    111 curl测试
    112 curl -H "X-Forwarded-For:192.168.0.1" "http://test.com/test.jsp"
    113 x-forwarded-for: 192.168.0.1, 123.123.123.123
    114 remote hosts: 172.16.100.10
    115 
    116 nginx 配置二
    117 proxy_set_header X-Real-IP $remote_addr;
    118 proxy_set_header X-Forwarded-For $remote_addr;
    119 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    120 
    121 wget测试:
    122 wget -O aa --header="X-Forwarded-For:192.168.0.1" "http://test.com/test.jsp"
    123 页面返回结果:
    124 x-forwarded-for: 123.123.123.123
    125 remote hosts: 172.16.100.10
    126 
    127 curl测试
    128 curl -H "X-Forwarded-For:192.168.0.1" "http://test.com/test.jsp"
    129 x-forwarded-for: 123.123.123.123
    130 remote hosts: 172.16.100.10
    131 
    132 测试结果:
    133 1、配置  
    134 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    135 增加了一个真实ip X-Forwarded-For,并且顺序是增加到了“后面”。
    136 
    137 2、配置  
    138 proxy_set_header X-Forwarded-For $remote_addr;
    139 清空了客户端伪造传入的X-Forwarded-For,
    140 保证了使用 request.getHeader("x-forwarded-for") 获取的ip为真实ip,
    141 或者用“,”分隔,截取 X-Forwarded-For 最后的值。
    142  
    143 +++附录B 搜狗浏览器高速模式的测试用例+++
    144 访问路径:
    145 搜狗浏览器“高速”模式(即使用代理)-->LVS-->Apache
    146 获得的值为:
    147 x-forwarded-for:180.70.92.43   (即真实ip)
    148 Proxy-Client-IP:null
    149 WL-Proxy-Client-IP:null 
    150 getRemoteAddr:123.126.50.185  (即搜狗代理ip)
    151  
    152  
    153 ×××参考资源:×××
    154 1,http://bbs.linuxtone.org/thread-9050-1-1.html
    155 2,http://hi.baidu.com/thinkinginlamp/item/e2cf05263eb4d18e6e2cc3e6
    156 3,http://bbs.chinaunix.net/thread-3659453-1-1.html
    157 
    158 
    159 
    160 
    161 
    162 转自:http://www.cnblogs.com/zhengyun_ustc/archive/2012/09/19/getremoteaddr.html
  • 相关阅读:
    HDU 1525
    kmp模板
    hdu 4616 Game(树形DP)
    hdu 4619 Warm up 2(并查集活用)
    hdu 4614 Vases and Flowers(线段树加二分查找)
    Codeforces 400D Dima and Bacteria(并查集最短路)
    poj 2823 Sliding Window (单调队列)
    hdu 2196 Computer(树形dp)
    hdu 4604 Deque
    最短路径
  • 原文地址:https://www.cnblogs.com/live365wang/p/2940005.html
Copyright © 2011-2022 走看看