说一哈,我也是转来的,不是想骗PV,方便自己查而已!

目前网上流行的所谓"取真实IP地址"的方法,都有bug,没有考虑到多层透明代理的情况。 
多数代码类似:

string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null 
&& HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] !=String.Empty) 
?HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] 
:HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

事实上,上面的代码只试用与用户只使用了1层代理,如果用户有2层,3层HTTP_X_FORWARDED_FOR 的值是:"本机真实IP,1层代理IP,2层代理IP,....." ,如果这个时候你的数据中保存IP字段的长度很小(15个字节),数据库就报错了。

实际应用中,因为使用多层透明代理的情况比较少,所以这种用户并不多。

其他应用情况,现在越来越多的网站使用了代理加速方式,比如 新浪、SOHU的新闻 都使用Squid做代理方式,利用多台服务器分流。Squid本身类似透明代理,会发送"HTTP_X_FORWARDED_FOR" ,HTTP_X_FORWARDED_FOR 中包括客户的IP地址,如果此时客户已经使用了一层透明代理,那么程序取的 "HTTP_X_FORWARDED_FOR" 就包括两个IP地址。(我遇到过3个IP地址的情况,4个的未遇到过)

所以取"真正"IP地址的方式,还应该判断 "HTTP_X_FORWARDED_FOR" 中是否有","逗号,或者长度是否超长(超过15字节 xxx.xxx.xxx.xxx)。

所以代码应该如下:

  1. /**//// <summary>
  2. /// 取得客户端真实IP。如果有代理则取第一个非内网地址
  3. /// </summary>
  4. public static string IPAddress
  5. {
  6. get
  7. {
  8. string result = String.Empty;
  9. result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
  10. if(result!=null&&result!= String.Empty)
  11. {
  12. //可能有代理
  13. if(result.IndexOf(".")==-1)    //没有"."肯定是非IPv4格式
  14. result = null;
  15. else
  16. {
  17. if(result.IndexOf(",")!=-1)
  18. {
  19. //有",",估计多个代理。取第一个不是内网的IP。
  20. result = result.Replace(" ","").Replace(""","");
  21. string[] temparyip = result.Split(",;".ToCharArray());
  22. for(int i=0;i<temparyip.Length;i++)
  23. {
  24. if( Text.IsIPAddress(temparyip[i])
  25. && temparyip[i].Substring(0,3)!="10."
  26. && temparyip[i].Substring(0,7)!="192.168"
  27. && temparyip[i].Substring(0,7)!="172.16.")
  28. {
  29. return temparyip[i];    //找到不是内网的地址
  30. }
  31. }
  32. }
  33. else if(Text.IsIPAddress(result)) //代理即是IP格式
  34. return result;
  35. else
  36. result = null;    //代理中的内容 非IP,取IP
  37. }
  38. }
  39. string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] !=String.Empty)?HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]:HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
  40. if (null == result || result == String.Empty)
  41. result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
  42. if (result == null || result == String.Empty)
  43. result = HttpContext.Current.Request.UserHostAddress;
  44. return result;
  45. }
  46. }

取"HTTP_X_FORWARDED_FOR" 的弊端。

HTTP_X_FORWARDED_FOR 是HTTP协议中头的一部分,不影响TCP的通讯。也就是说实际上客户端可以发送任意内容的 HTTP_X_FORWARDED_FOR,以就是伪造IP。最简单的是WEB程序的IP记录,本来是要记录真实IP的,反而被"黑客"欺骗。当你的应用程序记录客户的访问IP、拒绝或允许部分IP的访问、错误日志 都会出错,甚至误杀。

因此必要的安全日志应该记录 完整的 "HTTP_X_FORWARDED_FOR" (至少给数据库中的字段分配 3*15+2 个字节,以记录至少3个IP) 和 "REMOTE_ADDR"。对 HTTP_X_FORWARDED_FOR 的IP格式检查也是不可少的。

附:(Text是我自定义的一个类,IsIPAddress是其中的一个判断是否是IP地址格式的方法)

  1. #region bool IsIPAddress(str1) 判断是否是IP格式
  2. /**//// <summary>
  3. /// 判断是否是IP地址格式 0.0.0.0
  4. /// </summary>
  5. /// <param name="str1">待判断的IP地址</param>
  6. /// <returns>true or false</returns>
  7. public static bool IsIPAddress(string str1)
  8. {
  9. if(str1==null||str1==string.Empty||str1.Length<7||str1.Length>15) return false;
  10. string regformat = @"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$";
  11. Regex regex = new Regex(regformat,RegexOptions.IgnoreCase );
  12. return regex.IsMatch(str1);
  13. }
  14. #endregion

C#取真实IP地址及分析的更多相关文章

  1. 穿过代理服务器取远程用户真实IP地址

    public static string GetIP() { string str = ""; //穿过代理服务器取远程用户真实IP地址: if (System.Web.HttpC ...

  2. 查找“CDN、负载均衡、反向代理”等大型网络真实IP地址的方法

    首先,CDN.负载均衡.反向代理还分为很多层,有时查出来的是最外层的 CDN 服务器群,真实的机器是不对外开放的,类似这样的: 用户 → CDN 网络 → 一台或多台真实机器 ↗ CDN Server ...

  3. CDN下nginx获取用户真实IP地址

    随着nginx的迅速崛起,越来越多公司将apache更换成nginx. 同时也越来越多人使用nginx作为负载均衡, 并且代理前面可能还加上了CDN加速,但是随之也遇到一个问题:nginx如何获取用户 ...

  4. 多级反向代理下,Java获取请求客户端的真实IP地址多中方法整合

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  5. Java获取客户端真实IP地址的两种方法

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  6. php获取真实ip地址(转)

    REMOTE_ADDR只能获取访问者本地连接中设置的IP,如中南民族大学校园网中自己设置的10.X.XXX.XXX系列IP,而这个函数获取的是局域网网关出口的IP地址, 如果访问者使用代理服务器,将不 ...

  7. 获得用户的真实IP地址

    /** * 获得用户的真实IP地址 * * @access public * @return string */if (!function_exists('get_real_ip')){ functi ...

  8. JSP 获取真实IP地址的代码

    [转载]JSP 获取真实IP地址的代码 JSP 获取真实IP地址的代码 在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.   ...

  9. Java获取请求客户端的真实IP地址

    整理网友的材料,最后有源码,亲测能解决所有java获取IP真实地址的问题 整理的这里: 1.链接1 2.链接2 JSP里,获取客户端的IP地址的方法是: request.getRemoteAddr() ...

随机推荐

  1. Python 异常相关参考

    Python所有的异常都是从BaseException类派生的,常见的错误类型和继承关系如下: BaseException +-- SystemExit +-- KeyboardInterrupt + ...

  2. 【LeetCode】102 - Binary Tree Level Order Traversal

    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...

  3. MVC&amp;&amp;MVP

    Classic MVC Classic MVC 大概上世纪七十年代,Xerox PARC的Trygve提出了MVC的概念. 并应用在Smalltalk系统中,为了和其它类型的MVC加以区分,历史上习惯 ...

  4. 学习内容:Html5+Axure原型设计

    今日主要在http://www.runoob.com/html/html5-intro.html和http://www.imooc.com/learn/9网站上学习Html的知识,head.title ...

  5. HW7.18

    public class Solution { public static void main(String[] args) { int[][] m = {{1, 2}, {3, 4}, {5, 6} ...

  6. 阿里云存储OSS之九大使用技巧

    http://www.biphp.com/cloud-computing/%E9%98%BF%E9%87%8C%E4%BA%91%E5%AD%98%E5%82%A8oss%E4%B9%8B%E4%B9 ...

  7. 在RHEL5.4下安装ORACLE11G

    以root身份登录到系统,新增组和用户: #groupadd oinstall #groupadd dba #useradd -g oinstall -G dba oracle #passwd ora ...

  8. windows服务安装及卸载

    1)安装脚本Install.bat%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe JobSchedule.exeNet ...

  9. HDU 5821 Ball (排序)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5821 有n个盒子,每个盒子最多装一个球. 现在进行m次操作,每次操作可以将l到r之间盒子的球任意交换. ...

  10. POJ3185(简单BFS,主要做测试使用)

    没事做水了一道POJ的简单BFS的题目 这道题的数据范围是20,所以状态总数就是(1<<20) 第一次提交使用STL的queue,并且是在队首判断是否达到终点,达到终点就退出,超时:(其实 ...