Tôi Share
© Copyright 2018 Code đây rồi

DDoS Block PERL NEW HOT

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";
  }
}

Trần Thanh Bình

Muốn giỏi phải học, muốn học thì phải hỏi. Chính vì thế, hãy cùng tham gia thảo luận với nhau để tìm ra câu trả lời nếu có thắc mắc nhé!. Xem thêm về tôi

Nếu khung comments không hiển thị thì các bạn hãy liên hệ qua fb Trần Thanh Bình nhé


Cùng tham gia bình luận bài viết này nhé!

» Hãy là con người văn minh từ những câu nói