#!/usr/bin/perl # SmoothWall CGIs # # This code is distributed under the terms of the GPL # # JC HERITIER # page inspired from the initial firewalllog.dat # # Modified for IPFire by Christian Schmidt (www.ipfire.org) # enable only the following on debugging purpose #use warnings; #use CGI::Carp 'fatalsToBrowser'; #use strict; require '/var/ipfire/general-functions.pl'; require "${General::swroot}/geoip-functions.pl"; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; 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); my $start = -1; 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]; $cgiparams{country} = $temp[3]; } if (!($cgiparams{'MONTH'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11)$/) || !($cgiparams{'DAY'} =~ /^(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'}; @temp_then = localtime(POSIX::mktime(@temp_now) + 86400); ## Retrieve the same time on the next day - ## 86400 seconds in a day $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'}; @temp_then = localtime(POSIX::mktime(@temp_now) - 86400); ## Retrieve the same time on the previous day - ## 86400 seconds in a day $cgiparams{'MONTH'} = $temp_then[4]; $cgiparams{'DAY'} = $temp_then[3]; } if (($cgiparams{'DAY'} ne $now[3]) || ($cgiparams{'MONTH'} ne $now[4])) { my @then = (); if ( ( $cgiparams{'MONTH'} eq $now[4]) && ($cgiparams{'DAY'} > $now[3]) || ( $cgiparams{'MONTH'} > $now[4] ) ) { @then = localtime(POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1901 )); } else { @then = localtime(POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1900 )); } $tdoy = $then[7]; my $lastleap=($year-1)%4; if ($tdoy>$doy) { if ($lastleap == 0 && $tdoy < 60) { $doy=$tdoy+366; } else { $doy=$doy+365; } } } my $datediff=0; my $dowd=0; my $multifile=0; if ($tdoy ne $doy) { $datediff=int(($doy-$tdoy)/7); $dowd=($doy-$tdoy)%7; if (($dow-$dowd)<1) { $datediff=$datediff+1; } if (($dow-$dowd)==0) { $multifile=1; } } my $monthstr = $shortmonths[$cgiparams{'MONTH'}]; my $longmonthstr = $longmonths[$cgiparams{'MONTH'}]; my $day = $cgiparams{'DAY'}; my $daystr=''; if ($day <= 9) { $daystr = " $day"; } else { $daystr = $day; } my $skip=0; my $filestr=''; if ($datediff==0) { $filestr="/var/log/messages"; } else { $filestr="/var/log/messages.$datediff"; $filestr = "$filestr.gz" if -f "$filestr.gz"; } if (!(open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr)))) { $errormessage = "$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}"; $skip=1; # Note: This is in case the log does not exist for that date } my $lines = 0; my @log=(); my $country = $cgiparams{country}; if (!$skip) { while () { # First check whether valid log line (date, day) if (/(^${monthstr} ${daystr} ..:..:..) [\w\-]+ kernel:.*(IN=.*)$/) { # If ipv6 uses bridge, then use PHYSIN otherwise use IN if (/(^${monthstr} ${daystr} ..:..:..) [\w\-]+ kernel:.*(PHYSIN=.*)$/) {} elsif (/(^${monthstr} ${daystr} ..:..:..) [\w\-]+ kernel:.*(IN=.*)$/) {} my $packet = $2; my $iface = ''; my $srcaddr = ''; # If ipv6 uses bridge, use PHYSIN otherwise IN if ($packet =~ /PHYSIN=(\w+)/) { $iface = $1; } elsif ($packet =~ /IN=(\w+)/) { $iface = $1; } # Extract ipv4 and ipv6 addresses if (($packet =~ /SRC\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($packet =~ /SRC\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) { $srcaddr = $1; } if($iface eq $country) { # iface matches country code $log[$lines] = $_; $lines++; } elsif($srcaddr ne '') { # or srcaddr matches country code my $ccode = &GeoIP::lookup($srcaddr); if($ccode eq uc($country)){ $log[$lines] = $_; $lines++; } } } } close (FILE); } $skip=0; if ($multifile) { $datediff=$datediff-1; if ($datediff==0) { $filestr="/var/log/messages"; } else { $filestr="/var/log/messages.$datediff"; $filestr = "$filestr.gz" if -f "$filestr.gz"; } if (!(open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr)))) { $errormessage="$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}"; $skip=1; } if (!$skip) { while () { # Check if valid log line (date, day) if (/(^${monthstr} ${daystr} ..:..:..) [\w\-]+ kernel:.*(IN=.*)$/) { my $iface = ''; # If ipv6 uses bridge, then use PHYSIN otherwise IN if ($_ =~ /PHYSIN=(\w+)/) { $iface = $1; } elsif ($_ =~ /IN=(\w+)/) { $iface = $1; } if($iface eq $country) { # iface matches country code $log[$lines] = $_; $lines++; } # extract ipv4 and ipv6 address elsif (($_ =~ /SRC\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($_ =~ /SRC\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) { my $srcaddr=$1; my $ccode = $gi->country_code_by_name($srcaddr); if($ccode eq uc($country)){ # or srcaddr matches country code $log[$lines] = $_; $lines++; } } } } close (FILE); } } &Header::showhttpheaders(); &Header::openpage($Lang::tr{'firewall log country'}, 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'}: 
$Lang::tr{'source ip country'}
END ; &Header::closebox(); &Header::openbox('100%', 'left', $Lang::tr{'firewall log country'}); print "

$Lang::tr{'firewall hits'} $longmonthstr $daystr: $lines

"; if ($start == -1) { $start = $lines - ${Header::viewsize}; } if ($start >= $lines - ${Header::viewsize}) { $start = $lines - ${Header::viewsize}; }; if ($start < 0) { $start = 0; } my $prev = $start - ${Header::viewsize}; my $next = $start + ${Header::viewsize}; if ($prev < 0) { $prev = 0; } if ($next >= $lines) { $next = -1 } if ($start == 0) { $prev = -1; } if ($lines != 0) { &oldernewer(); } print < $Lang::tr{'time'} $Lang::tr{'chain'} $Lang::tr{'iface'} $Lang::tr{'proto'} $Lang::tr{'source'} $Lang::tr{'src port'} $Lang::tr{'destination'} $Lang::tr{'dst port'} END ; my @slice = splice(@log, $start, ${Header::viewsize}); if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @slice = reverse @slice; } $lines = 0; foreach $_ (@slice) { $a = $_; # If ipv6 uses bridge, use PHYSIN otherwise use IN if (/^... (..) (..:..:..) [\w\-]+ kernel:(.*)(PHYSIN=.*)$/) {} elsif (/^... (..) (..:..:..) [\w\-]+ kernel:(.*)(IN=.*)$/) {}; my $packet = $4; my $iface = ''; # If ipv6 uses bridge, use PHYSIN otherwise use IN if ($packet =~ /PHYSIN=(\w+)/) { $iface = $1; } elsif ($packet =~ /IN=(\w+)/) { $iface = $1; } if ( $1 =~ /2./ ){ $iface=""; } my $srcaddr = ''; # Extract ipv4 and ipv6 addresses if (($packet =~ /SRC\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($packet =~ /SRC\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) { $srcaddr = $1; }; if($iface eq $country || $srcaddr ne '') { my $ccode=''; if($iface ne $country) { $ccode = &GeoIP::lookup($srcaddr); } if($iface eq $country || $ccode eq uc($country)) { my $chain = ''; my $in = '-'; my $out = '-'; my $srcaddr = ''; my $dstaddr = ''; my $protostr = ''; my $srcport = ''; my $dstport = ''; # If ipv6 uses bridge, the use PHYSIN otherwise use IN if ($_ =~ /(^.* ..:..:..) [\w\-]+ kernel:(.*)(IN=.*)(PHYSIN=.*)$/) {} elsif ($_ =~ /(^.* ..:..:..) [\w\-]+ kernel:(.*)(IN=.*)$/) {} my $timestamp = $1; my $chain = $2; my $packet = $3; $timestamp =~ /(...) (..) (..:..:..)/; my $month = $1; my $day = $2; my $time = $3; # If ipv6 uses bridge, use PHYSIN and PHYSOUT, otherwise use IN and OUT if ($a =~ /PHYSIN=(\w+)/) { $iface = $1; } elsif ($a =~ /IN=(\w+)/) { $iface = $1; } if ($a =~ /PHYSOUT=(\w+)/) { $out = $1; } elsif ($a =~ /OUT=(\w+)/) { $out = $1; } # Extract ipv4 and ipv6 addresses if (($a =~ /SRC\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($a =~ /SRC\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) { $srcaddr = $1; } if (($a =~ /DST\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($a =~ /DST\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) { $dstaddr = $1; } if ($a =~ /PROTO\=(\w+)/) { $protostr = $1; } my $protostrlc = lc($protostr); if ($a =~ /SPT\=([\d\.]+)/){ $srcport = $1; } if ($a =~ /DPT\=([\d\.]+)/){ $dstport = $1; } if ($lines % 2) { print "\n"; } else { print "\n"; } print <$time $chain $iface $protostr
$srcaddr
$srcport
$dstaddr
$dstport END ; $lines++; } } } print < END ; &oldernewer(); print"
$Lang::tr{
"; &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 != -1) { print "$Lang::tr{'newer'}"; } else { print "$Lang::tr{'newer'}"; } print "\n"; print < END ; }