#!/usr/local/bin/perl -w my $rcsid = '$Id: iptables.pl,v 1.4 2002/01/28 14:10:10 marceld Exp $'; # ########################################################################################### # # Author: Marcel Dorenbos (based on ideas from Sjaak Schilperoort, donot know where he is now?) # email: M.Dorenbos@concert.net # This script parses the output from IPtables through syslog and beautify the output. Two environment # variables are important to set, to make this work: # $LOCALADDRESS: the IP address of the firewall (if you have more, than it is possible to do this as well, e.g.: # $LOCALADDRESS = "192.168.1.1|102.168.2.1" # These addresses, and 127.0.0.1, are used for coloring the date time stamp if an event is # related to the firewall itself: green, if an accept is seen, red on a drop or reject. # $file: this is the file receiving the syslog information from IPtables. # The script will notice file rotation on $file, it will reopen the new file. # Also, most lines will probably be not interesting and clutter the screen. It is possible to add/extend regular # expression in subroutine kill to filter out these events. They will be in the syslog file, but not shown on # the screen. The example below will filter out LANmanager 'broadcasts' and tftp broadcasts. # MAC addresses are filtered out of the output as well. # Every 25 lines from syslog a status message is sent to the screen, displaying howmany lines have been # killed (discarded). # For this script you need to have Term::ANSIColor, which can be found at CPAN. use Term::ANSIColor qw(:constants); my $LOCALADDRESS = '192.168.117.1'; my $file = "/var/log/iptables"; my $HOST = `hostname`; print $HOST; my $CLEAR = CLEAR; my $RESET = RESET; my $BOLD = BOLD; my $UNDERLINE = UNDERLINE; my $UNDERSCORE = UNDERSCORE; my $BLINK = BLINK; my $REVERSE = REVERSE; my $CONCEALED = CONCEALED; my $BLACK = BLACK; my $RED = RED; my $GREEN = GREEN; my $YELLOW = YELLOW; my $BLUE = BLUE; my $MAGENTA = MAGENTA; my $CYAN = CYAN; my $WHITE = WHITE; my $ON_BLACK = ON_BLACK; my $ON_RED = ON_RED; my $ON_GREEN = ON_GREEN; my $ON_YELLOW = ON_YELLOW; my $ON_BLUE = ON_BLUE; my $ON_MAGENTA = ON_MAGENTA; my $ON_CYAN = ON_CYAN; my $ON_WHITE = ON_WHITE; $debug = 0; $timeout = 5; $alarm = 600; $k = $s = $t = 0; $SIG{'INT'} = 'stats'; $SIG{'ALRM'} = 'wakeup'; alarm($alarm); sub wakeup { $i = (stat($file))[1]; if ($i > 0 && $i != $ino) { $ino = $i; $inochanged = 1; } alarm($alarm); } &wakeup; # read inode and opens file while (1) { if ($inochanged) { &debug("inode ", $ino ? "changed" : "set", " to $i"); print "inode has changed\n"; $inochanged = 0; close(LOG); open(LOG, "<$file"); seek(LOG, -10000, 2); $dummy=; $t = $k = $s = 0; # reset values as well! } $_= ; $nread = length($_); &debug("read $nread chars"); &display; if ( (int($t / 25) * 25) == $t) { ($sec, $min, $hour, $mday, $mon, $year, $wday, $ydat, $isdst) = localtime(); $now = sprintf("M%02d%02d %02d\:%02d\:%02d", 1900 + $year, ++$mon, $mday, $hour, $min, $sec); printf("$now Total: $t Killed: $k (%3.2f%%)\n", 100 * $k / $t); } while (eof) { &debug("EOF"); sleep $timeout; } } sub debug { print "(debug) @_\n" if $debug; } sub display { ($t++, $k++, return) if &kill ; chop($_); # chop off newline s/ws-5085\s//; s/(MAC=\S+) //; s/IN=\s//; s/OUT=\s//; s/Deny /$RED${BOLD}Deny $RESET/; s/Accept /$GREEN${BOLD}Accept $RESET/; if ( /(Accept|Deny).*$LOCALADDRESS|127.0.0.1/ ) { my $color = "$YELLOW$BOLD$ON_RED"; $color = "$BOLD$BLUE$ON_GREEN" if $1 eq "Accept"; my $line = $_; substr($line, 15, 0) = "$RESET"; $_ = "$color$line"; } /RULE (\d+)/; my $rulenr = sprintf("%2.2d",$1); s/RULE \d+/${UNDERLINE}RULE $rulenr$RESET/; s/(SRC=\S+|SPT=\S+)/$BLUE$BOLD$1$RESET/g; s/(DST=\S+|DPT=\S+)/$BLUE$UNDERLINE$1$RESET/g; s/(PROTO=\S+)/$BLUE$1$RESET/; print $_ . "\n"; $t++; } sub kill { /\d+\.\d+\.\d+\.255.*SPT\=13[7-9] DPT\=13[7-9]/ || /255.255.255.255.*DPT\=69/ } sub stats { if ($t) { printf("Total: $t\n"); printf("Killed: $k (%d%%)\n", 100 * $k / $t); printf("Selected: $s (%d%%)\n", 100 * $s / $t); } exit; }