PHP获得真正的IP(代理检测)

我确实跟踪了用户的“真实”IP,如果他有一个代理发送真实IP的头部......有没有更好的解决方案,甚至更多的头文件?

由于这个函数在脚本中经常被使用,所以它必须非常快速,并且看起来并不是这个星座:/

我提出了一些建议,但没有意识到:

  • 按顺序放置标题,使用最多的“野外”,使功能快速完成
  • 更快速地为IP进行pre_match检测
  • ===

    function get_real_ip()
    {
      $proxy_headers = array(
                              'CLIENT_IP', 
                              'FORWARDED', 
                              'FORWARDED_FOR', 
                              'FORWARDED_FOR_IP', 
                              'HTTP_CLIENT_IP', 
                              'HTTP_FORWARDED', 
                              'HTTP_FORWARDED_FOR', 
                              'HTTP_FORWARDED_FOR_IP', 
                              'HTTP_PC_REMOTE_ADDR', 
                              'HTTP_PROXY_CONNECTION',
                              'HTTP_VIA', 
                              'HTTP_X_FORWARDED', 
                              'HTTP_X_FORWARDED_FOR', 
                              'HTTP_X_FORWARDED_FOR_IP', 
                              'HTTP_X_IMFORWARDS', 
                              'HTTP_XROXY_CONNECTION', 
                              'VIA', 
                              'X_FORWARDED', 
                              'X_FORWARDED_FOR'
                             );
    
      foreach($proxy_headers as $proxy_header)
      {
        if(isset($_SERVER[$proxy_header]) && preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $_SERVER[$proxy_header])) /* HEADER ist gesetzt und dies ist eine gültige IP */
        {
            return $_SERVER[$proxy_header];
        }
        else if(stristr(',', $_SERVER[$proxy_header]) !== FALSE) /* Behandle mehrere IPs in einer Anfrage(z.B.: X-Forwarded-For: client1, proxy1, proxy2) */
        {
          $proxy_header_temp = trim(array_shift(explode(',', $_SERVER[$proxy_header]))); /* Teile in einzelne IPs, gib die letzte zurück und entferne Leerzeichen */
    
          if(($pos_temp = stripos($proxy_header_temp, ':')) !== FALSE) $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); /* Entferne den Port */
    
          if(preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $proxy_header_temp) return $proxy_header_temp;
        }
      }
    
      return $_SERVER['REMOTE_ADDR'];
    }
    

    如果代理发送一个头,那么你可以获取客户端的原始IP。 如果代理没有,那么你不能。 不幸的是(或者幸运地取决于你的观点),它就像那样简单。

    我在我们的Intranet上做的是在网络服务器上将“intranet.mydomain.com”重定向到“intranet”,后者由于内部网络/ DNS配置不使用代理...不知道你想要什么要做,但这可能会有用。

    您还可以在浏览器中设置排除列表...


    正则表达式验证对于ipv6地址将失败; 所以我宁愿删除它(或试图找到更好的RegEX)。

    stripos($proxy_header_temp, ':')会导致例如“:: 1”(localhost,ipv6)的预期行为。

    我提出的修改建议:

    function getIp()
    {
        $proxy_headers = array(
            'CLIENT_IP',
            'FORWARDED',
            'FORWARDED_FOR',
            'FORWARDED_FOR_IP',
            'HTTP_CLIENT_IP',
            'HTTP_FORWARDED',
            'HTTP_FORWARDED_FOR',
            'HTTP_FORWARDED_FOR_IP',
            'HTTP_PC_REMOTE_ADDR',
            'HTTP_PROXY_CONNECTION',
            'HTTP_VIA',
            'HTTP_X_FORWARDED',
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_FORWARDED_FOR_IP',
            'HTTP_X_IMFORWARDS',
            'HTTP_XROXY_CONNECTION',
            'VIA',
            'X_FORWARDED',
            'X_FORWARDED_FOR'
        );
        $regEx = "/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/";
        foreach ($proxy_headers as $proxy_header) {
            if (isset($_SERVER[$proxy_header])) {
                /* HEADER ist gesetzt und dies ist eine gültige IP */
                return $_SERVER[$proxy_header];
            } else if (stristr(',', $_SERVER[$proxy_header]) !== false) {
                // Behandle mehrere IPs in einer Anfrage
                //(z.B.: X-Forwarded-For: client1, proxy1, proxy2)
                $proxy_header_temp = trim(
                    array_shift(explode(',', $_SERVER[$proxy_header]))
                ); /* Teile in einzelne IPs, gib die letzte zurück und entferne Leerzeichen */
    
                // if IPv4 address remove port if exists
                if (preg_match($regEx, $proxy_header_temp)
                    && ($pos_temp = stripos($proxy_header_temp, ':')) !== false
                ) {
                    $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp);
                }
                return $proxy_header_temp;
            }
        }
    
        return $_SERVER['REMOTE_ADDR'];
    }
    
    链接地址: http://www.djcxy.com/p/5749.html

    上一篇: PHP get real IP (proxy detection)

    下一篇: singleton and inheritance in Java