21

i want to allow users to filter their login based on their ip address (a new settings in the user preferences i will implement).

so if a user with a specific ip login and there is not restriction, the login is successful.

in any other case i was thinking this

if the user choose his full IP like 67.31.85.47 and he has this IP then the login is good if a user choose 67.31.85.* and has this IP then the login is good if a user choose 67.31.. and has this IP then the login is good if a user choose 67...* and has this IP then the login is good any other case it's invalid

the user can choose up to 5 IP restrictions. eg:

67.31.*.*
167.77.47.*
62.11.28.28
25.57.*.*
169.*.*.*

i was tinking to strip the IP using explode and then compared to all restrictions he setup. this can be slow since i have to check 5 times * 4 (4 = IP exploded on the dot)

is there a faster way to do it? thanks

2
  • 7
    Consider converting those IPs to normal integers and using netmasks. Then it's a simple bit-wise AND operation for each IP address to be checked. if ((userIP && netmask) == (filterIP && netmask)) { ok to go }. Commented Nov 9, 2011 at 20:48
  • Since you seem to be filtering on the old-school /8 boundaries, you'd need 3 netmasks. 0xFF000000, 0xFFFF0000, 0xFFFFFF00. apply the relevant mask to each ip in your table, apply it to the user's IP, and if the masked values are equal, they're in the same IP block. Commented Nov 9, 2011 at 21:43

3 Answers 3

29
<?php
function testIP($ip) {
    if($ip == '*' || $ip == '*.*.*.*') {
        return TRUE;
    }
    if($_SERVER['REMOTE_ADDR'] == $ip) {
        return TRUE;
    }
    $mask = str_replace('.*', '', $ip);
    return strpos($_SERVER['REMOTE_ADDR'], $mask) === 0;
}

$_SERVER['REMOTE_ADDR'] = '70.69.68.67';

$ip = '1.11.1.*';
echo "Is $ip good: "; var_dump(testIP($ip));
$ip = '2.34.9.1';
echo "Is $ip good: "; var_dump(testIP($ip));
$ip = '70.11.*.*';
echo "Is $ip good: "; var_dump(testIP($ip));
$ip = '70.69.68.*';
echo "Is $ip good: "; var_dump(testIP($ip));
$ip = '70.69.*.*';
echo "Is $ip good: "; var_dump(testIP($ip));
$ip = '70.*.*.*';
echo "Is $ip good: "; var_dump(testIP($ip));
$ip = '*.*.*.*';
echo "Is $ip good: "; var_dump(testIP($ip));
$ip = '*';
echo "Is $ip good: "; var_dump(testIP($ip));

will output:

Is 1.11.1.* good: bool(false)
Is 2.34.9.1 good: bool(false)
Is 70.11.*.* good: bool(false)
Is 70.69.68.* good: bool(true)
Is 70.69.*.* good: bool(true)
Is 70.*.*.* good: bool(true)
Is *.*.*.* good: bool(true)
Is * good: bool(true)

If you are looking for specific ip (no wild card) checking, you can use:

function is_private_ip($ip) {
  return filter_var($ip, FILTER_VALIDATE_IP) != FALSE;
}

var_dump(is_private_ip('82.237.3.3')); var_dump(is_private_ip('748.1234.5.4'));

Sign up to request clarification or add additional context in comments.

Comments

6

Maybe this idea help for you:

<?php
$ip_restrict = "67.31.*.*
167.77.47.*
62.11.28.28
25.57.*.*
169.*.*.*";

$ip_restrict = array_flip(explode("\n", $ip_restrict));
$ip = preg_match("!([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)!", $_SERVER['REMOTE_ADDR'], $ip_match);


$ip_in_blacklist = false;
$ip_check_1 = $ip_match[1] . '.*.*.*';
$ip_check_2 = $ip_match[1] . '.' . $ip_match[2] . '.*.*';
$ip_check_3 = $ip_match[1] . '.' . $ip_match[2] . '.' . $ip_match[3] . '.*';
$ip_check_4 = $ip_match[1] . '.' . $ip_match[2] . '.' . $ip_match[3] . '.' . $ip_match[4];

if (isset($ip_restrict[$ip_check_1]) || isset($ip_restrict[$ip_check_2]) || isset($ip_restrict[$ip_check_3]) || isset($ip_restrict[$ip_check_4])) {
    $ip_in_blacklist = true;
}

var_dump($ip_in_blacklist);

;

3 Comments

why using a preg_match? why not explode? what's the difference?
It's easy to format and validate :) you may use explode, i do not see any difference
explode does not use regexp vs preg_match is
0
$auth_ip=array();
$client_ip=array();
$client_ip=explode(".", $_SERVER['REMOTE_ADDR']);
$auth_ip=explode("\n", $patner_name_id[0]['client_ip']);
$j=0;
$flag=0;

foreach ($auth_ip as $value) {
    $i=0;
    $value=explode(".", $value);
    foreach ($value as $valueip) {
        if($valueip!="*") { 
            if($valueip!=$client_ip[$i]){
                $flag=1;
                 break;
            }
            $i++;
        }
        else {
            $i++;
            continue;
        }               
    }
}

if($flag==1){
    header("Location:".$default_company);           
    exit;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.