#!/usr/bin/perl -w use strict; use Getopt::Long; #Perl DDoS Protection Script #Created By Joshua Knapp #joshua.knapp@lunarpages.com #version 1.13 #Change Log #Created and tested the script for functionality v0.01 11-01-09 #Added User Options, and Help Function v1.1 11-02-09 #Repaired the CSF and APF commands to work with Cron v 1.13 11-04-09 #Thanks Ryan, where ever you are. # Terminal Colors my %color = ("nocolor" =>"\033[0m", "white" =>"\033[1;37m", "light_gray" =>"\033[37m", "gray" =>"\033[1;30m", "black" =>"\033[30m", "red" =>"\033[31m", "light_red" =>"\033[1;31m", "green" =>"\033[32m", "light_green" =>"\033[1;32m", "brown" =>"\033[33m", "yellow" =>"\033[1;33m", "blue" =>"\033[34m", "light_blue" =>"\033[1;34m", "purple" =>"\033[35m", "pink" =>"\033[1;35m", "cyan" =>"\033[36m", "light_cyan" =>"\033[1;36m"); # End Terminal Colors sub shell_exec { my $exec = shift; my $ret = ""; local *PH; open(PH,"$exec |") || die "Can't exec $exec: $!"; while() { $ret .= $_; } close(PH); return($ret); } my $clear = shell_exec("clear"); #End copy from Ryan #Define User Options my ($help, $type, $limit, $version); #Get information from the user my $results = GetOptions( 'help' => \$help, 'version' => \$version, 'type=s' => \$type, 'limit=i' => \$limit, ); if ($version) { print "$color{blue}Version 1.13 Created by Joshua Knapp, Darksideofperfection.com $color{nocolor}\n"; exit; }; if ($help) { print "$color{light_blue}This script is ready to go out of the box if your using APF. By Default this script will block any IP that trys to connect 50 times (in a minute if you set it up as a cron).\n\nIf you would like to tweak the settings, here are optional commands.\n\n $color{green}-type : $color{white} This can be either apf or csf, two different types of firewalls. \n $color{green}-limit : $color{white} this is the limit trigger for the script\n\n$color{red} USE AT YOUR OWN RISK, NO WARRANTY IS PROVIDED\n\n$color{nocolor}"; exit; }; unless ($type) { $type = "apf"; }; unless ($limit) { $limit = 50; }; #The NetStat Scripts, Setup to watch port 80 my $netstat_script = 'netstat -plan | grep ":80" | awk \'{print $5}\' |sed \'s/::ffff://g\' | cut -d: -f1 | sort | uniq -c | sort -n'; #Get the Results of the Netstat Script my $netstat_results = shell_exec($netstat_script); #Defining Variables that are used later my (@netstat_array, @indiv_array, $is_over_limit, $run, $firewall_command, $numm_con); #was CSF set? if ($type eq "apf"){ $firewall_command = "/etc/apf/apf -d"; } else { $firewall_command = "/usr/sbin/csf -d"; }; $is_over_limit = "false"; #Start breaking down the Netstat Results @netstat_array = split(/\n/,$netstat_results); #And do it a little further foreach (@netstat_array) { @indiv_array = split(/ /,$_); #And now we have some figures to work with, lets see how many times someone connects foreach (@indiv_array) { #Make sure we arent dealing with blank space, Chomp didnt work for this... if ($_ ne '') { #check to see if it is a Number if ($_ =~ /^(\d+\.?\d*|\.\d+)$/) { #Is the number over the limit? if ($_ >= $limit) { $is_over_limit = "true"; $numm_con = $_; }; } #Has the over_limit flag been triggered? elsif ($is_over_limit eq "true") { #Block IP in the firewall $run = shell_exec("$firewall_command $_ # $_ blocked automatically for $numm_con connections, Which is over the Limit of $limit"); $is_over_limit = "false"; }; } #Prevent Netstat from blocking the wrong number in the array else { $is_over_limit = "false"; }; }; }; exit;