This tutorial explains not only why site owners
should or should not restrict user access to their sites, but how to
properly manage users access if they choose to place restraints.
How to restrict visitor access to your web site
I will start this tutorial by telling you that it's wrong to restrict access to your visitors. Why would you want to do that?
Maybe you want to restrict certain users from accessing
your web site...I recommend you to alter your database and just add a
simple field to store the status in (1=active, 0=inactive).
Should you ban a whole country because you target only regional traffic
and they're eating your bandwith (hard to believe but...) ? Whatever the
reason is (and if you're here in need for such tools please use the
comments form and let us know your intention and also the motif that
made you search for something like this) we will try to find out
various ways of restricting a (or more?!:) visitor's access to your web
site.
I will start with a PHP solution that uses wildcards so you can ban a
whole class just by replacing the desired class with an asterix "*"
that will also be our wildcard.
//Wilcard character is an asterix, *
$ip_ban = array();
$ip_ban[] = "10.10.10.*"; // Bans 10.10.10.0 - 10.10.10.255
$ip_ban[] = "10.12.13.50"; // Bans 10.12.13.50
if(in_array($_SERVER['REMOTE_ADDR'],$ip_ban))
{
die("Your IP Address has been banned.");//Kill/stop the script and show message to user.
}
else
{
//Do loop through bans:
foreach($ip_ban as $ban)
{
if(eregi($ban,$_SERVER['REMOTE_ADDR']))
{
die("Your IP Address has been banned."); //Kill/stop the script and show message to user.
}
//Finished loop
}
}
As you can see we stored our ip's (simple or by range using wildcards)
in an array ($ip_ban[]) and produced a loop to compare the
$_SERVER['REMOTE_ADDR'] which is the ip address of the visitor with the
data that is in our array. If a match comes out, the script will die
and output an error message.
Anyways, instead of $_SERVER['REMOTE_ADDR'] I would use a function
which it's not an ultimate solution but it will find out if the visitor
is behind a proxy trying to hide his real ip. Try to remember that this
is simple stuff and will not stop users behind SOCKS proxies or users
that benefit (or not by situation) from a dynamic ip which changes from
a pc restart to another or from 15 to 15 minutes...whatever. For
dynamic ip's I would recommend to use the script with a wildcard since
most providers offer ip's from the same range for example :
100.100.100.1-255 - where only the class D will change from 1 to 255 so
I would store this in my array:
$ip_ban[] = "100.100.100.*"; but try to remember that you will also
block another 254 of possible users that have nothing to do with the
war you're into.
Here's the function that might be more useful than
$_SERVER['REMOTE_ADDR']:
function ip_first($ips) {
if (($pos = strpos($ips, ',')) != false) {
return substr($ips, 0, $pos);
} else {
return $ips;
}
}
function ip_valid($ips) {
if (isset($ips)) {
$ip = ip_first($ips);
$ipnum = ip2long($ip);
if ($ipnum !== -1 && $ipnum !== false && (long2ip($ipnum) === $ip)) { // PHP 4 and PHP 5
if (($ipnum < 167772160 || $ipnum > 184549375) && // Not in 10.0.0.0/8
($ipnum < -1408237568 || $ipnum > -1407188993) && // Not in 172.16.0.0/12
($ipnum < -1062731776 || $ipnum > -1062666241)) // Not in 192.168.0.0/16
return true;
}
}
return false;
}
function ip() {
$check = array('HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED',
'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED',
'HTTP_VIA', 'HTTP_X_COMING_FROM', 'HTTP_COMING_FROM');
foreach ($check as $c) {
if (ip_valid(&$_SERVER[$c])) {
return ip_first($_SERVER[$c]);
}
}
return $_SERVER['REMOTE_ADDR'];
}
- where ip() is supposed to be the real ip of our visitor (<?php
echo ip(); ?>).
If you don't want to always modify the page that contains our array and
you wish to store the banned ip's into a database here's an example of
the script with the mods:
$check_visitor = "SELECT `visitor_ip` FROM `banned_visitors`";
$query_check_visitor = mysql_query($check_visitor) or die(mysql_error());
$ip_ban = array();
while ($row=mysql_fetch_array($query_check_visitor))
{
$ip_ban[] = $row['visitor_ip'];
}
if(in_array(ip(),$ip_ban))
{
die("Your access was restricted on this server.");
}
else
{
foreach($ip_ban as $ip)
{
if(eregi($ip,ip())) die("Your access was restricted on this server.");
}
}
Well that's just about it with the PHP banning. You could also use
.htaccess to restrict the access of your visitors. A method that I also
recommend instead of the one above. The usage is simple...deny from,
allow from...for example:
<limit GET>
order deny,allow
deny from all
allow from 192.168
</limit>
will allow only visitors that have the ip starting with 192.168. which
means 192.168.[1-255].[1-255] !IMPORTANT - don't put a space at the
after or before the comma that sits between deny and allow because the
server will take it as an error and restrict everyone's access. If we
change it into:
<limit GET>
order allow,deny
allow from all
deny from 192.168
</limit>
A very good implementation of this method is used for cron jobs. Let's
suppose you have a cron script which will execute something at a given
time and we don't want it to be executed by nobody else but our server. I would use this command:
<limit GET>
order deny,allow
deny from all
allow from 127.0.0.1
</limit>
- where 127.0.0.1 is our localhost and only the local server will be
able to execute this file. This is a variable, depends on your local
configuration. Please check with your hosting provider for this
information.
Another good reason to apply restrictions would be when a visitor will
enter an X amount of failed logins for example. A solution would be to
apply it automatically for an Y amount of time and output a nice error
telling him that but, again, not ban his IP. It will probably need some good knowledge of server setting. Also, as a
simpler version in PHP I would recommend you to store the attempts in a
session like this:
if(isset($_SESSION['failed_logins']))
{
$_SESSION['failed_logins']++;
}
else
{
$_SESSION['failed_logins'] = 1;
}
This is so easy to extend and, for example (supposing that we have a
table in our database to store the login attempts id, ip and time) if
the $_SESSION['failed_logins'] reaches 3 do an insert. Going further,
with some basic date and time calculations (and with a global variable
of 30 mins of restriction after 3 failed login attempts) we extract the
data from our table (Where ip=$_SERVER['REMOTE_ADDRESS']) and we do the
math. If the actual time minus the time that was entered in the
database along with the banned ip is smaller < than 30 minutes...we
still hide the login form... if it's bigger > ..you know the rest.
As a conclusion of this small tutorial I will ask you to read very
carefully and try to understand your problem and also try to apply the
proper method.
|