Jump to content

[SOLVED] PHP & Bans


ProXy_

Recommended Posts

Hello, I'm trying to figure out how i can ban an IP if they're flooding me

 

For example: if i had api http://blah.com/api.php?url=http://url

And someone makes a script to open 2000 iframes and flood it.

is there any way i can detect it with PHP?

 

i've already got a good idea how to auto add their ip to .htaccess

i just have been looking trying to find different ways of blocking floods

and i havn't gotten anywhere, appreciate any help. thanks

Link to comment
Share on other sites

I would do it with iptables personally....  (Assuming it's a linux box.)  That way the request never reaches Apache and you avoid the overhead of the request.

 

 

Just drop all packets from that IP address.

 

iptables -I INPUT -s 0.0.0.0 -j DROP

 

(Where 0.0.0.0 is a real IP address)

 

 

If the IP address changes, you'll need to make rules based on requests per second.  (Don't know if that's possible or not with iptables since I've never looked into it.)

 

 

(P.S. if the server is running Windows, Windows Firewall should work fine.)

 

 

If the problem is going to be long term and especially if you expect it to become more of an issue (for example if someone starts a decent size DDOS attack), you might want to look into blocking on a router level.  (Probably not worth the effort unless it becomes a big problem or if it's easy to do with your router.)

Link to comment
Share on other sites

If the IP address changes, you'll need to make rules based on requests per second.  (Don't know if that's possible or not with iptables since I've never looked into it.)

 

You could write a service that runs in the background and analyzes the access log. Not exactly a simple solution.

 

Easiest thing would be to have a counter using sessions that blocks if they've made X requests within the last Y time units.

Link to comment
Share on other sites

<?php
  $flood = $_SERVER['HTTP_REFERER'];
  
//Replace blah with the website url (without extension)
  if (preg_match("/blah/i", "$flood")) {
      die('Your banned, you flooder!');
  }
?>

 

This kinda helps a little bit, but the person randomly switches his host to another free host and does it again. so i'm trying to just stop an ip instead of a website.

 

And to the others, i'm on a paid shared server, thats why i am trying to make a php script to auto ban anyone that abuses my API.

 

i had a few ideas, but after a while of creating the ideas, i don't see a future that would resolve my problem.

 

But, if one IP adds 40 urls in under a minute, Add IP to .htaccess.

Would be a simple way of explaining what i am trying to figure out :/

Link to comment
Share on other sites

This is a pretty ugly way to do it, but it would work assuming the person is dumb enough to leave cookies enabled or let the session ID be appended to the URL:

 

 

<?php

session_start();

if(!isset($_SESSION['visits'])) {
    $_SESSION['visits'] = array();
}

$timeframe = 3; //3 seconds
$requests_per = 50; //50 requests

$visits &= $_SESSION['visits'];

$now = microtime(true);

foreach($visits as $key => $visit_utime) {
    if($visit_utime < $now-$timeframe) {
        unset($visits[$key]);
    }
}

//1 since the current visit isn't in the array yet

if(count($visits) + 1 > $requests_per) {
    //add IP to ban list
    exit;
}

$visits[] = $now;

 

 

 

 

 

Really doing it by IP would be better though...

 

 

That's a bit more complicated though since $_SESSION acts as a convenient container for the data.

 

 

With IPs you would have to store it somewhere like a file or a database.  Cleaning out old data would become an issue, and things like locking could be an issue in both a DB and flat files.

Link to comment
Share on other sites

With IPs you would have to store it somewhere like a file or a database.  Cleaning out old data would become an issue, and things like locking could be an issue in both a DB and flat files.

 

In the case of MySQL, you would then want to use InnoDB because it has got row level locking. It only locks a row you are currently using and not the entire table like MyISAM does.

Link to comment
Share on other sites

I've tried a few things above, and i couldn't really seem to get anywhere.

 

The main part i'm trying to figure out is how to Allow x amount of visits per ip in x minutes

 

Is this possible at all, i've searched everywhere and i'm just getting nowhere.

I Appreciate all help.

Link to comment
Share on other sites

In that case, the easiest solution is a MySQL database.  As Daniel mentioned, InnoDB does row level locking and MyISAM does table level locking, so you'll want to use InnoDB as the engine.

 

 

Anyway, then the concept is basically the same as earlier just with a different data storage method.  Do you have any SQL experience?  Also, is MySQL even an option?  If it's not, do you have access to any kind of database/

Link to comment
Share on other sites

I have the access to mysql & all that.

I'm not very experienced with mysql & innodb

I'm a pretty quick learner. so if i need to study these languages. i can do so.

 

I just needed to find some way to make this possible

just can't risk getting exploited again :/

 

so, thank you again for your time.

Link to comment
Share on other sites

Normally I don't give people code since it defeats the purpose of a helping forum, but I went ahead and made this since it would be kind of lame to link you to a couple of tutorials and be like "have fun!" when you obviously have a problem.

 

 

 

Anyway:

 

CREATE DATABASE iplimit;

 

USE iplimit;

 

 

CREATE TABLE visits (

ip_addr int unsigned NOT NULL,

visit_time float

) ENGINE=InnoDB;

 

CREATE INDEX idx_ip_addr ON visits(ip_addr);

CREATE INDEX idx_visit_time ON visits(visit_time);

 

CREATE TABLE banned (

ip_addr INT UNSIGNED UNIQUE

);

 

 

CREATE DATABASE iplimit;

USE iplimit;


CREATE TABLE visits (
ip_addr int unsigned NOT NULL,
visit_time float
) ENGINE=InnoDB;

CREATE INDEX idx_ip_addr ON visits(ip_addr);
CREATE INDEX idx_visit_time ON visits(visit_time);

CREATE TABLE banned (
ip_addr INT UNSIGNED UNIQUE
);

 

 

 

 

It basically does the same thing as the session thing from earlier, but it stores it in a database and does it by IP.

 

 

 

It's worth noting that you could replace the banned table with writing the IP to a htaccess file (which would save parsing the PHP page/connecting to the database), but then you would have to worry about file locking.

Link to comment
Share on other sites

i Appreciate your help.

This is exactly what i have been looking for all over the place.

 

And thank you for the code, it saves me a little time so i can just

throw this in here and get our api system back up in little time.

 

Thank you again. i really do appreciate this

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.