Maison  >  Questions et réponses  >  le corps du texte

php - 如何避免用户访问请求伪造ip

如上图,是我测试的一段代码访问一个IP查询服务的服务,可以看出,可以任何伪造ip地址!

当前正在做的一个PHP项目,需要验证用户的IP地址是否在授权范围中,请问有什么方法可以避免用户伪造IP?

或者,是否能提供一个其他思路?

补充:实际场景为rest调用,调用和被调用端都为服务器~

阿神阿神2771 Il y a quelques jours802

répondre à tous(5)je répondrai

  • 巴扎黑

    巴扎黑2017-04-10 13:13:19

    提供几个思路:

    1. 如果是局域网环境,那么建议你从系统上,甚至路由器上去限制IP
    2. 如果是公开的,伪造IP将无法收到你的Response,也就是说这个Response会发到那个被伪造的IP去。所以,除非是对你做泛洪攻击,伪造IP没有意义。

    再说你评论的那个方案,其实是一种验证的手段,我倒是觉得,这种手段和对称加密没什么两样,当然对称加密成本要比你说的握手方式成本低很多。

    总之,限制IP是为了做访问限制,而为了数据安全,还是要做加密和身份验证,对称加密是个好办法(对称加密中加入时间等元素,安全性一般比较高)。

    répondre
    0
  • 怪我咯

    怪我咯2017-04-10 13:13:19

    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;
    	}

    呵呵...

    répondre
    0
  • PHP中文网

    PHP中文网2017-04-10 13:13:19

    "X-FORWARDED-FOR" 是代理服务器通过 HTTP Headers 提供的客户端IP。代理服务器可以伪造任何IP。

    要防止伪造,不要读这个IP即可(同时告诉用户不要用HTTP 代理)。

    如果是PHP,$_SERVER['REMOTE_ADDR'] 就是跟你服务器直接连接的IP,用这个就可以了。

    répondre
    0
  • 天蓬老师

    天蓬老师2017-04-10 13:13:19

    我也试过这个,不止是X-FORWARDED-FOR,也可以伪造CLIENT_IP的请求头,看你的脚本如何取请求头的key, 好像就REMOTE_ADDR没办法伪造,可以取这个吧,PHP下是$_SERVER['REMOTE_ADDR'],不知道会不会存在空值的情况。

    répondre
    0
  • 巴扎黑

    巴扎黑2017-04-10 13:13:19

    想完全避免近乎不可能,透明和匿名http代理还能检测http头,但是socks代理呢,或者自己实现的端口转发呢?
    现在能想到的就是维护一个巨大的库,把所有能搜集到的可能是代理的ip加进去,用户访问之前先进库对比。但是这样缺点也很大,一是库太大了访问速度会变慢,影响效率;二是有些ip可能只是暂时是代理,比如肉鸡,可能会恢复正常,比如营运商动态分配的ip,今天我用时做代理,明天分配到你那里就可能不是代理了,如果没有一个很好的检测剔除机制,很可能误杀;三是库不可能把所有代理都收进去,只能尽可能搜集一些互联网上公开的代理,私有代理很难收集到,这些库之外的代理还是没法避免他们访问。
    不过目前有公司确实在维护这样的库,对外以api的方式提供服务。

    répondre
    0
  • Annulerrépondre