Geeks With Blogs
My lessons learned while developing!

Ok here is a cool trick I figured out that I hope will be helpful to someone:

What if you wanted to block all the incoming ip addresses from a given country to a given site using only PHP and mySQL (without using .htaccess, etc.) and be able to log who you blocked into your mySQL database?

First, you need to have a white list or a black list. I got mine from http://software77.net/geo-ip/ because they were free, based off of countries and worked pretty darn well.

For myself, I used the x.x.x.x-y.y.y.y option, cut out the headers and dropped the text file onto my server, then I made a little script to load them into a table in mydatabase:

<?php
include "myconfig.php"; //this contains my db connection info
--use your own here
include "openmyDB.php"; //this opens up my db connection --use your own here

//clear out the table first
mysql_query("DELETE FROM myallowedIp")or die(mysql_error()); 

//get all the ip ranges from the text file I put on the server
$validAddressList = file_get_contents('validipAddresses.txt');

//split them up into an array
$validAddresses = explode("\n", $validAddressList);

//put each element of the array into the db
foreach ($validAddresses as $validAddressRange)
{

    //trim it
    $validAddressRange = trim($validAddressRange);

    //get the two halves of the range
    $fromAndTo = explode("-", $validAddressRange);

    //put them into the db. NOTE: I am converting them into longs so thatI can quickly compare them later
    $myQuery = "INSERT INTO myallowedIp (ipaddressFrom, ipaddressTo)
        VALUES ('".ip2long($fromAndTo[0])."', '".ip2long($fromAndTo[1])."')";

    //echo $myQuery."<br>";
    mysql_query($myQuery)or die(mysql_error());
}

include "closemyDB.php"; //this closes my db connection
--use your own here

?>

I recommend taking that script off your server once you are done loading it up for security purposes.

Now that I have it all loaded into my db, I can now query that table every time a user shows up at my site and turn them away or allow them in (depending on if I want to treat my address ranges like a whitelist or a blacklist)!

To do this, first you get the ip address of the user (here I keep it around as a session variable, but do whatever you want):

<?php
session_start();

if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //to check ip is pass from proxy
{
    $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
    $ip=$_SERVER['REMOTE_ADDR'];
}
   
$_SESSION["REALIPADDRESS"] = $ip;

?>

Then, you compare it against your table (assuming you have already opened up your db connections):

    $allowResult = mysql_query("SELECT * FROM myallowedIp WHERE
        ipaddressFrom <= '".ip2long($_SESSION["REALIPADDRESS"])."' AND
        ipaddressTo >= '".ip2long($_SESSION["REALIPADDRESS"])."'")or die(mysql_error()); 
    if($allowRow = mysql_fetch_array( $allowResult ))
    {
        //if this is a whitelist, you can come in...(put other code here as you want)
    }
    else
    {
        //not on whitelist...

      //send them somewhere else or whatever you want. Note: only use the header() command if you have not sent ANYTHING to the user yet. If it is not working, check that first.
      header ('HTTP/1.1 301 Moved Permanently');
      header ('Location: http://www.google.com/');
      exit();
    }

I hope that helps someone! Take care and have fun developing!


EDIT: I had to move the site around where I use this, and I decided to change how I did it to make it more intuitive for me to test. Instead of storing the allowable IP addresses as LONGs, I stored them as VARCHAR with a max size of 15, so that my code snippet above would look like this instead:

    $myQuery = "INSERT INTO myallowedIp (ipaddressFrom, ipaddressTo) 
        VALUES ('".$fromAndTo[0]."', '".$fromAndTo[1]."')";

Then, when it comes time to check if something matches (or doesn't match), I do this instead, using mySQL's INET_ATON to compare them instead of PHP's ip2long: 

$allowResult = mysql_query("SELECT * FROM myallowedIp WHERE 

INET_ATON(ipaddressFrom) <= INET_ATON('".$_SESSION["REALIPADDRESS"]."') AND 

INET_ATON(ipaddressTo) >= INET_ATON('".$_SESSION["REALIPADDRESS"]."')")or die(mysql_error()); 


Posted on Wednesday, March 30, 2011 3:12 PM | Back to top


Comments on this post: Allowing or blocking ip addresses with PHP and mySQL based off of what country they are from

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © robertphyatt | Powered by: GeeksWithBlogs.net