Files
bpfire/html/cgi-bin/logs.cgi/firewalllogip.dat
Michael Tremer 00793c27c9 GeoIP: Add lookup function for convenience
Instead of opening the database again for each lookup,
we will read it into memory on first use and every lookup
after that will be coming from cache.

Reviewed-by: Peter Müller <peter.mueller@link38.eu>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2017-11-13 22:37:19 +00:00

509 lines
13 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 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 ip'}, 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', $Lang::tr{'firewall graph ip'});
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 $ccode = &GeoIP::lookup($key[$s]);
$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#$ccode'><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";
}