#!/usr/bin/perl # # SmoothWall CGIs # # This code is distributed under the terms of the GPL # # (c) The SmoothWall Team # # $Id: firewalllog.dat,v 1.4.2.18 2005/08/23 12:01:50 eoberlander Exp $ # # July 28, 2003 - Darren Critchley - darren@kdi.ca # - added source mac adapter to layout # use strict; use Geo::IP::PurePerl; use Getopt::Std; # enable only the following on debugging purpose #use warnings; #use CGI::Carp 'fatalsToBrowser'; require '/var/ipfire/general-functions.pl'; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; my %color = (); my %mainsettings = (); &General::readhash("${General::swroot}/main/settings", \%mainsettings); &General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); use POSIX(); #workaround to suppress a warning when a variable is used only once my @dummy = ( ${Header::table2colour} ); undef (@dummy); my %cgiparams=(); my %logsettings=(); my $errormessage = ''; my @shortmonths = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ); my @longmonths = ( $Lang::tr{'january'}, $Lang::tr{'february'}, $Lang::tr{'march'}, $Lang::tr{'april'}, $Lang::tr{'may'}, $Lang::tr{'june'}, $Lang::tr{'july'}, $Lang::tr{'august'}, $Lang::tr{'september'}, $Lang::tr{'october'}, $Lang::tr{'november'}, $Lang::tr{'december'} ); my @now = localtime(); my $dow = $now[6]; my $doy = $now[7]; my $tdoy = $now[7]; my $year = $now[5]+1900; $cgiparams{'DAY'} = $now[3]; $cgiparams{'MONTH'} = $now[4]; $cgiparams{'ACTION'} = ''; &Header::getcgihash(\%cgiparams); $logsettings{'LOGVIEW_REVERSE'} = 'off'; &General::readhash("${General::swroot}/logging/settings", \%logsettings); ${Header::viewsize} = defined ($logsettings{'LOGVIEW_VIEWSIZE'}) ? $logsettings{'LOGVIEW_VIEWSIZE'} : 150; my $start = ($logsettings{'LOGVIEW_REVERSE'} eq 'on') ? 0x7FFFF000 : 0; #index of firts line number to display if ($ENV{'QUERY_STRING'} && $cgiparams{'ACTION'} ne $Lang::tr{'update'}) { my @temp = split(',',$ENV{'QUERY_STRING'}); $start = $temp[0]; $cgiparams{'MONTH'} = $temp[1]; $cgiparams{'DAY'} = $temp[2]; } if (!($cgiparams{'MONTH'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11)$/) || !($cgiparams{'DAY'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)$/)) { $cgiparams{'DAY'} = $now[3]; $cgiparams{'MONTH'} = $now[4]; } elsif($cgiparams{'ACTION'} eq '>>') { my @temp_then=(); my @temp_now = localtime(time); $temp_now[4] = $cgiparams{'MONTH'}; $temp_now[3] = $cgiparams{'DAY'}; if ($cgiparams{'DAY'}) { @temp_then = localtime(POSIX::mktime(@temp_now) + 86400); ## Retrieve the same time on the next day + ## 86400 seconds in a day } else { $temp_now[3] = 1; $temp_now[4] = ($temp_now[4]+1) %12; @temp_then = localtime(POSIX::mktime(@temp_now) ); $temp_then[3] = 0; } $cgiparams{'MONTH'} = $temp_then[4]; $cgiparams{'DAY'} = $temp_then[3]; } elsif($cgiparams{'ACTION'} eq '<<') { my @temp_then=(); my @temp_now = localtime(time); $temp_now[4] = $cgiparams{'MONTH'}; $temp_now[3] = $cgiparams{'DAY'}; if ($cgiparams{'DAY'}) { @temp_then = localtime(POSIX::mktime(@temp_now) - 86400); ## Retrieve the same time on the next day - ## 86400 seconds in a day } else { $temp_now[3] = 1; $temp_now[4] = ($temp_now[4]-1) %12; @temp_then = localtime(POSIX::mktime(@temp_now) ); $temp_then[3] = 0; } $cgiparams{'MONTH'} = $temp_then[4]; $cgiparams{'DAY'} = $temp_then[3]; } # Find in which file.gz is the log. Can be calculated because WEEKLY ROTATING of access.log my $gzindex; my $date = $cgiparams{'DAY'} == 0 ? '' : $cgiparams{'DAY'} <= 9 ? "0$cgiparams{'DAY'}" : "$cgiparams{'DAY'}"; { my $xday; # Calculate time. If future date, calculate for past year !!! if (( $cgiparams{'MONTH'} eq $now[4]) && ($cgiparams{'DAY'} > $now[3]) || ( $cgiparams{'MONTH'} > $now[4] ) ) { $xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1901 ); $date = "$longmonths[$cgiparams{'MONTH'}] $date, ". int($year-1); } else { $xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1900 ); $date = "$longmonths[$cgiparams{'MONTH'}] $date, $year"; } # calculate end of active week (saturday 23H59) my @then = (); @then = localtime(time()); my $sunday = POSIX::mktime( 0, 0, 0, @then[3], @then[4], @then[5]); $sunday += (6-$then[6]) * 86400; # Convert delta in second to full weeks $gzindex = int (($sunday-$xday)/604800 ); } my $monthstr = $shortmonths[$cgiparams{'MONTH'}]; my $daystr = $cgiparams{'DAY'} == 0 ? '..' : $cgiparams{'DAY'} <= 9 ? " $cgiparams{'DAY'}" : "$cgiparams{'DAY'}"; my $lines = 0; my @log=(); my $loop = 1; my $filestr = 0; my $lastdatetime; # for debug my $search_for_end = 0; while ($gzindex >=0 && $loop) { # calculate file name if ($gzindex == 0) { $filestr = "/var/log/messages"; } else { $filestr = "/var/log/messages.$gzindex"; $filestr = "$filestr.gz" if -f "$filestr.gz"; } # now read file if existing if (open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr))) { #&General::log("reading $filestr"); READ:while () { my $line = $_; if ($line =~ /^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*IN=.*$/) { # when standart viewing, just keep in memory the correct slice # it starts a '$start' and size is $viewport # If export, then keep all lines... if ($cgiparams{'ACTION'} eq $Lang::tr{'export'}){ $log[$lines++] = "$line"; } else { if ($lines++ < ($start + $Header::viewsize)) { push(@log,"$line"); if (@log > $Header::viewsize) { shift (@log); } #} else { dont do this optimisation, need to count lines ! # $datetime = $maxtime; # we have read viewsize lines, stop main loop # last READ; # exit read file } } $search_for_end = 1; # we find the start of slice, can look for end now } else { if ($search_for_end == 1) { #finish read files when date is over (test month equality only) $line =~ /^(...) (..) ..:..:..*$/; $loop = 0 if ( ($1 ne $monthstr) || ( ($daystr ne '..') && ($daystr ne $2) ) ); } } } close (FILE); } $gzindex--; # will try next gz file eg 40,39,38,.... because it may have holes when ipcop stopped # for a long time }# while # $errormessage = "$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}"; if ($cgiparams{'ACTION'} eq $Lang::tr{'export'}) { print "Content-type: text/plain\n\n"; print "IPFire firewall log\r\n"; print "$Lang::{'date'}: $date\r\n\r\n"; if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; } foreach $_ (@log) { /^... (..) (..:..:..) [\w\-]+ kernel:.*(IN=.*)$/; my $day = $1; $day =~ tr / /0/; my $time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ; print "$time $3\r\n"; } exit 0; } &Header::showhttpheaders(); &Header::openpage($Lang::tr{'firewall log'}, 1, ''); &Header::openbigbox('100%', 'left', '', $errormessage); if ($errormessage) { &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); print "$errormessage \n"; &Header::closebox(); } &Header::openbox('100%', 'left', "$Lang::tr{'settings'}:"); print <
$Lang::tr{'month'}:   $Lang::tr{'day'}: 
END ; &Header::closebox(); &Header::openbox('100%', 'left', $Lang::tr{'log'}); print "

$Lang::tr{'firewall hits'} $date: $lines

"; $start = $lines - ${Header::viewsize} if ($start >= $lines - ${Header::viewsize}); $start = 0 if ($start < 0); my $prev; if ($start == 0) { $prev = -1; } else { $prev = $start - ${Header::viewsize}; $prev = 0 if ( $prev < 0); } my $next; if ($start == $lines - ${Header::viewsize}) { $next = -1; } else { $next = $start + ${Header::viewsize}; $next = $lines - ${Header::viewsize} if ($next >= $lines - ${Header::viewsize}); } if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; } if ($lines != 0) { &oldernewer(); } print < $Lang::tr{'time'} $Lang::tr{'chain'} $Lang::tr{'iface'} $Lang::tr{'proto'} $Lang::tr{'source'}
$Lang::tr{'destination'}
$Lang::tr{'src port'}
$Lang::tr{'dst port'}
Flag $Lang::tr{'mac address'} END ; $lines = 0; foreach $_ (@log) { /^... (..) (..:..:..) [\w\-]+ kernel:(.*)(IN=.*)$/; my $day = $1; $day =~ tr / /0/; my $time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ; my $comment = $3; my $packet = $4; $packet =~ /IN=(\w+)/; my $iface=$1; if ( $1 =~ /2./ ){ $iface="";} $packet =~ /SRC=([\d\.]+)/; my $srcaddr=$1; $packet =~ /DST=([\d\.]+)/; my $dstaddr=$1; $packet =~ /MAC=([\w+\:]+)/; my $macaddr=$1; $packet =~ /PROTO=(\w+)/; my $proto=$1; $packet =~ /SPT=(\d+)/; my $srcport=$1; $packet =~ /DPT=(\d+)/; my $dstport=$1; my $gi = Geo::IP::PurePerl->new(); my $ccode = $gi->country_code_by_name($srcaddr); my $fcode = lc($ccode); my $servi = uc(getservbyport($srcport, lc($proto))); if ($servi ne '' && $srcport < 1024) { $srcport = "$srcport($servi)"; } $servi = uc(getservbyport($dstport, lc($proto))); if ($servi ne '' && $dstport < 1024) { $dstport = "$dstport($servi)";} my @mactemp = split(/:/,$macaddr); $macaddr = "$mactemp[6]:$mactemp[7]:$mactemp[8]:$mactemp[9]:$mactemp[10]:$mactemp[11]"; if ($lines % 2) { print "\n"; } else { print "\n"; } print <$time $comment $iface $proto $srcaddr
$dstaddr $srcport
$dstport END ; if ( $fcode ne "" ){ print "$ccode";} else { print "";} print <$macaddr END ; $lines++; } print ""; &oldernewer(); &Header::closebox(); &Header::closebigbox(); &Header::closepage(); sub oldernewer { print < END ; print ""; if ($prev != -1) { print "$Lang::tr{'older'}"; } else { print "$Lang::tr{'older'}"; } print "\n"; print ""; if ($next >= 0) { print "$Lang::tr{'newer'}"; } else { print "$Lang::tr{'newer'}"; } print "\n"; print < END ; }