#!/usr/bin/perl # # filtermgr # Script zum dynamischen Verwalten von Filterregeln in Zusammenarbeit # mit portsentry und iptables # # R.Schulze, 27.8.2002 use strict; ############################################################################### # Basisverzeichnis (da, wo das Script liegt) my $BASE_DIR="/usr/local/portsentry"; # Datei zum Speichern der IPs und Timestamps my $DB_FILE="filtermgr.db"; # PortSentrys Block Datei my $BLOCK_FILE="portsentry.blocked"; # Pfad zu IpTables my $IPTABLES_CMD="/usr/sbin/iptables"; # Timeout einer Sperrung in Sekunden my $BLOCK_TIMEOUT=60*10; ############################################################################### if(!-e $IPTABLES_CMD) { &LogError("[main]: \"$IPTABLES_CMD\" nicht gefunden."); die("\"$IPTABLES_CMD\" nicht gefunden.\nBitte korrekten Pfad zu iptables angeben.\n"); } if( (scalar(@ARGV)>0) && ($ARGV[0]=~m/^(\-[adl])$/) ) { if($ARGV[0] eq "-a") { if( (defined($ARGV[1])) && ($ARGV[1]=~m/^([0-9.]*)$/) ) { &AddEntry($ARGV[1]); } else { &PrintUsage(); } } elsif($ARGV[0] eq "-d") { &DelOldTargets(); } elsif($ARGV[0] eq "-l") { &PrintTargets(); } else { &PrintUsage(); } } else { PrintUsage(); } exit(0); ############################################################################### # AddEntry # fuegt der Datenbank einen neuen Eintrag hinzu ############################################################################### sub AddEntry { my $Target=shift; my %Table; if(-e "$BASE_DIR/$DB_FILE") { &ReadDB(\%Table) || return; } if(defined($Table{$Target})) { return 1; } $Table{$Target}=time(); &WriteDB(\%Table) || return; &BlockTarget($Target); return 1; } ############################################################################### BlockTarget # BlockTarget # erzeugt eine Regel, die das Ziel blocken soll ############################################################################### sub BlockTarget { my $Target=shift; my $Cmd="$IPTABLES_CMD -I INPUT -s $Target -j DROP"; if(system($Cmd)) { &LogError("[BlockTarget]: \"$Cmd\" ist fehlgeschlagen."); return; } return 1; } ############################################################################### BlockTarget # UnBlockTarget # loescht die Regel, die das Ziel blocken soll ############################################################################### sub UnBlockTarget { my $Target=shift; my $Cmd="$IPTABLES_CMD -D INPUT -s $Target -j DROP"; if(system($Cmd)) { &LogError("[UnBlockTarget]: \"$Cmd\" ist fehlgeschlagen."); return; } return 1; } ############################################################################### # DelOldTargets # loescht alle alten Regeln ############################################################################### sub DelOldTargets { my %Table; my $Now=time(); (-e "$BASE_DIR/$DB_FILE") || return 1; &ReadDB(\%Table) || return; foreach my $IP(keys(%Table)) { if((int($Table{$IP})+$BLOCK_TIMEOUT)<$Now) { delete($Table{$IP}); &UnBlockTarget($IP); &DeleteTargetFromBlockfiles($IP); } } WriteDB(\%Table) || return; return 1; } ############################################################################### # DeleteTargetFromBlockfiles # loescht einen Eintrag einer IP aus den Blockfiles ############################################################################### sub DeleteTargetFromBlockfiles { my $Target=shift; my @Files; opendir(DIR,$BASE_DIR) || return &LogError("[DeleteTargetFromBlockfiles]: opendir ist fehlgeschlagen ($!).\n"); while(my $Entry=readdir(DIR)) { next if $Entry!~m/$BLOCK_FILE/; push(@Files,$Entry); } closedir(DIR); foreach my $File(@Files) { my @Lines; open(BFILE,"+<$BASE_DIR/$File") || return &LogError("[DeleteTargetFromBlockfile]: Konnte \"$BASE_DIR/$File\" nicht zum Lesen/Schreiben oeffnen.($!)\n"); flock(BFILE,2); while(my $Line=) { $Line=~s/\n//; next if ($Line=~m/\/$Target/); push(@Lines,$Line); } seek(BFILE,0,0); truncate(BFILE,0); foreach(@Lines) { print BFILE "$_\n"; } close(BFILE); } return 1; } ############################################################################### # PrintTargets # schreibt eine Tabelle mit den geblockten IPs und einigen Infos ############################################################################### sub PrintTargets { my %Table; &ReadDB(\%Table); print "Liste der geblockten IPs:\n\n"; foreach my $Entry(keys(%Table)) { my($sec,$min,$hour,$mday,$mon,$year)=(localtime($Table{$Entry}))[0..5]; $mon++; $year+=1900; print "- ".$Entry." : geblockt seit $mday\.$mon\.$year, $hour\:$min\:$sec\n"; } } ############################################################################### # PrintUsage ############################################################################### sub PrintUsage { print "\n"; print<) { $Line=~s/\n//; my($IP,$Timestamp)=split(/\:/,$Line); if( ($IP=~m/^([0-9\.]+)$/) && ($Timestamp=~m/^([0-9]+)$/) ) { $Table{$IP}=$Timestamp; } } close(FILE); %$Buffer=%Table; return 1; } ############################################################################### # WriteDB # schreibt die Daten eines Hashes in die Datenbank ############################################################################### sub WriteDB { my $Table=shift; open(FILE,">$BASE_DIR/$DB_FILE") || return &LogError("[WriteDB]: \"$BASE_DIR/$DB_FILE\" konnte nicht zum Schreiben geoeffnet werden ($!)"); flock(FILE,2); while(my($IP,$Timestamp)=each(%$Table)) { print FILE $IP.":".$Timestamp."\n"; } close(FILE); return 1; } ############################################################################### # LogError ############################################################################### sub LogError { my $Err=shift; open(LOG,">>$BASE_DIR/filtermgr.err") || return; print LOG scalar(localtime(time())).": $Err\n"; close(LOG); return; }