This would be a GREAT addition to CSF

Post Reply
felosi
Junior Member
Posts: 40
Joined: 26 Jan 2007, 07:44

This would be a GREAT addition to CSF

Post by felosi »

Since bots and zombie computer are getting harder for the average bot kiddy to come by now a days they are resorting to GET attacks on dynamic sites with the inetention to exhaust resources which in most cases it does no matter if you have network ddos protection, connection tracking, etc. The requests are legit requests for like index.php or GET / over and over but it does it slow enough and does not build up enough connections to be banned by most automatic methods.

So for the past year I been trying everywhere to get someone to make me this script to block these type attacks. I remember even asking here and for some reason or another was turned down but now I finally got someone to code it for me.

It has been tested by me and a few other people and it works. Its actually pretty simple.

I think another method that would work too is like the mod_security failure function to simply tail the specified domlog for the specified or if the script is real smart - the ability to pick up any request being requiested over and over abnormally.

This new script is called Block Apache Request Floods - B.A.R.F.and I think if this or something similar was integrated into csf it would totally complete everything it needs to provide effective and automatic ddos protection for all types of attacks. However in this script's current state the request, domain, and other paramters must be specified.

For example, I got a site under attack and the bots are making this request over and over again.
"GET / HTTP/1.1"

Ok, say I want to block any ip making this request over 2 times in 5 seconds I would enter

barf domain.com -n 2 -t 5 -s "GET / HTTP/1.1"

Here is script:

Code: Select all

#!/usr/bin/perl

##############################################################################
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#  Copyright 2009 jpetersen
#
##############################################################################

##############################################################################
#   _                 __
#  | |               / _|   BLOCK
#  | |__   __ _ _ __| |_    APACHE
#  | '_ \ / _` | '__|  _|   REQUEST
#  | |_) | (_| | |  | |     FLOODS
#  |_.__/ \__,_|_|  |_|      LoL:D
#
##############################################################################

##############################################################################
#
#  Block an IP address if it issues x number of y requests
#  to apache within z seconds. This script takes 4 options:
#
#  example.com  this is the domain to monitor
#  -n <num>     if this many requests
#  -t <num>     are made within this many seconds
#  -s <req>     for this string
#               then the IP address issuing the requests will be blocked.
#
#  Examples:
#
#    Look for 3 requests within 10 seconds that match GET /index.php
#    ./script example.com -n 3 -t 10 -s "GET /index.php"
#
#    Look for 10 requests within 30 seconds that match GET / HTTP/1.1
#    ./script example.com -n 10 -t 30 -s "GET / HTTP/1.1"
#
#  This is the expected Apache log format, which is the default on cPanel servers:
#  1.2.3.4 - - [28/Jun/2009:16:43:05 -0400] "GET / HTTP/1.1" 404 - "-" "-"
#
##############################################################################

use strict;
use warnings;
use File::Tail;
use Getopt::Long;

if ( @ARGV ne 7 )
{
    die "\nUsage:\n\t$0 example.com -n 3 -t 10 -s \"GET / HTTP/1.1\"\n\n";
}

my $site     = shift; # domain name
my $domlog   = '/usr/local/apache/domlogs/' . $site;
my %visitors = ();  # 1.2.3.4 => 1246231315
my %hits     = ();  # 1.2.3.4 => 3
my $log_line;

-e $domlog or die "Unable to locate $domlog\n";

my ( $max_number_of_requests, $time_to_track, $request_string );

GetOptions (
    "n=i" => \$max_number_of_requests,
    "t=i" => \$time_to_track,
    "s=s" => \$request_string,
);

my $file = File::Tail->new(
    name        => $domlog,
    interval    => 1,
    maxinterval => 1,
    resetafter  => 1,
    reset_tail  => 0,
);

################################################################
#
#  tail the domlog
#
################################################################
while ( defined ( $log_line = $file->read ) )
{
    if ( $log_line =~ m{\A((\d{1,3}\.){3}\d{1,3})(\s-){2}(\s\S+){2}\s"$request_string} )
    {
        my $ipaddr = $1;

        clean_hashes( $ipaddr );
        check_visitors( $ipaddr );
        check_for_block( $ipaddr );
    }
}

################################################################
#
#  Remove any IP addresses that have been seen longer than
#  $time_to_track seconds ago.
#
################################################################
sub clean_hashes
{
    my $ipaddr = shift;

    if ( %visitors )
    {
      if($visitors{$ipaddr}) {
        if ( ( time - $visitors{$ipaddr} ) > $time_to_track )
        {
            delete $visitors{$ipaddr};
            delete $hits{$ipaddr};
        }
      }
    }
}

################################################################
#
#  Check to see if we're tracking the IP address already.
#  If we aren't, update the %visitors hash.
#
################################################################
sub check_visitors
{
    my $ipaddr = shift;

    my $already_tracked = 0;

    for my $key ( keys %visitors )
    {
        if ( $key eq $ipaddr )
        {
            $already_tracked = 1;
        }
    }

    if ( $already_tracked == 0 )
    {
        $visitors{$ipaddr} = time;
    }
}

################################################################
#
#  Update the %hits hash. Check to see if the user specified
#  number of hits has exceeded the user specified time period.
#  If the threshold has been exceeded, then block the host and
#  stop tracking it.
#
################################################################
sub check_for_block
{
    my $ipaddr = shift;

    $hits{$ipaddr}++;

    if ( $hits{$ipaddr} >= $max_number_of_requests )
    {
        if ( ( time - $visitors{$ipaddr} ) <= $time_to_track )
        {
            print "blocking $ipaddr\n";
               system '/usr/local/bin/csf', '-d', $ipaddr;

            delete $visitors{$ipaddr};
            delete $hits{$ipaddr};
        }
    }
}
Also for anyone else interested in using this script or contributing to the devlopment of it please check http://nix101.com where I will be posting regular updates to it. Hopefujlly chirpy will integrate something like this into csf . But if not I will be sponsoring this project and soliciting people to help with it (as I cannot code) but so far I have recieved good help from WHT on it and will continue too. SO it will be updated and more features added.
Domineaux
Junior Member
Posts: 18
Joined: 19 Sep 2007, 23:42
Location: Houston, TX USA (Earth)
Contact:

Post by Domineaux »

Looks like a nice idea!
Post Reply