如何获取网站用户的真实IP

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取网站用户的真实IP相关的知识,希望对你有一定的参考价值。

参考技术A

问题引出:

<hr/>

在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。但是在通过了 Apache,Nagix等反向代理软件就不能获取到客户端的真实IP地址了。如果使用了反向代理软件,用 request.getRemoteAddr()方法获取的IP地址是:127.0.0.1或 192.168.1.110,而并不是客户端的真实IP。

经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的 IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端 IP地址和原来客户端请求的服务器地址。

举例来说,当我们访问口碑网首页hangzhou.jsp时,其实并不是我们浏览器真正访问到了服务器上的hangzhou.jsp 文件,而是先由代理服务器Nagix去访问hagnzhou.jsp ,代理服务器再将访问到的结果返回给我们的浏览器,因为是代理服务器去访问hangzhou.jsp的,所以hangzhou.jsp中通过 request.getRemoteAddr()的方法获取的IP实际上是代理服务器的地址,并不是客户端的IP地址。

<hr/>

获得客户端真实IP地址的方法一:

public String getRemortIP(HttpServletRequest request) 

if (request.getHeader("x-forwarded-for") == null) 

return request.getRemoteAddr();

return request.getHeader("x-forwarded-for");

<hr/>


获得客户端真实IP地址的方法二


public String getIpAddr(HttpServletRequest request) 

String ip = request.getHeader("x-forwarded-for");

if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 

ip = request.getHeader("Proxy-Client-IP");

if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 

ip = request.getHeader("WL-Proxy-Client-IP");

if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 

ip = request.getRemoteAddr();

return ip;

<hr/>

获取真实ip的报告

今天登录九秒社团 http://www.9miao.com/的时候忘记了用户名和密码,尝试了5次都没登录成功,网站弹出提示15分钟后才能再次登录。我纳闷它是怎么判断用户的登录次数,这时候用户还没有登录成功,获取不到userid的,那么也就是后台也不知道“登录者到底是谁”?(清除localStorage后,也还是提示15分钟后登录,当然我没有清cookie,九秒网站也不会这么做)。我所能想到的只有是根据ip来确定登录者的登录次数了,然后就想用代理服务器来蒙混过关,就有了下面的实验。

九秒是能够透过透明服务器获取用户ip的,所以要用匿名/高匿代理服务器才能跳过"15分钟后再登录"的关卡,事实也证明了这一点。

 

程序代码

 1 <?php
 2     //真实ip
 3      function getip() {
 4         $unknown = ‘unknown‘;
 5         if (isset($_SERVER[‘HTTP_X_FORWARDED_FOR‘]) && $_SERVER[‘HTTP_X_FORWARDED_FOR‘] && strcasecmp($_SERVER[‘HTTP_X_FORWARDED_FOR‘], $unknown)) {
 6             $ip = $_SERVER[‘HTTP_X_FORWARDED_FOR‘];
 7         }
 8         elseif(isset($_SERVER[‘REMOTE_ADDR‘]) && $_SERVER[‘REMOTE_ADDR‘] && strcasecmp($_SERVER[‘REMOTE_ADDR‘], $unknown)) {
 9             $ip = $_SERVER[‘REMOTE_ADDR‘];
10         }
11         /**
12             处理多层代理的情况 
13             或者使用正则方式:$ip = preg_match("/[\d\.]{7,15}/", $ip, $matches) ? $matches[0] : $unknown; 
14         ***/
15         if (false !== strpos($ip, ‘,‘)){ $ip = reset(explode(‘,‘, $ip)); }
16         return $ip;
17     } 
18     echo getip();
19 ?>

实验1:没有使用代理服务器情况下
  http://ip.chinaz.com/ 的显示结果是 【您来自:219.147.15.232 所在区域:山东省青岛市 电信】
  http://ip.cn/ 的显示结果是 【当前 IP:219.147.15.232 来自:山东省青岛市 电信】
  http://www.ip138.com/ 的显示结果是 【本机IP: 219.147.15.232山东省青岛市 电信】
  程序代码显示结果是 219.147.15.232

  结论:程序代码正确获得了用户主机ip

 

实验2使用 36.250.69.4:80 透明代理服务器的情况下
  http://ip.chinaz.com/ 的显示结果是 【您来自:219.147.15.232 所在区域:山东省青岛市 电信】
  http://ip.cn/ 的显示结果是 【当前 IP:36.250.69.4 来自:福建省厦门市 联通】
  http://www.ip138.com/ 的显示结果是 【您的IP是:[36.250.69.4] 来自:福建省厦门市 联通】
  程序代码显示结果是 219.147.15.232

  结论:程序代码能透过透明代理服务器获取到用户的真实ip(还是ip.chinaz.com比较专业一些)

实验3:使用 61.135.217.10:80 匿名代理服务器的情况下
  http://ip.chinaz.com/ 的显示结果是 【您来自:61.135.217.10 所在区域:北京市 联通互联网数据中心】
  http://ip.cn/ 的显示结果是 【当前 IP:61.135.217.10 来自:北京市 联通】
  http://www.ip138.com/ 的显示结果是 【您的IP是:[61.135.217.10] 来自:北京市北京市 联通】
  程序代码显示结果是 61.135.217.10

  结论:程序代码能不能透过匿名代理服务器获取到用户的真实ip

 

实验4:使用 1.69.186.141:8888 高匿代理服务器的情况下
  http://ip.chinaz.com/ 的显示结果是 【您来自:1.69.186.141 所在区域:山西省 G】
  http://ip.cn/ 的显示结果是 【当前 IP:1.69.186.141 来自:山西省运城市 电信】
  http://www.ip138.com/ 的显示结果是 【您的IP是:[1.69.186.141] 来自:山西省运城市 电信】
  程序代码显示结果是 1.69.186.141

  结论:程序代码能不能透过高匿代理服务器获取到用户的真实ip

总结:

在PHP获取客户端IP中常使用 $_SERVER["REMOTE_ADDR"] 。
(1) 但如果客户端是使用代理服务器来访问,那取到的是代理服务器的 IP 地址,而不是真正的客户端 IP 地址。要想透过代理服务器取得客户端的真实 IP 地址,就要使用 $_SERVER["HTTP_X_FORWARDED_FOR"] 来读取。
(2) 但只有客户端使用“透明代理”的情况下,$_SERVER["HTTP_X_FORWARDED_FOR"] 的值才是客户端真正的IP(如果是多层代理,该值可能是由客户端真正IP和多个代理服务器的IP组成,由逗号“,”分隔)。
(3) 而在“匿名代理”、“高匿名”的情况下是代理服务器的IP值(如果是多层代理,该值可能由多个代理服务器的IP组成,由逗号“,”分隔)。

扩展:

如果从隐藏使用代理用户的级别上划分,代理可以分为三种,即高度匿名代理、普通匿名代理和透明代理。 
(1)高度匿名代理不改变客户机的请求,这样在服务器看来就像有个真正的客户浏览器在访问它,这时客户的真实IP是隐藏的,服务器端不会认为我们使用了代理。 
(2)普通匿名代理能隐藏客户机的真实IP,但会改变我们的请求信息,服务器端有可能会认为我们使用了代理。不过使用此种代理时,虽然被访问的网站不能知道你的ip地址,但仍然可以知道你在使用代理,当然某些能够侦测ip的网页仍然可以查到你的ip。 
(3)透明代理,它不但改变了我们的请求信息,还会传送真实的IP地址。 
三者隐藏使用代理者身份的级别依次为高度匿名代理最隐蔽,其次是普通匿名代理,最差的是透明代理。

以上是关于如何获取网站用户的真实IP的主要内容,如果未能解决你的问题,请参考以下文章

如何在CloudFlare下Nginx实现访客真实IP网站日志?

获取CDN用户真实IP

nginx如何获取自己的ip

服务器架构前面加了防火墙,Nginx如何获取客户端真实ip???

如何在 php 中获取真实的客户端 IP 或地理位置?

java如何获取用户真实的ip