changeset 13:fc053b001027

Improved reporting and documentation.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 14 Aug 2009 02:58:52 +0300
parents d6da1a6567f8
children 3d18fdeabf90
files README maltfilter
diffstat 2 files changed, 67 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/README	Fri Aug 14 01:26:29 2009 +0300
+++ b/README	Fri Aug 14 02:58:52 2009 +0300
@@ -67,3 +67,9 @@
 settings to enable it, for example in Debian/Ubuntu you can use rcconf(8)
 or chkconfig(8).
 
+Reports
+=======
+Automatic report generation can be enabled from configuration.
+You can also run "full" report generation via the "-f" option, in this
+special mode, no automatic weeding is performed, resulting in
+more data being shown.
--- a/maltfilter	Fri Aug 14 01:26:29 2009 +0300
+++ b/maltfilter	Fri Aug 14 02:58:52 2009 +0300
@@ -54,6 +54,7 @@
 #############################################################################
 ### Script code
 #############################################################################
+my $report = 0;
 my @scanfiles = ();
 my @noblock_ips = ();
 my %filehandles = ();
@@ -215,6 +216,9 @@
 
 sub weed_entries()
 {
+  # Don't weed in report mode.
+  return if ($report);
+
   foreach my $mip (keys %iplist) {
     if (defined($iplist{$mip})) {
       if ($iplist{$mip} >= 0) {
@@ -297,6 +301,16 @@
   return $_[0] ? "</b>" : "";
 }
 
+sub pe($$)
+{
+  return $_[0] ? "<$_[1]>" : "";
+}
+
+sub getIP($$)
+{
+  return $_[0] ? "<a href=\"http://whois.domaintools.com/$_[1]\">$_[1]</a>" : $_[1];
+}
+
 sub generate_status($$)
 {
   my $filename = shift;
@@ -304,7 +318,6 @@
   
   return unless ($filename ne "");
 
-  mlog(-1, "dumping status '$filename'\n");
   open(STATUS, ">", $filename) or die("Could not open '".$filename."'!\n");
   my $f = \*STATUS;
   my $mtime = scalar localtime();
@@ -325,10 +338,24 @@
 
 
   printH($m, $f, 1, "Maltfilter v$progversion status report");
-  printP($m, $f, "Generated: ".$mtime."\n");
+  my $val = $settings{"WEEDPERIOD"};
+  my $period;
 
-  printH($m, $f, 2, "Blocked");
+  if ($val > 30 * 24) {
+    $period = sprintf("%1.1f months", $val / (30.0 * 24.0));
+  } elsif ($val > 24 * 7) {
+    $period = sprintf("%1.1f weeks", $val / 24);
+  } elsif ($val > 24) {
+    $period = sprintf("%d days", $val / 24);
+  } else {
+    $period = sprintf("%d hours", $val);
+  }
 
+  printP($m, $f,
+  "Generated ".bb($m).$mtime.eb($m).". Data computed from ".
+  ($report ? "complete logfile scan" : "a period of last $period").".\n");
+
+  printH($m, $f, 2, $report ? "Detailed report" : "Blocked entries");
   printElem($m, $f, "<table>\n<tr>". "<th>Hits</th><th>IP-address</th><th>Date of last hit</th><th>Reason(s)</th>"."</tr>\n");
   my $nexcluded = 0;
   my $ntotal = 0;
@@ -337,12 +364,20 @@
 
     printElem($m, $f, " <tr>");
     printTD($m, $f, sprintf("%-10d", $hitcount{$mip}));
-    printTD($m, $f, sprintf("%-15s", $mip));
+    printTD($m, $f, sprintf("%-15s", getIP($m, $mip)));
     printElem(!$m, $f, " : ");
     printTD($m, $f, scalar localtime($iplist{$mip}));
     my @s = ();
     foreach my $cond (sort keys %{$reason{$mip}}) {
-      push(@s, bb($m).$cond.eb($m)." [".$reason_n{$mip}{$cond}." hits] (".$reason{$mip}{$cond}.")");
+      my $str;
+      if ($report) {
+        my @tmp =  reverse(@{$reason{$mip}{$cond}});
+        $#tmp = 5 if ($#tmp > 5);
+        $str = join(" | ", @tmp);
+      } else {
+        $str = $reason{$mip}{$cond};
+      }
+      push(@s, bb($m).$cond.eb($m)." [".$reason_n{$mip}{$cond}." hits] (".$str.")");
     }
     printTD($m, $f, join(", ".($m ? "<br />" : ""), @s));
     printElem($m, $f, "</tr>\n", "\n");
@@ -354,33 +389,34 @@
   " excluded (defined in NOBLOCK_IPS).\n");
 
 
-  printH($m, $f, 2, "All recorded hits in general");
+  printH($m, $f, 2, "Overview of hits in general");
   printP($m, $f, "List of 'hits' of suspicious activity noticed by Maltfilter, but not necessarily acted upon.\n");
   
-  printElem($m, $f, "<table>\n<tr>". "<th>IP-address</th><th># of hits</th>" x 2 ."</tr>\n");
+  my $tmp = "<th>IP-address</th><th># of hits</th><th>Reasons</th>";
+  printElem($m, $f, "<table>\n<tr>". $tmp."<th> </th>".$tmp ."</tr>\n");
   my $hits = 0;
-  my @keys = sort { cmp_ip_hits($a, $b, $hitcount{$a}, $hitcount{$b}) } keys %hitcount;
+  my @keys = sort { cmp_ips($a, $b) } keys %hitcount;
   my $nkeys = scalar @keys;
 
   my $printEntry = sub {
-    printTD($m, $f, sprintf("%-15s", $_[0]));
+    printTD($m, $f, sprintf("%-15s", getIP($m, $_[0])));
+    printElem(!$m, $f, " : ");
+    printTD($m, $f, sprintf("%-8d ", $hitcount{$_[0]}));
     printElem(!$m, $f, " : ");
-    printTD($m, $f, sprintf("%-8d ", $_[1]));
+    my $tmp = join(", ", sort keys %{$reason{$_[0]}});
+    printTD($m, $f, sprintf("%-30s", $tmp));
+    $hits += $hitcount{$_[0]};
   };
 
   my $kmax = $nkeys / 2;
   for (my $i = 0; $i <= $kmax; $i++) {
     printElem($m, $f, " <tr>");
     if ($i < $kmax) {
-      my $mip = $keys[$i];
-      &$printEntry($mip, $hitcount{$mip});
-      $hits += $hitcount{$mip};
+      &$printEntry($keys[$i]);
     }
-    printElem(!$m, $f, " | ");
+    printElem($m, $f, "<th> </th>", " || ");
     if ($i + $kmax + 1 < $nkeys) {
-      my $mip = $keys[$i + $kmax + 1];
-      &$printEntry($mip, $hitcount{$mip});
-      $hits += $hitcount{$mip};
+      &$printEntry($keys[$i + $kmax + 1]);
     }
     printElem($m, $f, "</tr>\n", "\n");
   }
@@ -422,7 +458,13 @@
   my $mcond = $_[4];
   
   my $cnt = $hitcount{$mip}++;
-  if ($cnt >= $settings{"TRESHOLD"} && check_time($mdate)) {
+  $reason_n{$mip}{$mclass}++;
+  if ($report) {
+    push(@{$reason{$mip}{$mclass}}, $mreason);
+  } else {
+    $reason{$mip}{$mclass} = $mreason;
+  }
+  if ($report || ($cnt >= $settings{"TRESHOLD"} && check_time($mdate))) {
     my $pat;
     if (!$mcond) {
       $ignored{$mip}{$mclass} = $mreason;
@@ -436,14 +478,8 @@
         exec_iptables("-I", "INPUT", "1", "-s", $mip, "-j", $settings{"ACTION"});
       }
       $iplist{$mip} = $mdate;
-      $reason{$mip}{$mclass} = $mreason;
-      $reason_n{$mip}{$mclass}++;
     } else {
       # Over treshold, but is added, check if we can update the timedate
-      if ($iplist{$mip} < 0) {
-        $reason{$mip}{$mclass} = $mreason;
-        $reason_n{$mip}{$mclass}++;
-      }
       $iplist{$mip} = $mdate if ($mdate > $iplist{$mip});
     }
   }
@@ -559,7 +595,6 @@
 }
 
 # Test pid file existence
-my $report;
 $pid_file = shift;
 if ($pid_file eq "-f") {
   $report = 1;
@@ -615,6 +650,7 @@
 # Force dry run mode if we are reporting only
 if ($report) {
   $settings{"DRY_RUN"} = 1;
+  $settings{"VERBOSITY"} = 1;
 }
 
 # Clean up certain arrays duplicate entries