84669 person learning
152542 person learning
20005 person learning
5487 person learning
7821 person learning
359900 person learning
3350 person learning
180660 person learning
48569 person learning
18603 person learning
40936 person learning
1549 person learning
1183 person learning
32909 person learning
如上图,是我测试的一段代码访问一个IP查询服务的服务,可以看出,可以任何伪造ip地址!
当前正在做的一个PHP项目,需要验证用户的IP地址是否在授权范围中,请问有什么方法可以避免用户伪造IP?
或者,是否能提供一个其他思路?
补充:实际场景为rest调用,调用和被调用端都为服务器~
闭关修行中......
提供几个思路:
再说你评论的那个方案,其实是一种验证的手段,我倒是觉得,这种手段和对称加密没什么两样,当然对称加密成本要比你说的握手方式成本低很多。
总之,限制IP是为了做访问限制,而为了数据安全,还是要做加密和身份验证,对称加密是个好办法(对称加密中加入时间等元素,安全性一般比较高)。
REMOTE_ADDR 没那么容易伪造. 请参见 Can $_SERVER['REMOTE_ADDR'] be trusted?http://stackoverflow.com/questions/58...
"HTTP_" 开头的$_SERVER很容易伪造.
服务段判断还是挺容易的. 其实下面这个代码也是判断是否使用proxy.
<?php if ( $_SERVER['HTTP_X_FORWARDED_FOR'] || $_SERVER['HTTP_X_FORWARDED'] || $_SERVER['HTTP_FORWARDED_FOR'] || $_SERVER['HTTP_CLIENT_IP'] || $_SERVER['HTTP_VIA'] || in_array($_SERVER['REMOTE_PORT'], array(8080,80,6588,8000,3128,553,554))) || @fsockopen($_SERVER['REMOTE_ADDR'], 80, $errno, $errstr, 30)) { echo "we caught you"; } ?>
结论:服务段最好只取$_SERVER['REMOTE_ADDR']
------------------------小插曲--------------------- 最近帮人研究一下discuz的xplus投票系统.
function _get_client_ip() { $clientip = ''; if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) { $clientip = getenv('HTTP_CLIENT_IP'); } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) { $clientip = getenv('HTTP_X_FORWARDED_FOR'); } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) { $clientip = getenv('REMOTE_ADDR'); } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) { $clientip = $_SERVER['REMOTE_ADDR']; } preg_match("/[\d\.]{7,15}/", $clientip, $clientipmatches); $clientip = $clientipmatches[0] ? $clientipmatches[0] : 'unknown'; return $clientip; }
呵呵...
"X-FORWARDED-FOR" 是代理服务器通过 HTTP Headers 提供的客户端IP。代理服务器可以伪造任何IP。
要防止伪造,不要读这个IP即可(同时告诉用户不要用HTTP 代理)。
如果是PHP,$_SERVER['REMOTE_ADDR'] 就是跟你服务器直接连接的IP,用这个就可以了。
我也试过这个,不止是X-FORWARDED-FOR,也可以伪造CLIENT_IP的请求头,看你的脚本如何取请求头的key, 好像就REMOTE_ADDR没办法伪造,可以取这个吧,PHP下是$_SERVER['REMOTE_ADDR'],不知道会不会存在空值的情况。
想完全避免近乎不可能,透明和匿名http代理还能检测http头,但是socks代理呢,或者自己实现的端口转发呢? 现在能想到的就是维护一个巨大的库,把所有能搜集到的可能是代理的ip加进去,用户访问之前先进库对比。但是这样缺点也很大,一是库太大了访问速度会变慢,影响效率;二是有些ip可能只是暂时是代理,比如肉鸡,可能会恢复正常,比如营运商动态分配的ip,今天我用时做代理,明天分配到你那里就可能不是代理了,如果没有一个很好的检测剔除机制,很可能误杀;三是库不可能把所有代理都收进去,只能尽可能搜集一些互联网上公开的代理,私有代理很难收集到,这些库之外的代理还是没法避免他们访问。 不过目前有公司确实在维护这样的库,对外以api的方式提供服务。
提供几个思路:
再说你评论的那个方案,其实是一种验证的手段,我倒是觉得,这种手段和对称加密没什么两样,当然对称加密成本要比你说的握手方式成本低很多。
总之,限制IP是为了做访问限制,而为了数据安全,还是要做加密和身份验证,对称加密是个好办法(对称加密中加入时间等元素,安全性一般比较高)。
REMOTE_ADDR 没那么容易伪造.
请参见
Can $_SERVER['REMOTE_ADDR'] be trusted?
http://stackoverflow.com/questions/58...
"HTTP_" 开头的$_SERVER很容易伪造.
服务段判断还是挺容易的. 其实下面这个代码也是判断是否使用proxy.
结论:服务段最好只取$_SERVER['REMOTE_ADDR']
------------------------小插曲---------------------
最近帮人研究一下discuz的xplus投票系统.
呵呵...
"X-FORWARDED-FOR" 是代理服务器通过 HTTP Headers 提供的客户端IP。代理服务器可以伪造任何IP。
要防止伪造,不要读这个IP即可(同时告诉用户不要用HTTP 代理)。
如果是PHP,$_SERVER['REMOTE_ADDR'] 就是跟你服务器直接连接的IP,用这个就可以了。
我也试过这个,不止是X-FORWARDED-FOR,也可以伪造CLIENT_IP的请求头,看你的脚本如何取请求头的key, 好像就REMOTE_ADDR没办法伪造,可以取这个吧,PHP下是$_SERVER['REMOTE_ADDR'],不知道会不会存在空值的情况。
想完全避免近乎不可能,透明和匿名http代理还能检测http头,但是socks代理呢,或者自己实现的端口转发呢?
现在能想到的就是维护一个巨大的库,把所有能搜集到的可能是代理的ip加进去,用户访问之前先进库对比。但是这样缺点也很大,一是库太大了访问速度会变慢,影响效率;二是有些ip可能只是暂时是代理,比如肉鸡,可能会恢复正常,比如营运商动态分配的ip,今天我用时做代理,明天分配到你那里就可能不是代理了,如果没有一个很好的检测剔除机制,很可能误杀;三是库不可能把所有代理都收进去,只能尽可能搜集一些互联网上公开的代理,私有代理很难收集到,这些库之外的代理还是没法避免他们访问。
不过目前有公司确实在维护这样的库,对外以api的方式提供服务。