[Site map]
You are here ---
> Newbies Paradise
> Tutorials
> Unofficial
> Website
> PHP & MySQL
> Reading a tutorial
How to forbid website access to some IP addresses
You are about to read a tutorial written by a member of this website. Although the author probably invested every effort to make this tutorial's content correct, we can not guarantee that the information on this page is 100% exact. Please keep this in mind when reading this tutorial. ;o)
When you are webmaster, it's frequent to encounter strange users that just want to disturb you and your members. Sometimes, the problem can come from bots posting everywhere on the website (on the guest book, on the forums, etc.).
In these cases, it is really practical to have emergency solutions that can be applied right in the moment, fastly and effectively.
To detect an IP address is very easy to do. During the loading of a PHP file, the variable
$_SERVER contains information about the page involved and about the communcations between the server and the client in this query. The entry
REMOTE_ADDR give us exactly the IP address of the client who asked the page.
Thus, this code displays the IP address of the visitor :
Code: PHP1
2
3 | <?php
print ('Your IP address is <strong>' . $_SERVER['REMOTE_ADDR'] . '</strong>');
?>
|
As I told you, it is something simple to do. But sometimes, it happens that the net surfers log them to some servers that we call proxy servers. A proxy server, it is a server that is used to make relations between a visitor and a website. The advantage for the visitor is that his IP address is not showed to the server that recepts his query, it's the one of the proxy that is considered. Why ? Just because this is the one that transmits the query right to the server :
By using this way, it is possible to pass most of the websites protection. So, we will create a function that will give us the real IP of the client, you will see that it is not too hard.
When it is a proxy server that does the query for another client, a new entry is created in the array
$_SERVER. This entry has the key
HTTP_X_FORWARDED_FOR. With this one, we can create our function :
Code: PHP 1
2
3
4
5
6
7
8
9
10 | <?php
//Return the true IP address
function get_ip() {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
else
$ip = $_SERVER['REMOTE_ADDR'];
return $ip;
}
?>
|
Personnally, I prefer to make it shorter with a ternary expression :
Code: PHP1
2
3
4
5
6 | <?php
//Return the true IP address
function get_ip() {
return (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
}
?>
|
Make sure to include this file in wich you put the function everywhere you need it. Personnally, I dedicate a complete file just to that function, in a folder
libs/div/. This protection is not 100% sure, because super anonymous proxies exist. In these cases, it's almost impossible to detect the real client that is forwared by the proxy. Sometimes, it is even impossible to detect that the query is done by a proxy

. But as long as we do our best, we should have no problems.
Now, we will create a little interface to banish easily IP addresses. I see two ways to do it. The first use a MySQL database and the second use only a text file. It can be astute to use the second solution, because the first implies an additionnal sql query to all of your pages, no exception.
But if you use MySQL, it will be easier to add useful options like the displaying of personalized sanction reasons, automatic remove, etc..
And now, believe me, we are gonna banish a lot of IP

!
First, we must create a new table on your database (if you don't have any databases, jump to the second way

!). I give you an example structure, change it as you want to adapt it.
Code: SQL1
2
3
4
5 | CREATE TABLE `ban` (
`ban_id` MEDIUMINT( 9 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`ban_ip` INT NOT NULL ,
UNIQUE (`ban_ip`)
);
|
Once this table is created, we will create a new file. The code given is just here as example. Note that I didn't take care to protect pages, because your are the only one to know how to integrate it to your website and your admin pannel.
You must protect the access to these sections ! Of course, you guessed that I will not give you complete files, only the involved parts

.
Banish an IP address
To banish an IP address, we will follow this procedure :
- We display a formular asking the IP to banish ;
- If the formular is not submitted yet, we verify if the IP is valid ;
- If this one is valid, we convert it into numeric entity with ip2long(), if not we display the formular with an error.
First, the formular :
Code: HTML1
2
3
4
5
6
7
8 | <form action="ban.php" method="post">
<fieldset>
<legend>Banish an IP address</legend>
<p><label for="ip">Address to banish : </label>
<input type="text" name="ip" id="ip" />
<input type="submit" value="Banish" />
</fieldset>
</form>
|
Don't forget to replace the action of the formular to give the correct page to post datas. For those of you who are asking them about the
<label></label> markup, it is used to join a text to a formular field. Thus, by clicking on "Address to banish", the focus will be given to the field with the id "ip". Really useful

.
Now, we will treat datas from the formular. The code below considers that you have an active MySQL connection. The formular is included if it has not been submitted.
Code: PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 | <?php
$isset = isset($_POST['ip']); //true if the formular is posted
$error = false; //We will change this value when errors occure
if ($isset) {
//If the formular has been posted
if (!empty($_POST['ip'])) {
$ip = ip2long($_POST['ip'])
if ($ip != false && $ip != -1) {
//If the IP is valid
require ('libs/div/is_ban.php');
if (!is_ban($ip)) {
mysql_query('INSERT INTO ban (`ip`) VALUES(\'' . $ip . '\')');
print('This IP is now banished.');
}
else
print ('This IP is already banished.');
}
else
$error = 1; //The ip address is invalid, erreur #1
}
else
$error = 0; //The field is empty, erreur #0
}
if (!$isset || $error !== false) {
//If the formular has not been posted, or if an error occured
$errors = array('Vous devez entrer une adresse ip.', 'The IP address is invalid.');
if ($error !== false) {
//If there's a mistake, we display it
print('<p style="color: red; font-weight: bold;">' . $errors[$error] . '</p>');
}
//We display the formular
print ('<form action="ban.php" method="post">
<fieldset>
<legend>Banish an IP address</legend>
<p><label for="ip">Address to banish : </label>
<input type="text" name="ip" id="ip" />
<input type="submit" value="Banish" />
</fieldset>
</form>');
}
?>
|
I told you, this is very simple ! Now it is your resonsability to include this code to your admin pannel, an I repeat it : protect it

!
The function ip2long() returns the IP address as a number. If an IP address is invalid, it returns -1 with php3 and php4, but with php5 it returns false : a whim. You can change the script to do only the logical test that corresponds to the version of PHP that you use, if you know it (if not, phpinfo).
Get the list of banished IP addresses
To see the list of banished addresses, we just have to do a SELECT query on our table. Once the script to remove IP from the list will be done, it would be astute to put links on each address of this list to remove it

. You should be able to do the code alone, I hope

. But because some of you feel less secure (you must have an active MySQL connection) :
Code: PHP 1
2
3
4
5
6
7
8
9
10
11
12
13 | <?php
//It's that easy :p
$req = mysql_query("SELECT * FROM ban");
if($res = mysql_fetch_assoc($req)) {
print('<ul>');
do {
print ('<li>' . long2ip($res['ban_ip']) . '</li>');
} while($res = mysql_fetch_assoc($req));
print ('</ul>');
}
else
print ('Currently no address.'); //The list is empty, we tell it
?>
|
It is very simple and again, I let you protect all of that effectively. It's important, I didn't tell it 10 times for fun

!
Remove an IP address from the list
To remove an IP address from the list, we just have to delete the entry that corresponds in the database. I remind you that to delete an entry from a MySQL table, we must use the DELETE query. Look at this simple code :
Code: PHP 1
2
3
4
5
6
7
8
9
10
11 | <?php
if (isset($_GET['ip'])) {
mysql_query('DELETE FROM ban WHERE ban_ip=\'' . $_GET['ip'] . '\'');
if (mysql_affected_rows() == 0)
print ('This ip address were not banished.');
else
print ('The ip has been removed from the list.');
}
else
print ('You must give an IP to remove.');
?>
|
Now, you can add links to your list of IP addresses, with this line in your buckle :
Code: PHP1 | print ('<li><a href="supp.php?ip=' . $dselect['ban_ip'] . '" title="Remove this IP">' . long2ip($dselect['ban_ip']) . '</a></li>');
|
That's all for MySQL, you can jump to the last part about the restrictions of banished IP addresses.
Here, we will learn to use a softer solution. Of course, because of the low quantity of ressources used with this alternative, the possible options are fewer. But don't be afraid, you will be able to manage hundred of banished addresses : but don't try to display personalized message to each persone forbidden. But that is part of facultative stuff

.
At first, create a file named ips.txt and put it where you want. Don't forget to change the access paths when I use it in my examples

. This file will be simple : it will contain an IP address per line. Of course, each address in this file will be unallowed to access to the website.
Banish an IP address
To banish an IP address, we must add a line containing the address to the file ips.txt. We will create our script following these steps :
- We display the formular asking the IP to banish ;
- If the formular is submitted, we make sure that the IP is valid ;
- If yes, we convert it into a numeric entity using the function ip2long(), if not we display the formular with an error ;
- If everything is right, we add a line to the file and we display an information message.
The formular asking the IP address to banish is the same that if you would have chosen the MySQL solution :
Code: HTML1
2
3
4
5
6
7
8 | <form action="ban.php" method="post">
<fieldset>
<legend>Banish an IP address</legend>
<p><label for="ip">Address to banish : </label>
<input type="text" name="ip" id="ip" />
<input type="submit" value="Banish" />
</fieldset>
</form>
|
Now, we will treat datas coming from this formular. To open our file, we will use the function
fopen() an we will open it in mode 'a', which is a writting mode that put the pointer at the end of the file. To open your file, the folder's chmod that contains it must be set to 777. Look at the code, the structure is similar to the one for MySQL :
Code: PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 | <?php
$isset = isset($_POST['ip']); //true if the formular is posted
$error = false; //We change this value once there's error
if ($isset) {
//If the formular is posted
if (!empty($_POST['ip'])) {
$ip = ip2long($_POST['ip'])
if ($ip != false && $ip != -1) {
//If the IP address is valid
require ('libs/div/is_ban.php');
if (!is_ban(long2ip($ip))) {
$file = fopen('ips.txt', 'a'); //We open it in mode 'a'
fwrite($file, $ip . "\n"); //We add the line with the IP
fclose($file); //We close the file
print('This address is now banished.');
}
else
print ('This address is already banished.');
}
else
$error = 1; //IP invalid, error #1
}
else
$error = 0; //The field is empty, error #0
}
if (!$isset || $error !== false) {
//If the formular has not been posted or if there was an error
$errors = array('You must enter an IP address.', 'The IP address is invalid.');
if ($error !== false) {
//If there's an error, we display it
print('<p style="color: red; font-weight: bold;">' . $errors[$error] . '</p>');
}
//We display the formular
print ('<form action="ban.php" method="post">
<fieldset>
<legend>Banish an IP address</legend>
<p><label for="ip">Address to banish : </label>
<input type="text" name="ip" id="ip" />
<input type="submit" value="Banish" />
</fieldset>
</form>');
}
?>
|
Now, we will learn how to get the list of unallowed IP addresses

. Yeah, it can be useful

!
Get the list of banished address
To get this list, we must at first read the content of the file ips.txt and put it in a variable. To do it, we will use the function
file() wich returns an array containing different lines of the file (one entry per line). Look at this simple example :
Code: PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | <?php
//We put the content of the file in an array
$addresses = explode("\n", file_get_contents('ips.txt'));
$nbr = count($addresses);
if ($nbr != 0)
print ('<ul>'); //If there are addresses, we open the HTML list
foreach ($addresses as $key=>$value) {
if ($value != '')
print ('<li>' . long2ip($value) . '</li>'); //We display the IP
}
if ($nbr != 0)
print ('</ul>'); //We close the HTML list
else
print ('There's currently no IP addresses.'); //The file is empty
?>
|
That's all for the list ! Integrate it in your admin pannel and most of all, protect it

.
Remove an IP address from the file
Yes, it's practical to be able to remove IP addresses from the file

. To banish IP, we must add a line, to remove an IP, we must remove a... line ! We will use the function
str_replace() that's used to replace a part of string by another one in a text. The address in
$_GET['ip'] is already converted in numeric entity. Let's go !
Code: PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | <?php
if (isset($_GET['ip'])) {
$content_first = file_get_contents('ips.txt');
$content = str_replace($_GET['ip'] . "\n", '', $content_first);
$file = fopen('ips.txt', 'w');
fwrite($file, $content);
fclose($file)
if ($content_first == $content)
print ('This address was not banished.');
else
print ('The address has been removed.');
}
else
print ('You must give an address to remove.');
?>
|
That's all for the management of unallowed IP addresses. In the last part, we will learn how to forbid the access to people in the list

.
Until now, the banished addresses can always access the website. We will create a function
is_ban($ip) that will return true if the IP is banished, and false if not. First, let's begin by creating a basic HTML file that will be displayed to unallowed people. I suggest one, change it as you want :
Code: HTML 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>You're not allowed</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
#main
font-family: 'Trebuchet Ms', Serif;
font-size: 13px;
position: absolute;
top: 50%;
margin-top: -150px;
height: 150px;
left: 50%;
margin-left: -300px;
width: 600px;
}
.message {
border: 1px solid #c1c1c1;
padding: 10px;
margin-bottom: 10px;
height: 150px;
}
h1 {
font-family: Arial, Serif;
font-size: 30px;
text-align: center;
}
</style>
</head>
<body>
<div id="main">
<div class="message">
<h1>You're not allowed</h1>
<p>You are unallowed to access to this website.</p>
</div>
</div>
</body>
</html>
|
Moreover you have the CSS

.
The function for MySQL
In the case of MySQL, we will just select entries where the IP address is equal to the one of the visitor. If we get more thant 0 entry, the function will return true. If not, it will return false.
Code: PHP 1
2
3
4
5
6
7
8
9
10
11
12
13 | <?php
//Indicate if an address is banished
function is_ban($ip) {
$ip = ip2long($ip);
$query = mysql_query('SELECT * FROM ban WHERE ban_ip=\'' . $ip . '\'');
$nbr = mysql_num_rows($query);
if ($nbr == 0)
return (false);
else
return (true);
}
?>
|
Dedicate a whole file to this function and save it where you want

.
The function for the text file solution
In the case of the text file, there are a lot of ways to do the same thing. We will use the function
strpos() that returns the position of a string in another. If the first string doesn't appear in the second, the function returns false. Note that it's important to use the type and value comparison (===) because strpos returns 0 if the position is 0.
Code: PHP1
2
3
4
5
6
7 | <?php
//Indicate if an IP address is allowed or not
function is_ban($ip) {
return strpos(ip2long($ip) . "\n", file_get_contents('ips.txt')) === false ? false : true;
}
?>
|
That's all for the text file, we just have to use the function for now

.
Use the function and display the information page
The code that follows must be put in all the pages that you want to forbid to banished IP. You can also put it in a file that you include in all the pages of your site. In the case of MySQL, make sure your connection is active when you launch the function. Of course, if you use a system that separates your website into modules, you're lucky, because you will have to include it only once.
Don't forget to put the code below before any HTML code, because you would have two Doctype (example)

:
Code: PHP 1
2
3
4
5
6
7
8
9
10
11
12 | <?php
//We include the file
require ('libs/div/get_ip.php');
$ip = get_ip();
require ('libs/div/is_ban.php');
if (is_ban($ip)) {
//The ip is banished, we display the page
readfile('interdiction.html');
die();
}
?>
|
I repeat it, don't forget to change paths to access the included files

.
Now, you have a good way to forbid the access to your website. Use it moderatly ! By the way, the worst idea that you can have is to block the IP address of GoogleBot

.
Some other solutions exist to block the access to your website or just a particular folder of the server. For example, you can do that with .htaccess file for Apache, but this is a little bite more complicated to make it dynamic.