Restict Logins by IP Address

by frank on March 7, 2007

in PHP

Today I had to write into an admin area on one of our sites a restriction so that only people at certain IP addresses could log in.

I wrote a pretty quick piece of code, but it seems to work nicely enough so I though I would convert it into a quick and dirty php function and put it out there…

This system works very simply by reading IP addresses in an array. It converts them to a basic regex by escaping periods with \. and matching against the current IP address in $_SERVER[REMOTE_ADDR]. I also allow IP ranges in a way that I think is kind of cunning.

As you would ordinarily write an IP address range as: 10.10.3.* – all I do is replace any *’s with .*’s and then that works in the preg_match() function too.

I haven’t tested the function, but it should return true if there is a match and false if there is not – let me know if you come across any errors in it :).

//allowable IP addresses for admin login.
$ip = array();
$ip[] = '10.10.3.*';
$ip[] = '211.109.238.74';
$ip[] = '254.254.254.2';
 
function testIP($ip){
//testing that correct IP address used in order
//to access admin area...
for($i=0, $cnt=count($ip); $i<$cnt; $i++) {
    $ipregex = preg_replace("/./", "\.", $ip[$i]);
    $ipregex = preg_replace("/*/", ".*", $ipregex);
 
    if(preg_match('/^'.$ipregex.'/', $_SERVER[REMOTE_ADDR]))
        return true;
    }
    return false;
}

Was this article useful?

rss feed icon

Email this article to yourself or...

rss feed icon

Subscribe to the RSS feed for more useful articles and tips.

Share this article with others

  • del.icio.us
  • Twitter
  • Reddit
  • StumbleUpon
  • Facebook
  • Digg
  • eduke

    Hi

    Thanks for this function. There is small bug in it. You are missing backslash in preg_replace.

    Should be like this:

    $ipregex = preg_replace(“/\./”, “\.”, $ip[$i]);
    $ipregex = preg_replace(“/\*/”, “.*”, $ipregex);

  • http://deadlytechnology.com franktank

    Thanks, good spotting :)

  • du

    thank you. I was trying to make this on my own when I came across yours. Why do more work :) Very nice, short, and simple.

    du

  • http://luke.xifos.org/ Luke Eckley

    Thanks for the great PHP tip.

  • http://www.jenski.co.uk Jen

    Thanks for the function btw, its been really useful, one small tweak though….

    instead of
    ‘/’.$ipregex.’/’

    should be:
    ‘/^’.$ipregex.’/’

    Only because if an allowed IP was
    $ip[] = ”211.*.*.*”;

    it would also allow an IP of 74.192.211.23

  • frank

    Thanks Jen, good spotting, all fixed.

  • scott

    Any suggestions on how to add masks?
    Eg: 10.0.0.1/29 – would allow IP’s 10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4, 10.0.0.5, 10.0.0.6

  • http://www.acquadream.com.br roger

    loop for doesn’t work. There is return false and return true. Loop will never iterate through count($ip)

  • frank

    hi roger, not sure I follow why the for loop doesn’t work…

  • http://twitter.com/theProject707 Project707

    Actually you don’t even need the asterisks or to run all of that regex. Just enter the part of the IP you want to match on followed by a “.” so that say, .3 can’t become .345 (unless that’s desired functionality), and then use strpos() which tends to be faster for short string checks like this anyhow.

    To do it this way, if your array is:
    $ip = array();
    $ip[] = ’10.10.3.’;
    $ip[] = ’211.109.238.74′;
    $ip[] = ’254.254.254.2′;

    then this is all you need within the for loop (0 makes sure it matches from the beginning):
    if( strpos($_SERVER['REMOTE_ADDR'], $ip[$i]) === 0)
    return true;

  • Vinceas3

    That worked. Franks did not work, unfortunately, kept getting an error for preg match, but this works beautifully. I replaced everything in the for loop with your nice “if” statement, and it works like a charm. Thanks!!

  • Nickmokisasian

    What happens if one of the persons ip address changes?