Camen Design Forum

Banning By IPs

append delete rex

I wanted to be able to ban any trouble makers and here is my solution just incase anyone else needs to do the same.

First create a file named banned.php use the script below

// Let's redirect the undesirables all bans are in blacklist.txt

if ( !file_exists('blacklist.txt') ) {
 $deny_ips = array(
} else {
 $deny_ips = file('blacklist.txt');
// read user ip adress:
$ip = isset($_SERVER['REMOTE_ADDR']) ? trim($_SERVER['REMOTE_ADDR']) : '';
// search current IP in $deny_ips array
if ( (array_search($ip, $deny_ips))!== FALSE ) {
 // address is blocked:
 header("Location:");   //this is where you send banned ips

Now in your root folder you will need to create the blacklist.txt. Inside this text place all ips you need to ban one ip per line.

You will have to add


to the pages you want the bans to be applied too.

Thats it!

Reply RSS


append delete #1. Martijn

As NNF already depends on the .htaccess file for its URL rewrites, you may instead want to ban IP addresses in there.

Take a look at this example from the superb Perishable Press:

One of the great things about blocking access at the .htaccess layer is that Apache will drop the connection for you before it ever needs to spin up PHP to do any parsing. This will be easier on your server as well in case of a DoS attack.

For people who feel more at home with PHP, this is definitely nice to have!

append delete #2. Jos

Nice. I've used this one to block entire countrys from the forum - really only allow traffic from my country - Denmark. Its very easy to block an entire range with this
Do a seach for ip_in_range to find an updated version


 * Check if a given ip is in a network
 * @param  string $range IP/CIDR netmask eg., also is accepted and /32 assumed
 * @return boolean true if the ip is in this range / false if not.
function ip_in_range($ip, $lines)
    foreach ($lines as $range) {
        if (strpos($range, '/') == false) {
            $range .= '/32';
        // $range is in IP/CIDR format eg
        list( $range, $netmask ) = explode('/', $range, 2);
        $range_decimal = ip2long($range);
        $ip_decimal = ip2long($ip);
        $wildcard_decimal = pow(2, ( 32 - $netmask )) - 1;
        $netmask_decimal = ~ $wildcard_decimal;
        if (( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal )) {
            return 1;
    return 0;

$incidents = $_SERVER['DOCUMENT_ROOT'].'/ipblok/ipblok.log';

$lines = explode("\n", file_get_contents($_SERVER['DOCUMENT_ROOT'].'/ipblok/DK.cidr'));
if (!ip_in_range($_SERVER['REMOTE_ADDR'], $lines)) {  //udenlandske
    $txt = $_SERVER['REMOTE_ADDR']." [".date('Y-m-d H:i:s')."] FOR";
    $myfile = file_put_contents($incidents, $txt.PHP_EOL, FILE_APPEND);


Since i now need to block TOR and VPNs and proxys, i just block TOR users from certain pages and foreign IP's from posting in the forum. Its softer and works perfectly if you use both approaches.

Foreign IP's are removed by using a request to
I dont even bother to test for errors and such.

function isDanish()
    $response=json_decode(file_get_contents($theaddress), true);
    if ($response['country_code']=='DK')
        return true;
        return false;

Tor users are blocked by using the ip_in_range and using tor exit nodes list from . Same idea used by rex

:: @Jos added on 26 Feb ’18 · 07:43

I forget.
I add the function to the top og start.php and call it from

if ((   //if HTTP authentication is used, we don’t need to validate the form fields
) || (  //if an input form was submitted:
        FORM_SUBMIT &&
        //are the name and password non-blank?
        NAME && PASS &&
        //the email check is a fake hidden field in the form to try and fool spam bots
        isset ($_POST['email']) && @$_POST['email'] == '' 
        //Er det en dansk adresse
        && isDanish()
)) {
        //users are stored as text files based on the hash of the given name
append delete #3. Martijn

@Jos that’s interesting. I didn’t know about! 2 things though:

1. Your code is calling `".$_SERVER['REMOTE_ADDR']` but I don’t think the `/` should be in there. To query the database the IP/hostname should be the first thing after the format (`/json/`).

2. An IP address constitutes personal data under GDPR. I wonder if it is allowed to send the IP address of a visitor off to a third party without their explicit consent at all. (Not to mention a third-party service hosted outside of the EU.) You might have to run freegeoip locally or depend on the free GeoLite2 database yourself.

append delete #4. Jos

1) Oh yes - you're right. I i tryed to test for domainname and forgot to remove

2) Its just an IP adress and is not "person henførbar" - connected to a person or entity - so i doubt that it alone consists a problem.
I could also just call the ip_in_range feeded with list of danish IP networks - i've done that before.

append delete #5. Martijn

My 2 wasn’t really a criticism of course. I’ve just been watching GDPR stuff and it is really interesting, while also raising lots and lots of questions.

Its just an IP adress and is not "person henførbar" - connected to a person or entity - so i doubt that it alone consists a problem.

Do run that by your lawyer 😉 Here is the EU on the subject:

What constitutes personal data?
Any information related to a natural person or ‘Data Subject’, that can be used to directly or indirectly identify the person. It can be anything from a name, a photo, an email address, bank details, posts on social networking websites, medical information, or a computer IP address.

append delete #6. Jos

I've changed my approach since will be closed.

I've started to experiment with DNSBL's which is a simpler and in my case faster approach.

Im playing with the following code.


	function dnsblTjek( $ip_address = NULL, $dnsbl = NULL )
		if( filter_var($ip_address, FILTER_VALIDATE_IP) === false ) //Invalid IP
			return false;

		/*reverse IP address */
		$array = explode( ".", $ip_address );
		$array = array_reverse( $array );
		$reverse_ip = implode( ".", $array );

		/* Perform the check */
		$result = gethostbyname( $reverse_ip.".".$dnsbl );
		return $result;

	function isDanish($ipadress){
		$returncode= dnsblTjek( $ipadress, "" );
		if ($returncode == '') //Code for denmark -
			return true;
			return false;

	function isTorNode ($ipadress){
		$returncode= dnsblTjek( $ipadress, "" );

		if ($returncode == '') //see
			return true;
			return false;



(Leave this as-is, it’s a trap!)

There is no need to “register”, just enter the same name + password of your choice every time.

Pro tip: Use markup to add links, quotes and more.

Your friendly neighbourhood moderators: Kroc, Impressed, Martijn