Files
bpfire/html/cgi-bin/logs.cgi/firewalllogip.dat
Michael Eitelwein 9877d28d9e Enable correct display of ipv6 entries in Firewall log pages of web UI.
3 main changes:
 - Fill $iface and $out from PHYSIN and PHYSOUT when looking at bridged packets, othwerwise fill from IN and OUT
 - Recognize ipv4 and ipv6 address style for $srcaddr and $dstaddr
 - Match color coding of tables to pie charts (see seperate patch sent earlier)

I am using the bridged ipv6 setup as proposed in the wiki. I do not think this breaks anything when not using ipv6. So it would be nice to include this even if ipv6 is not officially supported yet. It is quite useful when using the ipv6 setup.

Signed-off-by: Michael Eitelwein <michael@eitelwein.net>
---
2016-01-07 14:00:01 +01:00

510 lines
15 KiB
Perl

#!/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
# and Michael Tremer (www.ipfire.org)
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}/geoip-functions.pl";
require "${General::swroot}/lang.pl";
require "${General::swroot}/header.pl";
use POSIX();
my %cgiparams=();
my %settings=();
my $pienumber;
my $otherspie;
my $showpie;
my $sortcolumn;
my $errormessage = '';
$cgiparams{'pienumber'} = 10;
$cgiparams{'otherspie'} = 1;
$cgiparams{'showpie'} = 1;
$cgiparams{'sortcolumn'} = 1;
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'} = '';
&General::readhash("${General::swroot}/fwlogs/ipsettings", \%settings);
if ($settings{'pienumber'} != 0) { $cgiparams{'pienumber'} = $settings{'pienumber'} };
if ($settings{'otherspie'} != 0) { $cgiparams{'otherspie'} = $settings{'otherspie'} };
if ($settings{'showpie'} != 0) { $cgiparams{'showpie'} = $settings{'showpie'} };
if ($settings{'sortcolumn'} != 0) { $cgiparams{'sortcolumn'} = $settings{'sortcolumn'} };
&Header::getcgihash(\%cgiparams);
if ($cgiparams{'pienumber'} != 0) { $settings{'pienumber'} = $cgiparams{'pienumber'} };
if ($cgiparams{'otherspie'} != 0) { $settings{'otherspie'} = $cgiparams{'otherspie'} };
if ($cgiparams{'showpie'} != 0) { $settings{'showpie'} = $cgiparams{'showpie'} };
if ($cgiparams{'sortcolumn'} != 0) { $settings{'sortcolumn'} = $cgiparams{'sortcolumn'} };
if ($cgiparams{'ACTION'} eq $Lang::tr{'save'})
{
&General::writehash("${General::swroot}/fwlogs/ipsettings", \%settings);
}
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];
}
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=();
if (!$skip)
{
while (<FILE>)
{
if (/(^${monthstr} ${daystr} ..:..:..) [\w\-]+ kernel:.*(IN=.*)$/) {
$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 (<FILE>) {
if (/(^${monthstr} ${daystr} ..:..:..) [\w\-]+ kernel:.*(IN=.*)$/) {
$log[$lines] = $_;
$lines++;
}
}
close (FILE);
}
}
my $MODNAME="fwlogs";
&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 "<font class='base'>$errormessage&nbsp;</font>\n";
&Header::closebox();
}
&Header::openbox('100%', 'left', "$Lang::tr{'settings'}");
print <<END
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
<table width='100%'>
<tr>
<td width='10%' class='base'>$Lang::tr{'month'}:&nbsp;</td>
<td width='10%'>
<select name='MONTH'>
END
;
my $month;
for ($month = 0; $month < 12; $month++)
{
print "\t<option ";
if ($month == $cgiparams{'MONTH'}) {
print "selected='selected' "; }
print "value='$month'>$longmonths[$month]</option>\n";
}
print <<END
</select>
</td>
<td width='10%' class='base' align='right'>&nbsp;$Lang::tr{'day'}:&nbsp;</td>
<td width='40%'>
<select name='DAY'>
END
;
for ($day = 1; $day <= 31; $day++)
{
print "\t<option ";
if ($day == $cgiparams{'DAY'}) {
print "selected='selected' "; }
print "value='$day'>$day</option>\n";
}
if( $cgiparams{'pienumber'} != 0){$pienumber=$cgiparams{'pienumber'};}
if( $cgiparams{'otherspie'} != 0){$otherspie=$cgiparams{'otherspie'};}
if( $cgiparams{'showpie'} != 0){$showpie=$cgiparams{'showpie'};}
if( $cgiparams{'sortcolumn'} != 0){$sortcolumn=$cgiparams{'sortcolumn'};}
print <<END
</select>
</td>
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day before'}' value='&lt;&lt;' /></td>
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day after'}' value='&gt;&gt;' /></td>
<td width='20%' align='right'><input type='submit' name='ACTION' value='$Lang::tr{'update'}' /></td>
</tr>
<tr>
<td colspan='3' align='left' valign="left">$Lang::tr{'Number of IPs for the pie chart'}:</td>
<td colspan='3' align='left' valign="center"><input type='text' name='pienumber' value='$pienumber' size='4'></td>
<td align='right'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
</tr>
</table>
</form>
END
;
&Header::closebox();
&Header::openbox('100%', 'left', 'Firewall Logs');
print "<p><b>$Lang::tr{'firewall hits'} $longmonthstr $daystr: $lines</b></p>";
my $linesjc = 0;
my %tabjc;
if ($pienumber == -1 || $pienumber > $lines || $sortcolumn == 2) { $pienumber = $lines; };
$lines = 0;
foreach $_ (@log)
{
# Extract ipv4 or ipv6 address
if (($_ =~ /SRC\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($_ =~ /SRC\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) {
$tabjc{$1} = $tabjc{$1} + 1 ;
if(($tabjc{$1} == 1) && ($lines < $pienumber)) { $lines = $lines + 1; }
$linesjc++;
}
}
$pienumber = $lines;
my @keytabjc = keys %tabjc;
my @slice;
my $go;
my $nblinejc;
if( $cgiparams{'linejc'} eq 'all' ){ $nblinejc = $linesjc; $go=1; }
if( ($cgiparams{'linejc'} != 0) && ($cgiparams{'linejc'} ne 'all') ){ $nblinejc = $cgiparams{'linejc'}; $go=1;}
if( $go != 1){ $nblinejc = 1000; }
my @key;
my @value;
my $indice=0;
my @tabjc2;
if ($sortcolumn == 1)
{
@tabjc2 = sort { $b <=> $a } values (%tabjc);
}
else
{
@tabjc2 = sort { $a <=> $b } keys (%tabjc);
}
my $colour=1;
##############################################
#pie chart generation
use GD::Graph::pie;
use GD::Graph::colour;
#ips sort by hits number
my $v;
if ($sortcolumn == 1)
{
for ($v=0;$v<$pienumber;$v++){
findkey($tabjc2[$v]);
}
}
else
{
foreach $v (@tabjc2) {
$key[$indice] = $v;
$value[$indice] = $tabjc{$v};
$indice++;
}
}
my @ips;
my @numb;
@ips = @key;
@numb = @value;
my $o;
if($cgiparams{'otherspie'} == 2 ){}
else{
my $numothers;
for($o=0;$o<$pienumber;$o++){
$numothers = $numothers + $numb[$o];
}
$numothers = $linesjc - $numothers;
if ($numothers > 0) {
$ips[$pienumber]="$Lang::tr{'otherip'}";
$numb[$pienumber] = $numothers;
}
}
my @data = (\@ips,\@numb);
use GD::Graph::colour qw( :files );
my $color=0;
my %color = ();
my %mainsettings = ();
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color);
if ($showpie != 2 && $pienumber <= 50 && $pienumber != 0) {
my $mygraph = GD::Graph::pie->new(500, 350);
$mygraph->set(
'title' => '',
'pie_height' => 50,
'start_angle' => 89
) or warn $mygraph->error;
$mygraph->set_value_font(GD::gdMediumBoldFont);
$mygraph->set( dclrs => [ "$color{'color1'}" , "$color{'color2'}" , "$color{'color3'}" , "$color{'color4'}" , "$color{'color5'}" , "$color{'color6'}" , "$color{'color7'}" , "$color{'color8'}" , "$color{'color9'}" , "$color{'color10'}" ] );
my $myimage = $mygraph->plot(\@data) or die $mygraph->error;
my @filenames = glob("/srv/web/ipfire/html/graphs/fwlog-ip*.png");
unlink(@filenames);
my $imagerandom = rand(1000000);
my $imagename = "/srv/web/ipfire/html/graphs/fwlog-ip$imagerandom.png";
open(FILE,">$imagename");
print FILE $myimage->png;
close(FILE);
#####################################################
print "<div style='text-align:center'>";
print "<img src='/graphs/fwlog-ip$imagerandom.png'>";
print "</div>";
}
print <<END
<table width='100%' class='tbl'>
<tr>
<th width='10%' align='center' class='boldbase'></th>
<th width='30%' align='center' class='boldbase'><b>$Lang::tr{'ip address'}</b></th>
<th width='10%' align='center' class='boldbase'><b>$Lang::tr{'country'}</b></th>
<th width='10%' align='center' class='boldbase'><b>$Lang::tr{'count'}</b></th>
<th width='30%' align='center' class='boldbase'><b>$Lang::tr{'percentage'}</b></th>
</tr>
END
;
my $total=0;
my $show=0;
my $s;
my $percent;
my $col="";
for($s=0;$s<$lines;$s++)
{
$show++;
$percent = $value[$s] * 100 / $linesjc;
$percent = sprintf("%.f", $percent);
$total = $total + $value[$s];
# colors are numbered 1 to 10
my $colorIndex = ($color % 10) + 1;
$col="bgcolor='$color{\"color$colorIndex\"}'";
print "<tr>";
my $gi = Geo::IP::PurePerl->new();
my $ccode = $gi->country_code_by_name($key[$s]);
my $fcode = lc($ccode);
$color++;
print "<td align='center' $col><form method='post' action='showrequestfromip.dat'><input type='hidden' name='MONTH' value='$cgiparams{'MONTH'}'> <input type='hidden' name='DAY' value='$cgiparams{'DAY'}'> <input type='hidden' name='ip' value='$key[$s]'> <input type='submit' value='$Lang::tr{'details'}'></form></td>";
print "<td align='center' $col><a href='/cgi-bin/ipinfo.cgi?ip=$key[$s]'>$key[$s]</a></td>";
# Get flag icon for of the country.
my $flag_icon = &GeoIP::get_flag_icon($ccode);
if ( $flag_icon ) {
print "<td align='center' $col><a href='/cgi-bin/country.cgi#$fcode'><img src='$flag_icon' border='0' align='absmiddle' alt='$ccode' title='$ccode'></a></td>";
} else {
print "<td align='center' $col></td>";
}
print "<td align='center' $col>$value[$s]</td>";
print "<td align='center' $col>$percent</td>";
print "</tr>";
}
if($cgiparams{'otherspie'} == 2 ){}
else{
# colors are numbered 1 to 10
my $colorIndex = ($color % 10) + 1;
$col="bgcolor='$color{\"color$colorIndex\"}'";
print "<tr>";
if ( $linesjc ne "0")
{
my $dif;
$dif = $linesjc - $total;
$percent = $dif * 100 / $linesjc;
$percent = sprintf("%.f", $percent);
print <<END
<td align='center' $col></td>
<td align='center' $col>$Lang::tr{'otherip'}</td>
<td align='center' $col></td>
<td align='center' $col>$dif</td>
<td align='center' $col>$percent</td>
</tr>
END
;
}
}
print <<END
</table>
END
;
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
sub findkey {
my $v;
foreach $v (@keytabjc) {
if ($tabjc{$v} eq $_[0]) {
delete $tabjc{$v};
$key[$indice] = "$v";
$value[$indice] = $_[0];
$indice++;
last;
}
}
}
sub checkversion {
#Automatic Updates is disabled
return "0","0";
}