CODE:

#!/usr/bin/perl

###############################################################################
## DDOSBlock version 0.1 Author: Jo3-GHT                                      #
##                                                                            #
## Download from https://sourceforge.net/projects/ddosblock                   #
##                                                                            #
## To execute, run:                                                           #
##                                                                            #
## ./ddosblock-0.2.pl                                                         #
###############################################################################

use strict;
use warnings;

use vars qw(%CONFIG %blocked);

$| = 1;

my %CONFIG = (

  ## 0 = No output
  ## 1 = Actions reported
  ## 2 = Actions + unix commands reported
  ## 3 = Verbose in the extreme

  DEBUG => 2,

  ## Do we perform checks only - no IPTABLE changes - Good for debugging

  TESTMODE => 0,

  ## Ban IP addresses above this number of accesses

  THRESHOLD => 150,

  ## How long, in seconds, between checks

  INTERVAL => 30,

  ## If we have APF use that, otherwise fallback on iptables

  USEAPF => 0,

  ## How long (in seconds) do we ban people for
  ## escalating each time they're bad
  ## This resets to the first item, when they have gone
  ## a full interval without being flagged
  ##
  ## 60, 300, 3600 would mean that they are banned for 60 seconds, then 5 minutes, then an hour
  ##
  ## This list can have as many increment levels as you like

  BANINCREMENTS => [60, 120, 240, 800, 1200],

  ## IP ADDRESSES THAT WE WILL NEVER BAN

  EXCLUDEIPS => [ "127.0.0.1", "10.0.0.1" ],

  ## UNIX COMMANDS

  NETSTAT => "/bin/netstat",

  IPT => "/usr/sbin/iptables",

  APF => "/usr/local/sbin/apf",

  SENDMAIL => "/usr/sbin/sendmail",

  ## WHERE TO STORE/SAVE OUTPUT

  LOGDIR => "/var/log/ddosblock",

  MAILTO => "nobody\@example.com", # NOTE: Under Perl you have to escape the @ symbol with a slash

  STDOUT => 1, # In addition to logging, do we want to report it to STDOUT

);

$CONFIG{TOTINCREMENTS} = $#{$CONFIG{BANINCREMENTS}};
$CONFIG{LISTFILE}      = "$CONFIG{LOGDIR}/bannedips.txt";
$CONFIG{LASTDAY}       = 0;

if ( ! -d $CONFIG{LOGDIR})
{
  print "Creating log directory $CONFIG{LOGDIR}\n\n";
  mkdir $CONFIG{LOGDIR},700;
}

my $command = qq($CONFIG{NETSTAT} -ntu | awk '{ sub(/(.*)\:/,"",\$4); sub(/\:(.*)/,"",\$5); print \$5,\$4}' | grep ^[0-9] | sort | uniq -c | sort -nr | head -30 );

&rotatelog();

if ($CONFIG{TESTMODE} == 1)
{
  &debug(qq(** NOTE **\n\nTest mode - No IPTABLE changes will be made\n));
}

&loadbanned();

while (1)
{
  &rotatelog();

  &check();

  &release();

  &debug(qq(- Sleeping for $CONFIG{INTERVAL} seconds\n)) if ($CONFIG{DEBUG} > 1);

  sleep $CONFIG{INTERVAL};
}

sub rotatelog
{
  my @date = localtime();
  my $weekday = $date[6];

  if ($weekday != $CONFIG{LASTDAY})
  {
    if ($CONFIG{LASTDAY})
    {
      close(DEBUG);
    }
    $CONFIG{LASTDAY} = $weekday;

    open(DEBUG, "> $CONFIG{LOGDIR}/doslog.$weekday.txt");
  }
}

sub check
{
  my @input = `$command`;

  my $now = time;

  my $savelist;

  INPUTLOOP:
  foreach my $item (@input)
  {
    chomp($item);

    $item =~ s/^ +//io;
    $item =~ s/ +/ /io;

    &debug("-- $item\n") if ($CONFIG{DEBUG} >= 3);

    my ($hits, $ipaddress, $port) = split(/ /, $item);

    next INPUTLOOP if (grep(/^$ipaddress/, @{$CONFIG{EXCLUDEIPS}}));

    next INPUTLOOP if (defined $blocked{$ipaddress} && $now < $blocked{$ipaddress}{sleepuntil});

    if ($hits > $CONFIG{THRESHOLD})
    {
      $blocked{$ipaddress}{blocklevel} = $blocked{$ipaddress}{lastblock} + 1 || 1;
      $blocked{$ipaddress}{lastblock}  = $blocked{$ipaddress}{blocklevel};

      if ($blocked{$ipaddress}{blocklevel} == 1)
      {
        my $iptcmd     = ($CONFIG{USEAPF}) ?
          "$CONFIG{APF} -d $ipaddress"
        :
          "$CONFIG{IPT} -I INPUT -s $ipaddress -j DROP";

        my $ok = `$iptcmd` unless ($CONFIG{TESTMODE});

        &debug("Adding block for $ipaddress ($hits hits/minute, port $port)") if ($CONFIG{DEBUG} > 0);
        &debug("- Command $iptcmd") if ($CONFIG{DEBUG} > 1);

        if ($CONFIG{MAILTO})
        {
          my $localtime = localtime();

          open (MAIL, "| $CONFIG{SENDMAIL} -t");
          print MAIL qq(To: $CONFIG{MAILTO}\nSubject: IP address $ipaddress banned\n\nBanned ip addresses $ipaddress on $localtime with $hits hits\n);
          close (MAIL);
        }
      }
      else
      {
        &debug("Setting $ipaddress to block level $blocked{$ipaddress}{blocklevel} ($hits hits/minute)") if ($CONFIG{DEBUG} > 0);
      }

      &updatesleep($ipaddress);

      $savelist = 1;
    }
  }

  # Save a list of banned IPs to a file incase this process dies
  if ($savelist)
  {
    &savebanned();
  }
}

sub release
{
  my $now = time;
  my $savelist;

  # Loop through all the IP addresses flagged

  foreach my $ipaddress (keys %blocked)
  {
    # No point looking at it until we've gone past the sleep date

    if ($now > $blocked{$ipaddress}{sleepuntil})
    {
      $blocked{$ipaddress}{passcount}++;

      # Remove the block on the first pass
      # then remove the

      if ($blocked{$ipaddress}{passcount} == 1)
      {
        # Release the block

        my $iptcmd = ($CONFIG{USEAPF}) ?
          "$CONFIG{IPT} -u "
          :
          "$CONFIG{IPT} -D INPUT -s $ipaddress -j DROP";

        &debug("Removing block from $ipaddress") if ($CONFIG{DEBUG}> 0);
        &debug("- Command $iptcmd") if ($CONFIG{DEBUG} > 1);

        my $ok = `$iptcmd` unless ($CONFIG{TESTMODE});

        $blocked{$ipaddress}{blocklevel} = 0;
      }
      else
      {
        &debug("- Two passes without issue $ipaddress, forgetting block level") if ($CONFIG{DEBUG} > 1);
        delete $blocked{$ipaddress};
      }

      $savelist = 1;
    }
  }

  # Save a list of banned IPs to a file incase this process dies
  if ($savelist)
  {
    &savebanned(\%blocked);
  }
}

sub updatesleep
{
  my ($ipaddress) = @_;

  my $blocklevel = $blocked{$ipaddress}{blocklevel};

  $blocklevel = ($blocklevel >= $CONFIG{TOTINCREMENTS}) ? $#{$CONFIG{BANINCREMENTS}} : $blocklevel;

  my $increment = $CONFIG{BANINCREMENTS}[$blocklevel - 1];

  $blocked{$ipaddress}{sleepuntil} = time + $increment;

  my $stamp = localtime(time + $increment);

  &debug("- Will check $ipaddress after $increment seconds ($stamp) - Block level $blocklevel") if ($CONFIG{DEBUG} > 1);
}

sub loadbanned
{
  undef %blocked;

  if (-f $CONFIG{LISTFILE})
  {
    open(LIST, "< $CONFIG{LISTFILE}");
    my @list = <LIST>;
    close (LIST);

    # Rebuild a list of those things we've blocked
    foreach my $ipaddress (@list)
    {
      chomp($ipaddress);

      # Let them be released and evaluated again
      $blocked{$ipaddress}{sleepuntil} = 1;
      $blocked{$ipaddress}{blocklevel} = 1;
      $blocked{$ipaddress}{lastblock}  = 1;
      $blocked{$ipaddress}{passcount}  = 0;

      &debug("- Loading blocked IP $ipaddress") if ($CONFIG{DEBUG} > 0);

    }
  }
}

sub savebanned
{
  my ($list) = @_;

  open(LIST, "> $CONFIG{LISTFILE}");
  print LIST join("\n", keys %blocked);
  close (LIST);
}

sub debug
{
  my ($line) = @_;

  print DEBUG localtime() . " $line \n";

  if ($CONFIG{STDOUT})
  {
    print localtime() . " $line \n";
  }
}


- 0 bình luận lượt xem

http://www.plusthuthuat.com/2015/09/ddos-block-perl-new-hot.html

BÌNH LUẬN (0)

Một số lưu ý khi bình luận

Mọi bình luận sai nội quy sẽ bị xóa mà không cần báo trước (xem nội quy)

Bấm Thông báo cho tôi bên dưới khung bình luận để nhận thông báo khi admin trả lời

Để bình luận một đoạn code, hãy mã hóa code trước nhé