]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/commitdiff
Guardian Paket angefangen, zum Testen muss Snort funktionieren ...
authormaniacikarus <maniacikarus@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Wed, 25 Jul 2007 18:02:01 +0000 (18:02 +0000)
committermaniacikarus <maniacikarus@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Wed, 25 Jul 2007 18:02:01 +0000 (18:02 +0000)
git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@720 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8

config/cfgroot/graphs.pl
config/guardian/guardian.conf [new file with mode: 0644]
config/guardian/guardian.pl [new file with mode: 0644]
config/guardian/guardian_block.sh [new file with mode: 0644]
config/guardian/guardian_unblock.sh [new file with mode: 0644]
config/rootfiles/packages/guardian [new file with mode: 0644]
lfs/guardian [new file with mode: 0644]
src/paks/guardian/install.sh [new file with mode: 0644]
src/paks/guardian/uninstall.sh [new file with mode: 0644]
src/paks/guardian/update.sh [new file with mode: 0644]

index 141819bf38ccaad472d9bf6a6d82a43eeed56a93..3390811157425eddebad7410bc7829678799c113 100644 (file)
@@ -268,7 +268,7 @@ sub updateifgraph {
   "GPRINT:incoming:MIN:$Lang::tr{'in'}\\:%8.3lf %sBps",
   "GPRINT:incoming:LAST:$Lang::tr{'in'}\\:%8.3lf %sBps\\j",
   "GPRINT:outgoing:MAX:$Lang::tr{'out'}\\:%8.3lf %sBps",
-  "GPRINT:outgoing:AVERAGE:$$Lang::tr{'out'}\\:%8.3lf %sBps",
+  "GPRINT:outgoing:AVERAGE:$Lang::tr{'out'}\\:%8.3lf %sBps",
   "GPRINT:outgoing:MIN:$Lang::tr{'out'}\\:%8.3lf %sBps",
   "GPRINT:outgoing:LAST:$Lang::tr{'out'}\\:%8.3lf %sBps\\j");
   $ERROR = RRDs::error;
diff --git a/config/guardian/guardian.conf b/config/guardian/guardian.conf
new file mode 100644 (file)
index 0000000..9181496
--- /dev/null
@@ -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
diff --git a/config/guardian/guardian.pl b/config/guardian/guardian.pl
new file mode 100644 (file)
index 0000000..d58fc02
--- /dev/null
@@ -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";
+}
diff --git a/config/guardian/guardian_block.sh b/config/guardian/guardian_block.sh
new file mode 100644 (file)
index 0000000..a35c58a
--- /dev/null
@@ -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
diff --git a/config/guardian/guardian_unblock.sh b/config/guardian/guardian_unblock.sh
new file mode 100644 (file)
index 0000000..ed14d96
--- /dev/null
@@ -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
diff --git a/config/rootfiles/packages/guardian b/config/rootfiles/packages/guardian
new file mode 100644 (file)
index 0000000..4564d96
--- /dev/null
@@ -0,0 +1,4 @@
+usr/local/bin/guardian.pl
+usr/local/bin/guardian_block.sh
+usr/local/bin/guardian_unblock.sh
+var/ipfire/guardian/guardian.conf
diff --git a/lfs/guardian b/lfs/guardian
new file mode 100644 (file)
index 0000000..4109c0a
--- /dev/null
@@ -0,0 +1,70 @@
+###############################################################################
+# This file is part of the IPCop Firewall.                                    #
+#                                                                             #
+# IPCop 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.                                         #
+#                                                                             #
+# IPCop 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 IPCop; if not, write to the Free Software                        #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA    #
+#                                                                             #
+# Makefiles are based on LFSMake, which is                                    #
+# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com>                        #
+#                                                                             #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+VER        = ipfire
+
+THISAPP    = guardian-$(VER)
+DIR_APP    = $(DIR_SRC)/$(THISAPP)
+TARGET     = $(DIR_INFO)/$(THISAPP)
+PROG       = guardian
+PAK_VER    = 1.7
+
+DESCDE     = "Guardian ist Sicherheitstool, welches das Snort IDS Log auswertet und IP´s mit Hilfe von iptables block."
+DESCEN     = "Guardian is a security tool which will issue commands to the OS to block ip addresses which attacks may be coming from. Guardian requires an IDS (Intrusion detection system), and currently only works with snort."
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects =
+
+install : $(TARGET)
+
+check : 
+
+download :
+
+md5 : 
+
+dist: 
+       @$(PAK)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
+       @$(PREBUILD)
+       -mkdir -p /var/ipfire/guardian/
+       -mkdir -p /var/log/guardian/
+       touch /var/log/guardian/guardian.log
+       install -v -m 755 $(DIR_SRC)/config/guardian/guardian.conf /var/ipfire/guardian/
+       install -v -m 755 $(DIR_SRC)/config/guardian/guardian.pl /usr/local/bin/
+       install -v -m 755 $(DIR_SRC)/config/guardian/guardian_block.sh /usr/local/bin/
+       install -v -m 755 $(DIR_SRC)/config/guardian/guardian_unblock.sh /usr/local/bin/
+       @$(POSTBUILD)
diff --git a/src/paks/guardian/install.sh b/src/paks/guardian/install.sh
new file mode 100644 (file)
index 0000000..a47a783
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+. /opt/pakfire/lib/functions.sh
+
+extract_files
diff --git a/src/paks/guardian/uninstall.sh b/src/paks/guardian/uninstall.sh
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/paks/guardian/update.sh b/src/paks/guardian/update.sh
new file mode 100644 (file)
index 0000000..e69de29