Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quick and easy flood protection?

I have a site where a user submits a message using AJAX to a file called like.php. In this file the users message is submitted to a database and it then sends a link back to the user. In my Javascript code I disabled the text box the user types into when they submit the AJAX request.

The only problem is, a malicious user can just constantly send POST requests to like.php and flood my database. So I would like to implement simple flood protection.

I don't really want the hassle of another database table logging users IPs and such... as if they are flooding my site there will be a lot of database read/writes slowing it down. I thought about using sessions, like have a session that contains a timestamp that gets checked every time they send data to like.php, and if the current time is before the timestamp let them add data to the database, otherwise send out an error and block them. If they are allowed to enter something into the database, update their session with a new timestamp.

What do you think? Would this be the best way to go about it or are there easier alternatives?

Thanks for any help. :)

like image 830
VIVA LA NWO Avatar asked Jun 11 '10 22:06

VIVA LA NWO


People also ask

How can I stop my house from flooding without sandbags?

HydraBarrier is an effective alternative to sand bags when it comes to spill containment and similar water containment and prevention applications. These water barriers are durable, come in a variety of sizes, are reusable, and can be filled when needed and emptied once used. This makes storing them a simple task.

What can I use for flood barrier?

Using Sand Bags. Traditional sand bags are an effective way to deflect water and help protect structures from flooding. Sand bags can be made of burlap, polypropylene, polyethylene and nylon.

What are temporary flood barriers?

What are temporary flood barriers? Temporary flood barriers consist of portable metal frames with a waterproof cover, designed to be quickly set up in pre-planned locations which do not have permanent defences. When flooding is expected, the barriers are quickly put up.


1 Answers

Well I made a script to handle it for core requests only (no session requests or other requests who aren't calling the core). If you have a look to google you'll find scripts/classes which will kill your server because of high loads every time. The fact, that many use SESSIONs and maybe ALSO SQL/Database will let you get a flooding protection as a server-killer. Also the fact that SESSIONs need a Cookie (or a GET SID) so you can manipulate SESSIONs easy to get a new SESSION ID.

My function is text-based and do a simple handling. The bad thing is that you maybe have to use a CronJob to delete ips from time to time. Comparing to other scripts its about 10* faster (and more save than sessions).

I don't know if its really useful at all. ;) You maybe like to change the rpm value to less or/and also the 200 req. My setting is a ban for a bot doing interval requests in <=6 seconds.

<?php
function ht_request_limiter() {
    if (!isset($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
    if (empty($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
    $path = '/your/path/ipsec/'; // I use a function to validate a path first and return if false...
    $path = $path.$_SERVER['REMOTE_ADDR'].'.txt'; // Real file path (filename = <ip>.txt)
    $now = time(); // Current timestamp
    if (!file_exists($path)) { // If first request or new request after 1 hour / 24 hour ban, new file with <timestamp>|<counter>
        if ($handle = fopen($path, 'w+')) {
            if (fwrite($handle, $now.'|0')) { chmod($path, 0700); } // Chmod to prevent access via web
            fclose($handle);
        }
    }
    else if (($content = file_get_contents($path)) !== false) { // Load existing file
        $content = explode('|',$content); // Create paraset [0] -> timestamp  [1] -> counter
        $diff = (int)$now-(int)$content[0]; // Time difference in seconds from first request to now
        if ($content[1] == 'ban') { // If [1] = ban we check if it was less than 24 hours and die if so
            if ($diff>86400) { unlink($path); } // 24 hours in seconds.. if more delete ip file
            else {
                header("HTTP/1.1 503 Service Unavailable");
                exit("Your IP is banned for 24 hours, because of too many requests.");
            }
        }
        else if ($diff>3600) { unlink($path); } // If first request was more than 1 hour, new ip file
        else {
            $current = ((int)$content[1])+1; // Counter + 1
            if ($current>200) { // We check rpm (request per minute) after 200 request to get a good ~value
                $rpm = ($current/($diff/60));
                if ($rpm>10) { // If there was more than 10 rpm -> ban (if you have a request all 5 secs. you will be banned after ~17 minutes)
                    if ($handle = fopen($path, 'w+')) {
                        fwrite($handle, $content[0].'|ban');
                        fclose($handle);
                        // Maybe you like to log the ip once -> die after next request
                    }
                    return;
                }
            }
            if ($handle = fopen($path, 'w+')) { // else write counter
                fwrite($handle, $content[0].'|'.$current .'');
                fclose($handle);
            }
        }
    }
}

Edit: My way to test the request time was with microtime and simulate 10'000 users. I ask google and tested (as example) http://technitip.net/simple-php-flood-protection-class

So I don't know what should be simple there? You have about 3 SQL Requests at one time like:

$this -> user_in_db($ip))
$this->user_flooding($ip);
$this->remove_old_users();

It maybe supply more functions, but all legit users use servertime for nothing. ;)

like image 76
7three Avatar answered Oct 05 '22 09:10

7three