From: maniacikarus Date: Tue, 7 Apr 2009 18:45:50 +0000 (+0200) Subject: Fixed Guardian for new snort X-Git-Tag: v2.5-beta1~44 X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=commitdiff_plain;h=6579aab26777a1a21932aec0eb629d9f55716d3e Fixed Guardian for new snort --- diff --git a/config/guardian/guardian.pl b/config/guardian/guardian.pl index 82e5c58cba..5c421868b9 100644 --- a/config/guardian/guardian.pl +++ b/config/guardian/guardian.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -# V 1.7 +# based on V 1.7 guardian enhanced for IPFire and snort 2.8 # Read the readme file for changes # # Enhanced for IPFire by IPFire Team @@ -15,12 +15,12 @@ require 'getopts.pl'; &Getopts ('hc:d'); if (defined($opt_h)) { - print "Guardian v1.7 \n"; - print "guardian.pl [-hd] <-c config>\n"; - print " -h shows help\n"; - print " -d run in debug mode (doesn't fork, output goes to STDOUT)\n"; - print " -c specifiy a configuration file other than the default (/etc/guardian.conf)\n"; - exit; + print "Guardian v1.7 \n"; + print "guardian.pl [-hd] <-c config>\n"; + print " -h shows help\n"; + print " -d run in debug mode (doesn't fork, output goes to STDOUT)\n"; + print " -c specifiy a configuration file other than the default (/etc/guardian.conf)\n"; + exit; } &load_conf; &sig_handler_setup; @@ -28,8 +28,8 @@ if (defined($opt_h)) { print "My ip address and interface are: $hostipaddr $interface\n"; if ($hostipaddr !~ /\d+\.\d+\.\d+\.\d+/) { - print "This ip address is bad : $hostipaddr\n"; - die "I need a good host ipaddress\n"; + print "This ip address is bad : $hostipaddr\n"; + die "I need a good host ipaddress\n"; } $networkaddr = $hostipaddr; @@ -43,354 +43,370 @@ $broadcastaddr =~ s/\d+$/255/; # This is the target hash. If a packet was destened to any of these, then the # sender of that packet will get denied, unless it is on the ignore list.. -%targethash = ( "$networkaddr" => 1, - "$broadcastaddr" => 1, - "0" => 1, # This is what gets sent to &checkem if no - # destination was found. - "$hostipaddr" => 1); +%targethash = ( "$networkaddr" => 1, + "$broadcastaddr" => 1, + "0" => 1, # This is what gets sent to &checkem if no + # destination was found. + "$hostipaddr" => 1); %sshhash = (); if ( -e $targetfile ) { - &load_targetfile; + &load_targetfile; } if (!defined($opt_d)) { - print "Becoming a daemon..\n"; - &daemonize; + print "Becoming a daemon..\n"; + &daemonize; } else { print "Running in debug mode..\n"; } open (ALERT, $alert_file) or die "can't open alert file: $alert_file: $!\n"; -seek (ALERT, 0, 2); # set the position to EOF. +seek (ALERT, 0, 2); # set the position to EOF. # this is the same as a tail -f :) $counter=0; open (ALERT2, "/var/log/messages" ) or die "can't open /var/log/messages: $!\n"; -seek (ALERT2, 0, 2); # set the position to EOF. +seek (ALERT2, 0, 2); # set the position to EOF. # this is the same as a tail -f :) -for (;;) { - sleep 1; - if (seek(ALERT,0,1)){ - while () { - chop; - if (defined($opt_d)) {print "$_\n";} - if (/\[\*\*\]\s+(.*)\s+\[\*\*\]/){ - $type=$1; - } - if (/(\d+\.\d+\.\d+\.\d+):\d+ -\> (\d+\.\d+\.\d+\.\d+):\d+/) { - &checkem ($1, $2, $type); - } - if ($_=~/Portscan/) { - my @array=split(/ /,$_);&checkem ($array[5], $hostipaddr, "Portscan was detected.");} - } - } - - sleep 1; - if (seek(ALERT2,0,1)){ - while () { - chop; - if ($_=~/.*sshd.*Failed password for root from.*/) { - my @array=split(/ /,$_);&checkssh ($array[10], "possible SSH-Bruteforce Attack");} - } - } - # Run this stuff every 30 seconds.. - if ($counter == 30) { - &remove_blocks; # This might get moved elsewhere, depending on how much load - # it puts on the system.. - &check_log_name; - $counter=0; - } else { $counter=$counter+1; } +for (;;) { + sleep 1; + if (seek(ALERT,0,1)){ + while () { + chop; + if (defined($opt_d)) { + print "$_\n"; + } + if (/\[\*\*\]\s+(.*)\s+\[\*\*\]/){ + $type=$1; + } + if (/(\d+\.\d+\.\d+\.\d+):\d+ -\> (\d+\.\d+\.\d+\.\d+):\d+/) { + &checkem ($1, $2, $type); + } + if (/(\d+\.\d+\.\d+\.\d+)+ -\> (\d+\.\d+\.\d+\.\d+)+/) { + &checkem ($1, $2, $type); + } + } + } + + sleep 1; + if (seek(ALERT2,0,1)){ + while () { + chop; + if ($_=~/.*sshd.*Failed password for root from.*/) { + my @array=split(/ /,$_);&checkssh ($array[10], "possible SSH-Bruteforce Attack");} + } + } + +# Run this stuff every 30 seconds.. + if ($counter == 30) { + &remove_blocks; # This might get moved elsewhere, depending on how much load + # it puts on the system.. + &check_log_name; + $counter=0; + } else { + $counter=$counter+1; + } } sub check_log_name { - my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, - $atime,$mtime,$ctime,$blksize,$blocks) = stat($alert_file); - if ($size < $previous_size) { # The filesize is smaller than last - close (ALERT); # we checked, so we need to reopen it - open (ALERT, "$alert_file"); # This should still work in our main while - $previous_size=$size; # loop (I hope) - write_log ("Log filename changed. Reopening $alert_file\n"); - } else { - $previous_size=$size; - } + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) = stat($alert_file); + if ($size < $previous_size) { # The filesize is smaller than last + close (ALERT); # we checked, so we need to reopen it + open (ALERT, "$alert_file"); # This should still work in our main while + $previous_size=$size; # loop (I hope) + write_log ("Log filename changed. Reopening $alert_file\n"); + } else { + $previous_size=$size; + } } - + sub checkem { - my ($source, $dest,$type) = @_; - my $flag=0; - return 1 if ($source eq $hostipaddr); # this should prevent is from nuking - # ourselves - return 1 if ($source eq $gatewayaddr); # or our gateway - if ($ignore{$source} == 1) { # check our ignore list.. - &write_log("$source\t$type\n"); - &write_log("Ignoring attack because $source is in my ignore list\n"); - return 1; - } - # if the offending packet was sent to us, the network, or the broadcast, then - if ($targethash{$dest} == 1) { - &ipchain ($source, $dest, $type); - } - # you will see this if the destination was not in the $targethash, and the - # packet was not ignored before the target check.. - else { - &write_log ("Odd.. source = $source, dest = $dest - No action done.\n"); - if (defined ($opt_d)) { - foreach $key (keys %targethash) { - &write_log ("targethash{$key} = $targethash{$key}\n"); - } - } - } + my ($source, $dest,$type) = @_; + my $flag=0; + + return 1 if ($source eq $hostipaddr); + # this should prevent is from nuking ourselves + + return 1 if ($source eq $gatewayaddr); # or our gateway + if ($ignore{$source} == 1) { # check our ignore list.. + &write_log("$source\t$type\n"); + &write_log("Ignoring attack because $source is in my ignore list\n"); + return 1; + } + +# if the offending packet was sent to us, the network, or the broadcast, then + if ($targethash{$dest} == 1) { + &ipchain ($source, $dest, $type); + } +# you will see this if the destination was not in the $targethash, and the +# packet was not ignored before the target check.. + else { + &write_log ("Odd.. source = $source, dest = $dest - No action done.\n"); + if (defined ($opt_d)) { + foreach $key (keys %targethash) { + &write_log ("targethash{$key} = $targethash{$key}\n"); + } + } + } } sub checkssh { - my ($source,$type) = @_; - my $flag=0; - return 1 if ($source eq $hostipaddr); # this should prevent is from nuking - # ourselves - return 1 if ($source eq $gatewayaddr); # or our gateway - if ($sshhash{$dest} eq "" ){ $sshhash{$dest} = 1; } - if ($sshhash{$dest} >= 3 ) { - &write_log ("source = $source, count $sshhash{$dest} - blocking for ssh attack.\n"); - &ipchain ($source, "", $type); - } - # you will see this if the destination was not in the $sshhash, and the - # packet was not ignored before the target check.. - else { - &write_log ("Odd.. source = $source, ssh count only $sshhash{$dest} - No action done.\n"); - if (defined ($opt_d)) { - foreach $key (keys %sshhash) { - &write_log ("sshhash{$key} = %sshhash{$key}\n"); - } - } - $sshhash{$key} = $sshhash{$key}+1; - } + my ($source,$type) = @_; + my $flag=0; + + return 1 if ($source eq $hostipaddr); + # this should prevent is from nuking ourselves + + return 1 if ($source eq $gatewayaddr); # or our gateway + + if ($sshhash{$dest} eq "" ){ + $sshhash{$dest} = 1; + } + if ($sshhash{$dest} >= 3 ) { + &write_log ("source = $source, count $sshhash{$dest} - blocking for ssh attack.\n"); + &ipchain ($source, "", $type); + } +# you will see this if the destination was not in the $sshhash, and the +# packet was not ignored before the target check.. + else { + &write_log ("Odd.. source = $source, ssh count only $sshhash{$dest} - No action done.\n"); + if (defined ($opt_d)) { + foreach $key (keys %sshhash) { + &write_log ("sshhash{$key} = %sshhash{$key}\n"); + } + } + $sshhash{$key} = $sshhash{$key}+1; + } } -sub ipchain { - my ($source, $dest, $type) = @_; - &write_log ("$source\t$type\n"); - if ($hash{$source} eq "") { - &write_log ("Running '$blockpath $source'\n"); - system ("$blockpath $source"); - $hash{$source} = time() + $TimeLimit; - } else { - # We have already blocked this one, but snort detected another attack. So - # we should update the time blocked.. - $hash{$source} = time() + $TimeLimit; - } +sub ipchain { + my ($source, $dest, $type) = @_; + &write_log ("$source\t$type\n"); + if ($hash{$source} eq "") { + &write_log ("Running '$blockpath $source'\n"); + system ("$blockpath $source"); + $hash{$source} = time() + $TimeLimit; + } else { +# We have already blocked this one, but snort detected another attack. So +# we should update the time blocked.. + $hash{$source} = time() + $TimeLimit; + } } - + sub build_ignore_hash { # This would cause is to ignore all broadcasts if it # got set.. However if unset, then the attacker could spoof the packet to make # it look like it came from the network, and a reply to the spoofed packet -# could be seen if the attacker were on the local network. -# $ignore{$networkaddr}=1; +# could be seen if the attacker were on the local network. +# $ignore{$networkaddr}=1; # same thing as above, just with the broadcast instead of the network. # $ignore{$broadcastaddr}=1; - my $count =0; - $ignore{$gatewayaddr}=1; - $ignore{$hostipaddr}=1; - if ($ignorefile ne "") { - open (IGNORE, $ignorefile); - while () { - chop; - next if (/\#/); #skip comments - next if (/^\s*$/); # and blank lines - $ignore{$_}=1; - $count++; - } - close (IGNORE); - print "Loaded $count addresses from $ignorefile\n"; - } else { - print "No ignore file was loaded!\n"; - } + my $count =0; + $ignore{$gatewayaddr}=1; + $ignore{$hostipaddr}=1; + if ($ignorefile ne "") { + open (IGNORE, $ignorefile); + while () { + chop; + next if (/\#/); #skip comments + next if (/^\s*$/); # and blank lines + $ignore{$_}=1; + $count++; + } + close (IGNORE); + print "Loaded $count addresses from $ignorefile\n"; + } else { + print "No ignore file was loaded!\n"; + } } sub load_conf { - if ($opt_c eq "") { - $opt_c = "/etc/guardian.conf"; - } - if (! -e $opt_c) { - die "Need a configuration file.. please use to the -c option to name a -configuration file\n"; - } - open (CONF, $opt_c) or die "Cannot read the config file $opt_c, $!\n"; - while () { - chop; - next if (/^\s*$/); #skip blank lines - next if (/^#/); # skip comment lines - if (/LogFile\s+(.*)/) { - $logfile = $1; - } - if (/Interface\s+(.*)/) { - $interface = $1; - } - if (/AlertFile\s+(.*)/) { - $alert_file = $1; - } - if (/IgnoreFile\s+(.*)/) { - $ignorefile = $1; - } - if (/TargetFile\s+(.*)/) { - $targetfile = $1; - } - if (/TimeLimit\s+(.*)/) { - $TimeLimit = $1; - } - if (/HostIpAddr\s+(.*)/) { - $hostipaddr = $1; - } - if (/HostGatewayByte\s+(.*)/) { - $hostgatewaybyte = $1; - } -# if (/ipchainsPath\s+(.*)/) { -# $ipchains_path = $1; -# } - } - if ($interface eq "") { - die "Fatal! Interface is undefined.. Please define it in $opt_o with keyword Interface\n"; - } - if ($alert_file eq "") { - print "Warning! AlertFile is undefined.. Assuming /var/log/snort.alert\n"; - $alert_file="/var/log/snort.alert"; - } - if ($hostipaddr eq "") { - print "Warning! HostIpAddr is undefined! Attempting to guess..\n"; - $hostipaddr = &get_ip($interface); - print "Got it.. your HostIpAddr is $hostipaddr\n"; - } - if ($ignorefile eq "") { - print "Warning! IgnoreFile is undefined.. going with default ignore list (hostname and gateway)!\n"; - } - if ($hostgatewaybyte eq "") { - print "Warning! HostGatewayByte is undefined.. gateway will not be in ignore list!\n"; - } - if ($logfile eq "") { - print "Warning! LogFile is undefined.. Assuming debug mode, output to STDOUT\n"; - $opt_d = 1; - } - if (! -w $logfile) { - print "Warning! Logfile is not writeable! Engaging debug mode, output to STDOUT\n"; - $opt_d = 1; - } - foreach $mypath (split (/:/, $ENV{PATH})) { - if (-x "$mypath/guardian_block.sh") { - $blockpath = "$mypath/guardian_block.sh"; - } - if (-x "$mypath/guardian_unblock.sh") { - $unblockpath = "$mypath/guardian_unblock.sh"; - } - } - if ($blockpath eq "") { - print "Error! Could not find guardian_block.sh. Please consult the README. \n"; - exit; - } - if ($unblockpath eq "") { - print "Warning! Could not find guardian_unblock.sh. Guardian will not be\n"; - print "able to remove blocked ip addresses. Please consult the README file\n"; - } - if ($TimeLimit eq "") { - print "Warning! Time limit not defined. Defaulting to absurdly long time limit\n"; - $TimeLimit = 999999999; - } + if ($opt_c eq "") { + $opt_c = "/etc/guardian.conf"; + } + + if (! -e $opt_c) { + die "Need a configuration file.. please use to the -c option to name a configuration file\n"; + } + + open (CONF, $opt_c) or die "Cannot read the config file $opt_c, $!\n"; + while () { + chop; + next if (/^\s*$/); #skip blank lines + next if (/^#/); # skip comment lines + if (/LogFile\s+(.*)/) { + $logfile = $1; + } + if (/Interface\s+(.*)/) { + $interface = $1; + } + if (/AlertFile\s+(.*)/) { + $alert_file = $1; + } + if (/IgnoreFile\s+(.*)/) { + $ignorefile = $1; + } + if (/TargetFile\s+(.*)/) { + $targetfile = $1; + } + if (/TimeLimit\s+(.*)/) { + $TimeLimit = $1; + } + if (/HostIpAddr\s+(.*)/) { + $hostipaddr = $1; + } + if (/HostGatewayByte\s+(.*)/) { + $hostgatewaybyte = $1; + } + } + + if ($interface eq "") { + die "Fatal! Interface is undefined.. Please define it in $opt_o with keyword Interface\n"; + } + if ($alert_file eq "") { + print "Warning! AlertFile is undefined.. Assuming /var/log/snort.alert\n"; + $alert_file="/var/log/snort.alert"; + } + if ($hostipaddr eq "") { + print "Warning! HostIpAddr is undefined! Attempting to guess..\n"; + $hostipaddr = &get_ip($interface); + print "Got it.. your HostIpAddr is $hostipaddr\n"; + } + if ($ignorefile eq "") { + print "Warning! IgnoreFile is undefined.. going with default ignore list (hostname and gateway)!\n"; + } + if ($hostgatewaybyte eq "") { + print "Warning! HostGatewayByte is undefined.. gateway will not be in ignore list!\n"; + } + if ($logfile eq "") { + print "Warning! LogFile is undefined.. Assuming debug mode, output to STDOUT\n"; + $opt_d = 1; + } + if (! -w $logfile) { + print "Warning! Logfile is not writeable! Engaging debug mode, output to STDOUT\n"; + $opt_d = 1; + } + + foreach $mypath (split (/:/, $ENV{PATH})) { + if (-x "$mypath/guardian_block.sh") { + $blockpath = "$mypath/guardian_block.sh"; + } + if (-x "$mypath/guardian_unblock.sh") { + $unblockpath = "$mypath/guardian_unblock.sh"; + } + } + + if ($blockpath eq "") { + print "Error! Could not find guardian_block.sh. Please consult the README. \n"; + exit; + } + if ($unblockpath eq "") { + print "Warning! Could not find guardian_unblock.sh. Guardian will not be\n"; + print "able to remove blocked ip addresses. Please consult the README file\n"; + } + if ($TimeLimit eq "") { + print "Warning! Time limit not defined. Defaulting to absurdly long time limit\n"; + $TimeLimit = 999999999; + } } sub write_log { - my $message = $_[0]; - my $date = localtime(); - if (defined($opt_d)) { # we are in debug mode, and not daemonized - print STDOUT $message; - } else { - open (LOG, ">>$logfile"); - print LOG $date.": ".$message; - close (LOG); - } + my $message = $_[0]; + my $date = localtime(); + if (defined($opt_d)) { # we are in debug mode, and not daemonized + print STDOUT $message; + } else { + open (LOG, ">>$logfile"); + print LOG $date.": ".$message; + close (LOG); + } } sub daemonize { - my ($home); - if (fork()) { - # parent - exit(0); - } else { - # child - &write_log ("Guardian process id $$\n"); - $home = (getpwuid($>))[7] || die "No home directory!\n"; - chdir($home); # go to my homedir - setpgrp(0,0); # become process leader - close(STDOUT); - close(STDIN); - close(STDERR); - print "Testing...\n"; - } -} + my ($home); + if (fork()) { +# parent + exit(0); + } else { +# child + &write_log ("Guardian process id $$\n"); + $home = (getpwuid($>))[7] || die "No home directory!\n"; + chdir($home); # go to my homedir + setpgrp(0,0); # become process leader + close(STDOUT); + close(STDIN); + close(STDERR); + print "Testing...\n"; + } +} sub get_ip { - my ($interface) = $_[0]; - my $ip; - open (IFCONFIG, "/bin/netstat -iee |grep $interface -A7 |"); - while () { - if ($OS eq "FreeBSD") { - if (/inet (\d+\.\d+\.\d+\.\d+)/) { - $ip = $1; - } - } - if ($OS eq "Linux") { - if (/inet addr:(\d+\.\d+\.\d+\.\d+)/) { - $ip = $1; - } - } - } - close (IFCONFIG); - if ($ip eq "") { die "Couldn't figure out the ip address\n"; } - $ip; -} + my ($interface) = $_[0]; + my $ip; + open (IFCONFIG, "/bin/netstat -iee |grep $interface -A7 |"); + while () { + if ($OS eq "FreeBSD") { + if (/inet (\d+\.\d+\.\d+\.\d+)/) { + $ip = $1; + } + } + if ($OS eq "Linux") { + if (/inet addr:(\d+\.\d+\.\d+\.\d+)/) { + $ip = $1; + } + } + } + close (IFCONFIG); + + if ($ip eq "") { die "Couldn't figure out the ip address\n"; } + $ip; + } sub sig_handler_setup { - $SIG{TERM} = \&clean_up_and_exit; # kill - $SIG{QUIT} = \&clean_up_and_exit; # kill -3 + $SIG{TERM} = \&clean_up_and_exit; # kill + $SIG{QUIT} = \&clean_up_and_exit; # kill -3 # $SIG{HUP} = \&flush_and_reload; # kill -1 } sub remove_blocks { - my $source; - my $time = time(); - foreach $source (keys %hash) { - if ($hash{$source} < $time) { - &call_unblock ($source, "expiring block of $source\n"); - delete ($hash{$source}); - } - } + my $source; + my $time = time(); + foreach $source (keys %hash) { + if ($hash{$source} < $time) { + &call_unblock ($source, "expiring block of $source\n"); + delete ($hash{$source}); + } + } } sub call_unblock { - my ($source, $message) = @_; - &write_log ("$message"); - system ("$unblockpath $source"); + my ($source, $message) = @_; + &write_log ("$message"); + system ("$unblockpath $source"); } sub clean_up_and_exit { - my $source; - &write_log ("received kill sig.. shutting down\n"); - foreach $source (keys %hash) { - &call_unblock ($source, "removing $source for shutdown\n"); - } - exit; + my $source; + &write_log ("received kill sig.. shutting down\n"); + foreach $source (keys %hash) { + &call_unblock ($source, "removing $source for shutdown\n"); + } + exit; } sub load_targetfile { - my $count = 0; - open (TARG, "$targetfile") or die "Cannot open $targetfile\n"; - while () { - chop; - next if (/\#/); #skip comments - next if (/^\s*$/); # and blank lines - $targethash{$_}=1; - $count++; - } - close (TARG); - print "Loaded $count addresses from $targetfile\n"; + my $count = 0; + open (TARG, "$targetfile") or die "Cannot open $targetfile\n"; + while () { + chop; + next if (/\#/); #skip comments + next if (/^\s*$/); # and blank lines + $targethash{$_}=1; + $count++; + } + close (TARG); + print "Loaded $count addresses from $targetfile\n"; }