All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark <markryan@cfl.rr.com>
To: netfilter@lists.netfilter.org
Subject: error message
Date: Sun, 6 Jul 2003 14:59:42 -0400	[thread overview]
Message-ID: <200307061459.42268.markryan@cfl.rr.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]

I am using the following script to ban users with iptables.  I keep getting an 
error that says the following:
 
06.07.2003 14:38:41: Creating chain proftpdban to store blacklisted IPs
06.07.2003 14:38:41: Adding INPUT-rule which redirects to proftpdban
06.07.2003 14:38:41: Shutting down: Insertion of new rule in INPUT chain 
failed: Index of insertion too big

 
I have no idea what the error means or how to solve the problem.  Any help 
would be appreciated.
 
I have attached the perl script that I am using.
 
Mark

[-- Attachment #2: anti-hammer.pl --]
[-- Type: text/x-perl, Size: 8905 bytes --]

#!/usr/bin/perl

# anti-hammer v. 0.1
# Copyright (c) 2003 Michael Renner <robe@amd.co.at>

#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 2 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, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#
#TODO : 
#
#Statefile/permbans/checking of hitcounters

use strict;
use warnings;
use IPTables::IPv4;
use File::Tail;
use Time::ParseDate;
use POSIX;

use vars qw (%ips %config);

my (%config) = (
    logtoparse => "/usr/local/sbin/proftpd.log",
    outputlog => "/usr/local/sbin/hammer.log",
    port => "21",
    chainname => "proftpdban",
    duration => "60",
    maxhits => "4",
    bantime => "86400",
    bofh => "1",
    logdebug => "1",
    logstatus => "1",
    logbans => "1",
    loginfos => "1",
    );


daemonize();
open_log();
init_sighandlers();
init_iptable();

parselog();
die("parselog() returned... this should not happen!\n");


############
#   SUBS   #
############

sub parselog {
  my ($log) = File::Tail->new(name => $config{'logtoparse'}, resetafter=>120, interval => 1);
  my ($line);

  my ($ctime) = time();

  while (defined($line = $log->read)) {
    chomp $line;

    if ((time() - $ctime) >= 60) {
      cleanup(\%ips);
      $ctime = time();
    }

    my ($logtime, $ip) = parseproftpd($line);

    if ($logtime > 0) {
      if (! exists($ips{$ip})) {
        $ips{$ip} = [];
      }

      my ($iparef) = \@{$ips{$ip}}; 
      if (($#$iparef < 0) || ($$iparef[0] ne "BANNED")) {
        storeip($iparef, $logtime, $ip);
        clearold($iparef, $ip);
        try_ban($iparef, $ip);
      } else {
        logit("debug", "%s: is already banned, probably lines from the logbuffer", $ip);
      }
    } 
  }
}

sub daemonize {
  chdir('/') || die("Can't chdir to /: $!");
  open(STDIN, '/dev/null') || die("Failed to set stdin to /dev/null: $!");
  open(STDOUT, '>/dev/null') || die("Failed to set stdout to /dev/null: $!");

  defined(my $pid = fork()) || die("Failed to fork: $!");
  exit if $pid;
  setsid() || die("Failed to start a new session: $!");
  open(STDERR, '>&STDOUT') || die("Failed to redirect STDERR: $!");
}


sub cleanup {
  my ($chain, $timeout) = ($config{'chainname'}, $config{'duration'});
  my ($now) = time();

  my ($ip, @unban);

  logit("status", "!!!!!! Cleanup-Run-Start !!!!!!");

  foreach $ip (keys %ips) {
    my ($iparef) = $ips{$ip};

    if ($#$iparef < 0) {
      logit("status", "%-15s: Deleting: Empty.", $ip);
      delete($ips{$ip});

    } elsif (($$iparef[0] eq "BANNED")) {

      if ($$iparef[1] < $now) {
        logit("status", "%-15s: Unbanning: %d seconds old", $ip, $now - $$iparef[1]);
        
        do_unban($ip, $chain);
        push @unban, sprintf("IP %s got unbanned, Ban expired %d seconds ago", $ip, $now - $$iparef[1]);
        delete($ips{$ip});
        
      } else {
        logit("status", "%-15s: Banned: %d seconds left", $ip, $$iparef[1] - $now);
      } 

    } elsif ($$iparef[-1] < ($now - $timeout)) {
      logit("status", "%-15s: Deleting: %d seconds old", $ip, $now - $$iparef[-1]);
      delete($ips{$ip});

    } else {
      logit("status", "%-15s: Still active: %d seconds old, %d hit(s) recorded", $ip, $now - $$iparef[-1], $#$iparef + 1);
    }
  }

  logit("status", "!!!!!! Cleanup-Run-End !!!!!!");
  logit("ban", $_) foreach (@unban);
}

sub do_unban {
  my ($ip, $chain) = @_;
  my ($it) = IPTables::IPv4::init('filter');
  my (@banr) = $it->list_rules($chain);
  my ($rule);

  foreach $rule (@banr) {
    if ($rule->{'source'} eq $ip) {
      $it->delete_entry($chain, $rule) || shut_down("Deletion of banrule for $ip in $chain failed: $!");
    }
  }
  $it->commit();
}

  
sub storeip {
  my ($iparef, $ctime, $ip) = @_;

  if ($#$iparef >= 0) { 
    if (${$iparef}[-1] <= $ctime) {
      logit("debug", "%-15s: Storing hit %d", $ip, $ctime);
      push(@$iparef, $ctime);

    } else {
      logit("error", "Array for %s has a newer element than %d (possible clock jump?), clearing it", $ip, $ctime);
      @$iparef = ($ctime);
    } 
  } else {
    push(@$iparef, $ctime);
    logit("debug", "%-15s: First hit: %d", $ip, $ctime);
  }
}

sub clearold {
  my ($iparef, $ip) = @_;
  my ($timeout) = ($config{'duration'});
  my ($now) = time();

  while (($#$iparef >= 0) && (${$iparef}[0] < ($now - $timeout))) {
    my ($removed) = shift(@$iparef);
    logit("debug", "%-15s: Removed $removed", $ip);
  }
  logit("debug", "%-15s: %d hit(s) stored", $ip, ($#$iparef + 1)); 
}

sub try_ban {
  my ($iparef, $ip) = @_;
  my ($treshold, $chain, $bantime) = ($config{'maxhits'}, $config{'chainname'}, $config{'bantime'});
  
  if ($#$iparef >= ($treshold - 1)) {
    logit("ban", "IP %s gets banned now for %d seconds (%d hits in %d seconds)", $ip, $bantime, $treshold, $$iparef[-1] - $$iparef[0]);

    do_ban($ip, $chain, $bantime);

    $#$iparef = 1;
    $$iparef[0] = "BANNED";
    $$iparef[1] = time() + $bantime;
  }
}

sub do_ban {
  my ($ip, $chain, $bantime) = @_;
  my ($it) = IPTables::IPv4::init('filter');

  my (%newrule) = (
      source => $ip,
      jump => 'DROP',
      );

  $it->append_entry($chain, \%newrule) || shut_down("Insertion of ban-rule into $chain failed: $!");
  $it->commit();
}

sub init_iptable {
  my ($it) = IPTables::IPv4::init('filter');
  my ($chain, $port, $bofh) = ($config{'chainname'}, $config{'port'}, $config{'bofh'});
  my ($state, $rule);

  if ($it->is_chain($chain)) {
    logit("error", "Chain %s exists - flushing entries", $chain);
    $it->flush_entries($chain);
  } else {
    logit("info", "Creating chain %s to store blacklisted IPs", $chain);
    $it->create_chain($chain);
  }

  my ($cicrc) = clear_input_chain($it, $chain);
  shut_down($cicrc) if ($cicrc ne "");

  if ($bofh) {
    $state = ['NEW', 'ESTABLISHED', 'RELATED']
  } else {
    $state = ['NEW']
  }

  my (%newrule) = (
      protocol => "TCP",
      'destination-port' => $port,
      matches => ['state'],
      state => $state,
      jump => $chain,
      );

  logit("info", "Adding INPUT-rule which redirects to %s", $chain);

  $it->insert_entry('INPUT', \%newrule, 1) || shut_down("Insertion of new rule in INPUT chain failed: $!");
  $it->commit();
}

sub clear_input_chain {
  my ($it, $chain) = @_;
  my (@inputr) = $it->list_rules('INPUT');

  my ($rule);
  foreach $rule (@inputr) {
    if ($rule->{jump} eq $chain) {
      logit("debug", "Deleting rule in INPUT chain which jumps to %s", $chain);
      $it->delete_entry('INPUT', $rule) || return("Deletion of rule in INPUT chain failed: $!");
    }
  }
  return("");
}

sub logit {
  my ($priority, $message, @strings) = @_;
  my ($debug, $status, $bans, $info) = ($config{'logdebug'}, $config{'logstatus'}, $config{'logbans'}, $config{'loginfos'});
  my ($timestamp) = strftime("%d.%m.%Y %H:%M:%S", localtime(time()));

  if ((($priority eq "debug") && ($debug)) 
      || (($priority eq "status") && ($status)) 
      || (($priority eq "ban") && ($bans))
      || (($priority eq "info") && ($info))
      || ($priority eq "error")) {
    $message = "$timestamp: $message\n";
    printf(LOG $message, @strings);
  }
}

sub open_log {
  my ($logfile) = ($config{'outputlog'});
  open(LOG, ">>$logfile") || die("Failed to open logfile $logfile: $!\n");
  select(LOG);
  $|=1;
}

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

  #Datetime: $1, IP: $3
  if ($line =~ /^([a-zA-Z]{3}\s+[0-9]{1,2}\s+([0-9]{2}:){2}[0-9]{2}).*\([a-zA-Z0-9\-\.]+\[(([0-9]{1,3}\.){3}[0-9]{1,3})\]\):\ FTP\ session\ opened\.$/) {
    my ($ctime, $ip) = ($1, $3);
    $ctime = parsedate($ctime);
    return($ctime, $ip);
  }
}

sub shut_down {
  my ($reason) = @_;
  my ($chain) = $config{'chainname'};
  my ($it) = IPTables::IPv4::init('filter');

  $reason = "Shutting down: $reason";
  
  logit("error", $reason);

  my ($cicrc) = clear_input_chain($it, $chain);
  logit("error", "Shutting down: %s", $cicrc) if ($cicrc ne "");

  if ($it->is_chain($chain)) {
    $it->flush_entries($chain) || logit("error", "Shutting down: Failed to flush entries of %s: %s", $chain, $!);
    $it->delete_chain($chain) || logit("error", "Shutting down: Failed to delete chain %s: %s", $chain, $!);
  }

  $it->commit();
  close(LOG);
  exit;
}

sub handle_signal {
  my ($signame) = @_;
  shut_down("Signal SIG$signame received");
}

sub init_sighandlers {
  $SIG{INT} = \&handle_signal;
  $SIG{ABRT} = \&handle_signal;
  $SIG{TERM} = \&handle_signal;
}

             reply	other threads:[~2003-07-06 18:59 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-07-06 18:59 Mark [this message]
  -- strict thread matches above, loose matches on Subject: below --
2011-03-28 11:50 error message folkert
2010-01-06 23:23 Carles Pina i Estany
2010-01-07 21:42 ` Robert Millan
2005-02-06  3:03 btinsley
2004-10-20 23:35 John
2004-10-21  7:09 ` Kay Sievers
2003-08-01 19:47 Error Message Mark Trottier
2003-08-01 20:20 ` Alan Cox
2003-07-06 22:48 error message George Vieira
2003-04-18 21:32 Error_message dhd

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200307061459.42268.markryan@cfl.rr.com \
    --to=markryan@cfl.rr.com \
    --cc=netfilter@lists.netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.