转载自:http://www.cnblogs.com/lmule/archive/2010/10/15/1852020.html

看ecshop的lib_base.php的时候里面获取客户端真实ip的函数(real_ip),有许多情况的判断,主要判断客户端是否使用代理的情况,注意判断顺序,先判断客户端是否使用代理HTTP_X_FORWARDED_FOR

还是把源码附上吧

  1. <?php
  2. /**
  3. * 获得用户的真实IP地址
  4. *
  5. * @access  public
  6. * @return  string
  7. */
  8. function real_ip()
  9. {
  10. static $realip = NULL;
  11. if ($realip !== NULL)
  12. {
  13. return $realip;
  14. }
  15. if (isset($_SERVER))
  16. {
  17. if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
  18. {
  19. $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  20. /* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */
  21. foreach ($arr AS $ip)
  22. {
  23. $ip = trim($ip);
  24. if ($ip != 'unknown')
  25. {
  26. $realip = $ip;
  27. break;
  28. }
  29. }
  30. }
  31. elseif (isset($_SERVER['HTTP_CLIENT_IP']))
  32. {
  33. $realip = $_SERVER['HTTP_CLIENT_IP'];
  34. }
  35. else
  36. {
  37. if (isset($_SERVER['REMOTE_ADDR']))
  38. {
  39. $realip = $_SERVER['REMOTE_ADDR'];
  40. }
  41. else
  42. {
  43. $realip = '0.0.0.0';
  44. }
  45. }
  46. }
  47. else
  48. {
  49. if (getenv('HTTP_X_FORWARDED_FOR'))
  50. {
  51. $realip = getenv('HTTP_X_FORWARDED_FOR');
  52. }
  53. elseif (getenv('HTTP_CLIENT_IP'))
  54. {
  55. $realip = getenv('HTTP_CLIENT_IP');
  56. }
  57. else
  58. {
  59. $realip = getenv('REMOTE_ADDR');
  60. }
  61. }
  62. preg_match("/[\d\.]{7,15}/", $realip, $onlineip);
  63. $realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';
  64. return $realip;
  65. }
  66. ?>

顺便说下$_SERVER和getenv的区别,getenv不支持IIS的isapi方式运行的php

一、没有使用代理服务器的情况:

REMOTE_ADDR = 您的 IP
      HTTP_VIA = 没数值或不显示
      HTTP_X_FORWARDED_FOR = 没数值或不显示

二、使用透明代理服务器的情况:Transparent Proxies

REMOTE_ADDR = 最后一个代理服务器 IP
      HTTP_VIA = 代理服务器 IP
      HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。

三、使用普通匿名代理服务器的情况:Anonymous Proxies

REMOTE_ADDR = 最后一个代理服务器 IP
      HTTP_VIA = 代理服务器 IP
      HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。

四、使用欺骗性代理服务器的情况:Distorting Proxies

REMOTE_ADDR = 代理服务器 IP
      HTTP_VIA = 代理服务器 IP
      HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。

五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)

REMOTE_ADDR = 代理服务器 IP
      HTTP_VIA = 没数值或不显示
      HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。

REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。
HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。
$_SERVER['REMOTE_ADDR']; //访问端(有可能是用户,有可能是代理的)IP
$_SERVER['HTTP_CLIENT_IP'];  //代理端的(有可能存在,可伪造)
$_SERVER['HTTP_X_FORWARDED_FOR']; //用户是在哪个IP使用的代理(有可能存在,也可以伪造)

----------------------------------------------------------------------------------------------------

在WEB开发中.我们可能都习惯使用下面的代码来获取客户端的IP地址: 
C#代码

复制代码 代码如下:
//优先取得代理IP 
string IP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; 
if (string.IsNullOrEmpty(IP)) { 
//没有代理IP则直接取连接客户端IP 
IP = Request.ServerVariables["REMOTE_ADDR"]; 
}

上面代码看来起是正常的.可惜这里却隐藏了一个隐患!!因为"HTTP_X_FORWARDED_FOR"这个值是通过获取HTTP头的"X_FORWARDED_FOR"属性取得.所以这里就提供给恶意破坏者一个办法:可以伪造IP地址!! 
下面是测试代码:

复制代码 代码如下:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://localhost/ip.aspx"); 
request.Headers.Add("X_FORWARDED_FOR", "0.0.0.0"); 
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
StreamReader stream = new StreamReader(response.GetResponseStream()); 
string IP = stream.ReadToEnd(); 
stream.Close(); 
response.Close(); 
request = null;

"ip.aspx"文件代码:

复制代码 代码如下:
Response.Clear(); 
//优先取得代理IP 
string IP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; 
if (string.IsNullOrEmpty(IP)) 

//没有代理IP则直接取客户端IP 
IP = Request.ServerVariables["REMOTE_ADDR"]; 

Response.Write(IP); 
Response.End();

这样.当测试代码中去访问ip.aspx文件时."string IP = stream.ReadToEnd();"这段代码取到的IP数据就是"0.0.0.0"!!!!(呵.在真实情况下.这样的IP地址肯定不是我们想要的结果.而在有些投票系统中限制一个IP只能投1次票时,如果也是用类似的代码取得对方IP然后再判断的话.呵呵.限制就失效咯)...

或者如果你用上面代码获取IP地址后后面又不再进行数据判断的话也许还能更进一步进行数据破坏!! 
比如你用类似上面的代码中获取IP地址就直接有这样的SQL语句: 
string sql = "INSERT INTO (IP) VALUE ('" + IP + "')"; 
那么也许破坏者还可以进行SQL注入进行数据破坏!!

这样看来利用"HTTP_X_FORWARDED_FOR"这个属性获取客户端IP的方法就不再可取了.-_-# 但如果不用这种方法.那么那些真正使用了代理服务器的人.我们又不能再获取到他们的真实IP地址(因为某些代理服务器会在"X_FORWARDED_FOR"这个HTTP头里加上访问用户真正的IP地址).呵.现实就是这样,某种东西都有有得必有失...

------------------------------------------------------------------------------------------------------

详解REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR的更多相关文章

  1. nginx通过域名访问项目(不接项目名称),cookie丢失问题详解

    最近搞了个域名,想用它直接去访问Tomcat上部署的项目,开始一直必须加上项目名称,经过短暂配置,成功了. 访问一次,到达登陆页面,结果死活登录不进去,一直在登陆界面,原来是由于cookie丢失,现配 ...

  2. Nginx代理功能与负载均衡详解

    序言 Nginx的代理功能与负载均衡功能是最常被用到的,关于nginx的基本语法常识与配置已在上篇文章中有说明,这篇就开门见山,先描述一些关于代理功能的配置,再说明负载均衡详细. Nginx代理服务的 ...

  3. Nginx配置文件nginx.conf中文详解(转)

    ######Nginx配置文件nginx.conf中文详解##### #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_ ...

  4. Nginx配置文件详解

    Nginx是一款面向性能设计的HTTP服务器,相较于Apache.lighttpd具有占有内存少,稳定性高等优势. ######Nginx配置文件nginx.conf中文详解##### #定义Ngin ...

  5. Nginx主配置参数详解,Nginx配置网站

    1.Niginx主配置文件参数详解 a.上面博客说了在Linux中安装nginx.博文地址为:http://www.cnblogs.com/hanyinglong/p/5102141.html b.当 ...

  6. Nginx中文详解、配置部署及高并发优化

      一.Nginx常用命令: 1. 启动 Nginx          /usr/local/nginx/sbin/nginxpoechant@ubuntu:sudo ./sbin/nginx2. 停 ...

  7. Nginx配置文件(nginx.conf)配置详解(2)

    Nginx的配置文件nginx.conf配置详解如下: user nginx nginx ; Nginx用户及组:用户 组.window下不指定 worker_processes 8; 工作进程:数目 ...

  8. ubuntu nginx 安装以及配置文件详解

    1.到nginx官网下载源码包.最好下载稳定版本,nginx官网http://www.nginx.org/ 2.安装nginx依赖包运行命令: sudo apt-get install libssl- ...

  9. 日志分析工具ELK配置详解

    日志分析工具ELK配置详解 一.ELK介绍 1.1 elasticsearch 1.1.1 elasticsearch介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分 ...

随机推荐

  1. 【转载】Xutils3-Dbutils

    Github源码地址:https://github.com/wyouflf/xUtils3 下面是源码中sample关于Dbutils的使用代码: import android.view.View; ...

  2. (14) go 结构体

    1. 声明一个结构体 2.属性 如果是 指针 切片 map 需要用make 3.赋值 (2) (3) (4) 4. 正确,字段相同,数据类型相同,名字相同 5.

  3. 洛谷P3275 [SCOI2011]糖果 [差分约束系统]

    题目传送门 糖果 题目描述 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比 ...

  4. java _循环练习和数组练习

    练习 1.输出所有的水仙花数,所谓水仙花数是指一个数3位数,其每位数字立方和等于其本身,如153 = 1*1*1 + 3*3*3 + 5*5*5(很经典的题目) 分析: 通过观察发现,本题目要实现打印 ...

  5. 【C++初级】static用法总结、问题探讨及常见错误排查

    static的基本用法: static的作用主要有两种第一个作用是限定作用域:第二个作用是保持变量内容持久化: 一.c语言中static的用法: 1.全局静态变量: 用法:在全局变量前加上关键字sta ...

  6. Bzoj[Usaco2018 Feb]5194 Snow Boots(线段树)

    Description 到冬天了,这意味着下雪了!从农舍到牛棚的路上有N块地砖,方便起见编号为1…N,第i块地砖上积了fi英尺的雪 .在Farmer John的农舍的地窖中,总共有B双靴子,编号为1… ...

  7. lambda 表达式+python内置函数

    #函数 def f1(a,b): retrun  a+b #lambda方式,形参(a,b):返回值(a+b) f2=lambda a,b : a+b 在一些比较简单的过程计算就可以用lambda p ...

  8. hdu 1372Knight Moves

    E - Knight Moves Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Su ...

  9. 「HAOI2015」按位或

    「HAOI2015」按位或 解题思路 : 这类期望题一眼 \(\text{Min-Max}\) 容斥,只需要稍微推一下如何求 \(E(minS)\) 即可. \[ E(minS) = \frac{1} ...

  10. luoguP3978 [TJOI2015]概率论 卡特兰数

    考虑分别求出$f_n, g_n$表示$n$个点的有根二叉树的数量和$n$个点的所有情况下有根二叉树的叶子结点的总数 有$f_n = \sum_{k} f_k * f_{n - 1 - k}$,因此有$ ...