mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-28 11:43:25 +02:00
Guardian Paket angefangen, zum Testen muss Snort funktionieren ...
git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@720 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8
This commit is contained in:
33
config/guardian/guardian.conf
Normal file
33
config/guardian/guardian.conf
Normal file
@@ -0,0 +1,33 @@
|
||||
# The machines IP address that is visable to the internet
|
||||
# If this is left undefined, then guardian will attempt to get the information
|
||||
# from ifconfig, as long as it has an interface to use. This would be useful
|
||||
# for people on ppp links, or dhcp machines, or if you are lazy :)
|
||||
# HostIpAddr
|
||||
|
||||
# Here we define the interface which we will use to guess the IP address, and
|
||||
# block incoming offending packets. This is the only option that is required
|
||||
# for guardian to run. If the rest are undefined, guardian will use the default.
|
||||
Interface ppp0
|
||||
|
||||
# The last octet of the ip address, which gives us the gateway address.
|
||||
HostGatewayByte 1
|
||||
|
||||
# Guardian's log file
|
||||
LogFile /var/log/guardian/guardian.log
|
||||
|
||||
# Snort's alert file. This can be the snort.alert file, or a syslog file
|
||||
# There might be some snort alerts that get logged to syslog which guardian
|
||||
# might not see..
|
||||
AlertFile /var/log/snort/alert
|
||||
|
||||
# The list of ip addresses to ignore
|
||||
IgnoreFile /var/ipfire/guardian.ignore
|
||||
|
||||
# This is a list of IP addresses on the current host, in case there is more
|
||||
# than one. If this file doesn't exist, then it will assume you want to run
|
||||
# with the default setup (machine's ip address, and broadcast/network).
|
||||
TargetFile /var/ipfire/guardian.target
|
||||
|
||||
# The time in seconds to keep a host blocked. If undefined, it defaults to
|
||||
# 99999999, which basicly disables the feature.
|
||||
TimeLimit 86400
|
||||
374
config/guardian/guardian.pl
Normal file
374
config/guardian/guardian.pl
Normal file
@@ -0,0 +1,374 @@
|
||||
#!/usr/bin/perl
|
||||
# V 1.7
|
||||
# Read the readme file for changes
|
||||
#
|
||||
|
||||
$OS=`uname`;
|
||||
chomp $OS;
|
||||
print "OS shows $OS\n";
|
||||
|
||||
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;
|
||||
}
|
||||
&load_conf;
|
||||
&sig_handler_setup;
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
$networkaddr = $hostipaddr;
|
||||
$networkaddr =~ s/\d+$/0/;
|
||||
$gatewayaddr = $hostipaddr;
|
||||
$gatewayaddr =~ s/\d+$/$hostgatewaybyte/;
|
||||
$broadcastaddr = $hostipaddr;
|
||||
$broadcastaddr =~ s/\d+$/255/;
|
||||
&build_ignore_hash;
|
||||
|
||||
# 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);
|
||||
|
||||
if ( -e $targetfile ) {
|
||||
&load_targetfile;
|
||||
}
|
||||
|
||||
if (!defined($opt_d)) {
|
||||
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.
|
||||
# this is the same as a tail -f :)
|
||||
$counter=0;
|
||||
for (;;) {
|
||||
sleep 1;
|
||||
if (seek(ALERT,0,1)){
|
||||
while (<ALERT>) {
|
||||
chop;
|
||||
if (/snort/) { #syslog file
|
||||
if (defined($opt_d)) {print "$_\n";}
|
||||
# This is *much* cleaner, and should work on all systems
|
||||
@foo=split(/\s+/,$_);
|
||||
($junk,$reason) = split (/\]:/,$_,2);
|
||||
@array=();
|
||||
foreach $str (@foo) {
|
||||
if ($str=~/(\d+\.\d+\.\d+\.\d+)/) {
|
||||
$array[$#array+1]=$1;
|
||||
# write_log ("Found $array[$#array]\n");
|
||||
}
|
||||
}
|
||||
if ($array[1] eq "") { $array[1]=0; }
|
||||
# this should work if snort didn't report the target address.
|
||||
# $array[1] should be the target address (portscans don't show this)
|
||||
&checkem ($array[0], $array[1], $reason);
|
||||
} else { # snort.alert type file for backwards compat
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub checkem {
|
||||
my ($source, $dest,$type) = @_;
|
||||
my $flag=0;
|
||||
my $date = localtime();
|
||||
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("$date: ");
|
||||
&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) {
|
||||
&write_log("$date: ");
|
||||
&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 ipchain {
|
||||
my ($source, $dest, $type) = @_;
|
||||
&write_log ("$source\t$type\n");
|
||||
if ($hash{$source} eq "") {
|
||||
&write_log ("Running '$blockpath $source $interface'\n");
|
||||
system ("$blockpath $source $interface");
|
||||
$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;
|
||||
|
||||
# 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 (<IGNORE>) {
|
||||
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 (<CONF>) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub write_log {
|
||||
my $message = $_[0];
|
||||
if (defined($opt_d)) { # we are in debug mode, and not daemonized
|
||||
print STDOUT $message;
|
||||
} else {
|
||||
open (LOG, ">>$logfile");
|
||||
print LOG $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";
|
||||
}
|
||||
}
|
||||
|
||||
sub get_ip {
|
||||
my ($interface) = $_[0];
|
||||
my $ip;
|
||||
open (IFCONFIG, "/bin/netstat -iee |grep $interface -A7 |");
|
||||
while (<IFCONFIG>) {
|
||||
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{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});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub call_unblock {
|
||||
my ($source, $message) = @_;
|
||||
&write_log ("$message");
|
||||
system ("$unblockpath $source $interface");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
sub load_targetfile {
|
||||
my $count = 0;
|
||||
open (TARG, "$targetfile") or die "Cannot open $targetfile\n";
|
||||
while (<TARG>) {
|
||||
chop;
|
||||
next if (/\#/); #skip comments
|
||||
next if (/^\s*$/); # and blank lines
|
||||
$targethash{$_}=1;
|
||||
$count++;
|
||||
}
|
||||
close (TARG);
|
||||
print "Loaded $count addresses from $targetfile\n";
|
||||
}
|
||||
12
config/guardian/guardian_block.sh
Normal file
12
config/guardian/guardian_block.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this is a sample block script for guardian. This should work with ipchains.
|
||||
# This command gets called by guardian as such:
|
||||
# guardian_block.sh <source_ip> <interface>
|
||||
# and the script will issue a command to block all traffic from that source ip
|
||||
# address. The logic of weither or not it is safe to block that address is
|
||||
# done inside guardian itself.
|
||||
source=$1
|
||||
interface=$2
|
||||
|
||||
/sbin/iptables -I INPUT -s $source -i $interface -j DROP
|
||||
10
config/guardian/guardian_unblock.sh
Normal file
10
config/guardian/guardian_unblock.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this is a sample unblock script for guardian. This should work with ipchains.
|
||||
# This command gets called by guardian as such:
|
||||
# unblock.sh <source_ip> <interface>
|
||||
# and the script will issue a command to remove the block that was created with # block.sh address.
|
||||
source=$1
|
||||
interface=$2
|
||||
|
||||
/sbin/iptables -D INPUT -s $source -i $interface -j DROP
|
||||
Reference in New Issue
Block a user