获取用户原始IP地址

转载于:http://www.cnblogs.com/chengmo/archive/2013/05/29/php.html


 

  • 分析过程

这个来自一些项目中,获取用户Ip,进行用户操作行为的记录,是常见并且经常使用的。 一般朋友,都会看到如下通用获取IP地址方法。

function getIP() { 
	if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 
		$realip = $_SERVER['HTTP_X_FORWARDED_FOR']; 
	} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { 
		$realip = $_SERVER['HTTP_CLIENT_IP']; 
	} else { 
		$realip = $_SERVER['REMOTE_ADDR']; 
		} 
		return $realip; 
	}
 
  

这个是网上常见获取,ip函数,用这些值获取IP,我们首先要弄清楚,这些数据是从那个地方传过来的。

  • IP获取来源

1.’REMOTE_ADDR’  是远端IP,默认来自tcp 连接是,客户端的Ip。可以说,它最准确,确定是,只会得到直接连服务器客户端IP。如果对方通过代理服务器上网,就发现。获取到的是代理服务器IP了。

如:a->b(proxy)->c  ,如果c 通过’REMOTE_ADDR’ ,只能获取到b的IP,获取不到a的IP了。

另外:该IP想篡改将很难实现,在传递知道生成php server值,都是直接生成的。

2.’HTTP_X_FORWARDED_FOR’,’HTTP_CLIENT_IP’ 为了能在大型网络中,获取到最原始用户IP,或者代理IP地址。对HTTp协议进行扩展。定义了实体头。

HTTP_X_FORWARDED_FOR = clientip,proxy1,proxy2  所有IP用”,”分割。 HTTP_CLIENT_IP 在高级匿名代理中,这个代表了代理服务器IP。既然是http协议扩展一个实体头,并且这个值对于传入端是信任的,信任传入方按照规则格式输入的。以下以x_forword_for例子加以说明,正常情况下,这个值变化过程。

image

 

  • 分析Bug风险点:

通过刚刚分析我们发现,其实这些变量,来自http请求的:x-forword-for字段,以及client-ip字段。 正常代理服务器,当然会按rfc规范来传入这些值。但是,当一个用户直接构造该x-forword-for值,发送给用户用户,那将会怎么样呢?

image图(1)

第2步,修改x-forword-fox值,我们看看结果

image

 

第三步,我们再修改下看看会怎么样?

image

 

哈哈,看到上面结果没,x-forwarded-for不光可以自己设置值,而且可以设置任意格式值。 这样一来,好比就直接有一个可以写入任意值的字段。并且服务器直接读取,或者写入数据库,或者做显示。它将带来危险性,跟一般对入输入没有做任何过滤检测,之间操作数据源结果一样。 并且容易带来隐蔽性。

  • 结论:

上面getip函数,除了客户端可以任意伪造IP,并且可以传入任意格式IP。 这样结果会带来2大问题,其一,如果你设置某个页面,做IP限制。 对方可以容易修改IP不断请求该页面。 其二,这类数据你如果直接使用,将带来SQL注册,跨站攻击等漏洞。至于其一,可以在业务上面做限制,最好不采用IP限制。 对于其二,这类可以带来巨大网络风险。我们必须加以纠正。

需要对getip 进行修改,得到安全的getip函数。

这类问题,其实很容易出现,以前我就利用这个骗取了大量伪装投票。有它的隐蔽性,其实只要我们搞清楚了,某些值来龙去脉的话。理解了它的原理,修复该类bug将是非常容易。

题外话,做技术,有三步,先要会做,会解决;后要思考为什么要这么做,原因原理是什么;最后是怎么样做,有没有其它方法。多问问自己,你发现距离技术真理越来越近。你做事会越来越得心应手的!

作者:chengmo  QQ:8292669 
原文网址:http://blog.chacuo.net/98.html 
订阅保持关注:http://blog.chacuo.net/feed 
本文版权归作者所有,欢迎转载,请务必添加原文链接。


### 如何在Java Web应用程序中获取用户的实际IP地址 为了获得访问Web应用的客户端的实际IP地址,在Java中有几种方法可以实现这一点。通常情况下,当请求通过代理服务器或负载均衡器转发时,`request.getRemoteAddr()`可能不会返回真实的客户端IP地址,而是返回最后一个处理该请求的代理服务器的IP地址。 一种常用的方式是从HTTP头信息中读取特定字段来确定真实IP地址。常见的头部名称有 `X-Forwarded-For` 或者 `X-Real-IP` 。下面是一个简单的例子展示如何尝试从这些头部获取用户的真实IP: ```java public String getUserIp(HttpServletRequest request) { String ip; // 尝试从 X-Forwarded-For 获取第一个非未知的 IP 地址 ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } // 如果存在多个IP,则只保留最左边的一个作为原始发起者的IP if (ip != null && !ip.isEmpty()) { int commaIndex = ip.indexOf(','); if (commaIndex > 0) { ip = ip.substring(0, commaIndex); } } return ip; } ``` 上述代码片段展示了如何遍历不同的HTTP头部以找到最有可能代表最终用户设备的真实公共IPv4/IPv6地址的信息[^1]。 值得注意的是,由于网络配置的不同以及中间件的存在形式各异,以上逻辑并不能保证适用于所有的部署环境;因此建议开发者依据具体的生产环境中使用的基础设施调整此函数的行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值