使用IP地址限制对站点的访问

时间:2009-09-08 07:11:05

标签: php ip-address

我想知道是否存在一种限制网站用户的方式,使他们只能访问某个网站的内页,如果他们在某个IP地址或某个网络范围内?

当前的PHP脚本我无法区分真正的IP和代理?

谢谢

5 个答案:

答案 0 :(得分:4)

我不会限制IP地址。正如你所说,你不知道它是否是代理人。此外,IP地址很容易被欺骗。

答案 1 :(得分:3)

您是否考虑过使用apache .htaccess文件? IP restriction with htaccess

答案 2 :(得分:2)

您可以尝试我创建的脚本,它允许非常高级的IP规则。我几年前编码了所以我提前为它的当前形状道歉。

编辑: 如果你正在寻找“&”算法中的运算符不要打扰。我编码时忘记添加它,回头看这个脚本现在让我因为再次触摸它而感到畏缩。

<?php
##############################################################
# IP Expression Class                                        #
# Easy IP-based Access Restrictions                          #
# Change Log:                                                #
# - Added Range and limited IPv6 support                     #
# - Changed name from IPAR to IPEX                           #
#                                #
##############################################################
# Example Rules:                                             #
# 69.[10-20].[^50].*                                         #
# 69.*.[1-5 | 10-20 |^30].*                                  #
# 60.12.2.*                                                  #
# 127.*                                                      #
# 69.1.1.1-70.1.1.1   <-- This is a range                    #
#                                                            #
# Usage:                                                     #
# Ipex::IsMatch($rule, $ip);                                 #
#                                                            #
# [range] - Defines a range for a section of the IP          #
# |   - OR token. IP can match this range/number         #
# ^       - NOT token. IP can not match this range/number    #
# x-y     - Defines a range from x to y                      #
# x       - Exactly match x (x = a hex or dec number)        #
# *       - Match any number                                 #
#                                #
#----------===============================-------------------#
#           [ Written by Chris Tarquini ]                    #
#----------===============================-------------------#
##############################################################

define('IPR_DENY', false);
define('IPR_ALLOW', true);
define('IPR_ERR_MISMATCH',-1);
define('IPR_ERR_RANGE_MISMATCH',-2);
define('IPR_ERR_RANGE_INVALID',-3);
define('IPR_ERR_INVALID_RULE',-4);

class IPEX
{

    const TOKEN_RANGE_BEGIN = '[';
    const TOKEN_RANGE_END = ']';
    const TOKEN_WILDCARD = '*';
    const TOKEN_RANGE_SPLIT = '-';
    const TOKEN_OR = '|';
    const TOKEN_NOT = '^';
    const DEBUG_MODE = TRUE;

    private static function trace($err){if(self::DEBUG_MODE) echo "$err\r\n";}
    private static function FixRule($rule,$count = 4, $split='.')
    {
        $rule = explode($split,$rule);
        $filler = 0;
        $size = sizeof($rule);
        for($i = 0; $i < $count; $i++)
        {
            if($i > $size) { $rule[] = $filler; $size++;}
            else if(empty($rule[$i])) { $filler = self::TOKEN_WILDCARD; $rule[$i] = $filler;}
        }
        return $rule;   
    }

    private static function FixIP($rule,$count = 4, $split='.')
    {
        $rule = explode($split,$rule);
        $size = sizeof($rule);
        for($i = 0;  $i < $count; $i++)
        {
            if($i > $size) { $rule[] = 0; $size++;}
            else if(empty($rule[$i])) { $rule[$i] = 0;}
        }
        return $rule;   
    }
    private static function GetIpType(&$ip)
    {
        $mode = IPID::Identify($ip,$newip);
        if($mode == IPID_IPv4_Embed) { $ip = $newip; return IPID_IPv4;}
        return $mode;
    }
    private static function FixIPRange(&$start, &$stop)
    {
        $count = 4; $split = '.';
        if(self::GetIpType($start) == IPID_IPv6) {$count = 8; $split = ':';}

        $q = 0;
        while($q < 2)
        {
            $filler = ($q == 0) ? 0 : 255;
            $arr = explode($split,($q == 0) ? $start : $stop);
            $size = sizeof($arr);
            for($i = 0; $i < $count; $i++)
            {
                if($i > $size){ $arr[] = $filler; $size++;}
                else if(empty($arr[$i])){ $arr[$i] = $filler; }
            }
            if($q == 0) $start = implode($split, $arr);
            else $stop = implode($split,$arr);
            $q++;
        }

    }
    public static function IsInRange($start, $stop, $ip)
    {
        //Sorry guys we only support IPv4 for this ;(
        self::FixIPRange($start,$stop);
        self::trace("fixed: start = $start, stop = $stop");
        $start = ip2long($start); $stop = ip2long($stop);
        $ip = ip2long($ip);
        self::trace("start = $start, stop = $stop, ip = $ip");
        return ($ip >= $start && $ip <= $stop);
    }
    public static function IsAllowed($rule, $ip){return self::IsMatch($rule,$ip);}
    public static function IsMatch($rule,$ip)
    {
        $mode = self::GetIpType($ip);
        self::trace("ip type: $mode");
        if(strpos($rule, self::TOKEN_RANGE_SPLIT) !== false && strpos($rule,self::TOKEN_RANGE_BEGIN) === false)
        {
            self::trace("ip range mode");
            $test = explode(self::TOKEN_RANGE_SPLIT, $rule);
            self::trace("range size: ".sizeof($test));
            print_r($test);
            if(sizeof($test) != 2) return IPR_ERR_RANGE_INVALID;
            $start = $test[0]; $end = $test[1];
            if(empty($start) || empty($end)) return IPR_ERR_RANGE_INVALID;
            self::trace("range start: $start, range stop: $end");
            $rm1 = (self::IsHex($start)) ? $mode : self::GetIpType($start);
            $rm2 = (self::IsHex($end)) ? $mode : self::GetIpType($end);
            self::trace("range types: $rm1, $rm2\r\nip type: $mode");
            if($rm1 != $rm2  || $rm1 != $mode) return IPR_ERR_RANGE_MISMATCH;
            if($mode == IPID_IPv6) { return IPR_ERR_IPv6_NOTSUPPORTED;}     
            return self::IsInRange($start,$end,$ip);
        }

        if(self::GetIpType($rule) != $mode) return IPR_ERR_MISMATCH;


        //all is good so far
        $count = 4;
        $split = '.'; if($mode==IPID_IPv6){$count = 8; $split=':';}
        $rule = self::FixRule($rule, $count,$split);

        $ip = self::FixIp($ip,$count,$split);
        self::trace("ip: ".implode($split,$ip));
        self::trace('rule: '.implode($split,$rule));
        for($i = 0; $i < $count; $i++)
        {
            $r = str_replace(' ', '', $rule[$i]);
            $ri = false;
if($r == self::TOKEN_WILDCARD) continue;
            if($mode == IPPID_IPv6 && self::IsHex($r)) { $ri = hexdec($r);}else if(is_numeric($r)) $ri = $r;


            $x = $ip[$i];
            if($mode == IPPID_IPv6) $x = hexdec($x);
            //* Exact Match *//
            self::trace("rule[$i]: $ri");
            self::trace("ip[$i]: $x");
            if($ri !== false && $ri != $x) return IPR_DENY;
            $len = strlen($r);
            for($y = 0; $y < $len; $y++)
            {
                self::trace("y = $y");
                if(substr($r, $y,1) == self::TOKEN_RANGE_BEGIN)
                {
                    ++$y;
                    self::trace("found range, y = $y");
                    $negflag = false;
                    $start = false;
                    $stop = false;
                    $allows = 0;
                    $denys = 0;
                    $q = 0;
                    $c = substr($r,$y,1);
                    while($c !== false)
                    {
                        self::trace("in range, char: $c");
                        //* Flags *//
                        $break = false;
                        $exec = false;
                        $toggle = false;
                        $reset = false;

                        if($c === self::TOKEN_RANGE_END) {$skiphex = true;$break = true; $exec = true; self::trace("found end of range");}
                        if($c === self::TOKEN_NOT) {if($q > 0){ $toggle = true; $exec = true;} else $negflag = !$negflag; $skiphex =false; self::trace("found TOKEN_NOT");}
                        if($c === self::TOKEN_OR) { $exec = true; $reset = true;$skiphex=true;self::trace("found TOKEN_OR");} 
                        if($c === self::TOKEN_RANGE_SPLIT){ $skiphex = false;++$q; self::trace("found range split");}

                        //* Read Hex Tokens *//
                        if(!$skiphex && self::IsHexChar($c))
                        {
                            $n = self::ReadNextHexToken($r,$y);
                            if($mode == IPID_IPv6) $n = hexdec($n);
                            if($q == 0) $start = $n;
                            else if($q == 1) $stop = $n;
                            --$y; //fixes error
                            self::trace("parsed number: $n, y = $y");
                        }   
                        if($reset) {$negflag = false; $start = false; $stop = false;  $q = 0;}
                        if($exec)
                        {
                            self::trace("executing: start = $start, stop = $stop, x = $x");
                            self::trace("negflag = $negflag");
                            if($stop !== false && $x >= $start && $x <= $stop)
                            {
                                if($negflag) { ++$denys; $allows = 0; break;}
                                else ++$allows;
                            }
                            else if($stop === false && $start == $x)
                            {
                                if($negflag) { ++$denys; $allows = 0; break;}
                                else ++$allows;
                            }
                            self::trace("exec complete: allows = $allows, denys = $denys"); 
                            $q = 0;
                        }
                        if($toggle) $negflag = !$negflag;
                        if($break) break;
                        ++$y;
                        $c = substr($r,$y,1);
                    } 
                    if(!$allows) return IPR_DENY;
                }
            }


        }
                return IPR_ALLOW;   

    }
    private static function ReadNextHexToken($buff, &$offset, $max = -1)
    {
        $str = '';
        if($max == -1) { $max = strlen($buff);}
        for(; $offset < $max; $offset++)
        {
            $c = substr($buff,$offset, 1);
            if(self::IsHexChar($c))
                $str .= $c;
            else
                return $str;
        }
        return $str;
    }
    private static function IsHex($x){ $len = strlen($x); for($i = 0; $i < $len; $i++) if(!self::IsHexChar(substr($x,$i,1))) return false; return true;}
    private static function IsHexChar($x){self::trace("isHex($x);"); return (in_array(strtoupper($x),array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F')));
}
}



######################
# IP Identify Class  #
#####################
define('IPID_INVALID',false);
define('IPID_IPv4',2);
define('IPID_IPv6',3);
define('IPID_IPv4_Embed',6);

class IPID
{

        public static function Identify($ip,&$ipconvert = false)
        {
                $ip = strtoupper($ip);
                $ipconvert = $ip;
                // Check if we are IPv4
                if(strpos($ip,':') === false && strpos($ip,'.') !== false)
                        return IPID_IPv4;
                //Is it one of those hybrids?
                else if(strpos($ip,':FFFF') !== false && strpos($ip,'.') !== false)
                {
                        $ipconvert = substr($ip,strpos($ip,':FFFF:')+6);
                        return IPID_IPv4_Embed;
                }
                // Is it IPv6?
                else if(strpos($ip,':') !== false)  return IPID_IPv6;
                // What the...?
                return IPID_INVALID;
        }


}
?>

您可以使用它,只要您不尝试转售它并保持标题不变。

答案 3 :(得分:0)

代理服务器应设置X-Forwarded-For HTTP标头,您可以使用$_SERVER['HTTP_X_FORWARDED_FOR']查找该标头。否则$_SERVER['REMOTE_ADDR']可用于获取IP地址。正如其他人所指出的那样,这两者都很容易被欺骗,并且代理不需要设置X-Forwarded-For请求标头。

PHP中有一个ip2long()函数,它为您提供了一个用于范围检查的整数。

要获取IP地址的位置,您需要一个查找表,该表将IP地址范围映射到近似地理位置(此类查找表通常不是免费的)。有许多服务提供IP地址定位,其中一些提到herehere

答案 4 :(得分:0)

<?php
    //This function returns True if visitor IP is allowed.
    //Otherwise it returns False.
    function CheckAccess()
    {
        //allowed IP. Change it to your static IP
        $allowedip = '127.0.0.1';
        $ip = $_SERVER['REMOTE_ADDR'];
        return ($ip == $allowedip);
    }