From: Tim FitzGeorge <ipfr@tfitzgeorge.me.uk>
To: development@lists.ipfire.org
Subject: [PATCH 09/12] statusmail: Other plugins
Date: Fri, 05 Apr 2019 18:29:37 +0100 [thread overview]
Message-ID: <20190405172940.13168-10-ipfr@tfitzgeorge.me.uk> (raw)
In-Reply-To: <20190405172940.13168-1-ipfr@tfitzgeorge.me.uk>
[-- Attachment #1: Type: text/plain, Size: 41934 bytes --]
Note that the graphs plugin requires a change to the existing graphs.pl
to allow for arbitary time periods.
Signed-off-by: Tim FitzGeorge <ipfr(a)tfitzgeorge.me.uk>
---
src/statusmail/plugins/graphs.pm | 697 +++++++++++++++++++++++++
src/statusmail/plugins/hardware_media_space.pm | 154 ++++++
src/statusmail/plugins/network_firewall.pm | 357 +++++++++++++
3 files changed, 1208 insertions(+)
create mode 100644 src/statusmail/plugins/graphs.pm
create mode 100644 src/statusmail/plugins/hardware_media_space.pm
create mode 100644 src/statusmail/plugins/network_firewall.pm
diff --git a/src/statusmail/plugins/graphs.pm b/src/statusmail/plugins/graphs.pm
new file mode 100644
index 000000000..5b72c6e1a
--- /dev/null
+++ b/src/statusmail/plugins/graphs.pm
@@ -0,0 +1,697 @@
+#!/usr/bin/perl
+
+############################################################################
+# #
+# Send log and status emails for IPFire #
+# #
+# This is free software; you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with IPFire; if not, write to the Free Software #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+# #
+# Copyright (C) 2018 - 2019 The IPFire Team #
+# #
+############################################################################
+
+use strict;
+use warnings;
+
+require "${General::swroot}/lang.pl";
+require "${General::swroot}/graphs.pl";
+
+package Graphs;
+
+############################################################################
+# Function prototypes
+############################################################################
+
+sub add_graph( $$$$@ );
+
+############################################################################
+# BEGIN Block
+#
+# Register the graphs available in this file.
+#
+# Note that some graphs are only available under certain circumstances, so
+# it's necessary to check the circumstances apply.
+############################################################################
+
+sub BEGIN
+{
+ my %netsettings;
+ my %mainsettings;
+
+ &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
+ &General::readhash("${General::swroot}/main/settings", \%mainsettings);
+
+ my $config_type = $netsettings{'CONFIG_TYPE'};
+
+ my %common_options = ( 'section' => $Lang::tr{'graph'},
+ 'format' => 'html' );
+
+ #----------------------------------------------------------------------------
+ # Network
+
+ if ($netsettings{'RED_TYPE'} ne 'PPPOE')
+ {
+ if ($netsettings{'RED_DEV'} ne $netsettings{'GREEN_DEV'})
+ {
+ if ($netsettings{'RED_DEV'} eq 'red0')
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-red0',
+ 'subsection' => $Lang::tr{'interfaces'},
+ 'item' => 'red0',
+ 'function' => \&red0 );
+ }
+ else
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-ppp0',
+ 'subsection' => $Lang::tr{'interfaces'},
+ 'item' => 'ppp0',
+ 'function' => \&ppp0 );
+ }
+ }
+ }
+ else
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-ppp0',
+ 'subsection' => $Lang::tr{'interfaces'},
+ 'item' => 'ppp0',
+ 'function' => \&ppp0 );
+ }
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-green0',
+ 'subsection' => $Lang::tr{'interfaces'},
+ 'item' => 'green0',
+ 'function' => \&green0 );
+
+ if ($config_type == 3 or $config_type == 4)
+ {
+ # BLUE
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-blue0',
+ 'subsection' => $Lang::tr{'interfaces'},
+ 'item' => 'blue0',
+ 'function' => \&blue0 );
+ }
+
+ if ($config_type == 2 or $config_type == 4)
+ {
+ # ORANGE
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-orange0',
+ 'subsection' => $Lang::tr{'interfaces'},
+ 'item' => 'orange0',
+ 'function' => \&orange0 );
+ }
+
+
+ if (-e "/var/log/rrd/collectd/localhost/interface/if_octets-ipsec0.rrd")
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-ipsec0',
+ 'subsection' => $Lang::tr{'network'},
+ 'item' => 'ipsec0',
+ 'function' => \&ipsec0 );
+ }
+
+ if (-e "/var/log/rrd/collectd/localhost/interface/if_octets-tun0.rrd")
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-tun0',
+ 'subsection' => $Lang::tr{'network'},
+ 'item' => 'tun0',
+ 'function' => \&tun0 );
+ }
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-network-fwhits',
+ 'subsection' => $Lang::tr{'network'},
+ 'item' => $Lang::tr{'firewallhits'},
+ 'function' => \&fw_hits );
+
+ #----------------------------------------------------------------------------
+ # System
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-system-cpu-usage',
+ 'subsection' => $Lang::tr{'system'},
+ 'item' => "CPU $Lang::tr{'graph'}",
+ 'function' => \&cpu_usage );
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-system-cpu-load',
+ 'subsection' => $Lang::tr{'system'},
+ 'item' => "Load $Lang::tr{'graph'}",
+ 'function' => \&cpu_load );
+
+ if ( -e "$mainsettings{'RRDLOG'}/collectd/localhost/cpufreq/cpufreq-0.rrd")
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-system-cpu-frequency',
+ 'subsection' => $Lang::tr{'system'},
+ 'item' => "CPU $Lang::tr{'frequency'}",
+ 'function' => \&cpu_freq );
+ }
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-system-entropy',
+ 'subsection' => $Lang::tr{'system'},
+ 'item' => $Lang::tr{'entropy'},
+ 'function' => \&entropy );
+
+ #----------------------------------------------------------------------------
+ # Hardware
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-hardware-cpu-load',
+ 'subsection' => $Lang::tr{'hardware graphs'},
+ 'item' => "Load $Lang::tr{'graph'}",
+ 'function' => \&cpu_load );
+
+ if ( `ls $mainsettings{'RRDLOG'}/collectd/localhost/thermal-thermal_zone* 2>/dev/null` )
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-hardware-acpi-zone-temp',
+ 'subsection' => $Lang::tr{'hardware graphs'},
+ 'item' => "ACPI Thermal-Zone Temp",
+ 'function' => \&therm );
+ }
+
+ if ( `ls $mainsettings{'RRDLOG'}/collectd/localhost/sensors-*/temperature-* 2>/dev/null` )
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-hardware-temp',
+ 'subsection' => $Lang::tr{'hardware graphs'},
+ 'item' => "hwtemp",
+ 'function' => \&hwtemp );
+ }
+
+ if ( `ls $mainsettings{'RRDLOG'}/collectd/localhost/sensors-*/fanspeed-* 2>/dev/null` )
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-hardware-fan',
+ 'subsection' => $Lang::tr{'hardware graphs'},
+ 'item' => "hwfan",
+ 'function' => \&hwfan );
+ }
+
+ if ( `ls $mainsettings{'RRDLOG'}/collectd/localhost/sensors-*/voltage-* 2>/dev/null` )
+ {
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-hardware-volt',
+ 'subsection' => $Lang::tr{'hardware graphs'},
+ 'item' => "hwvolt",
+ 'function' => \&hwvolt );
+ }
+
+ #----------------------------------------------------------------------------
+ # Memory
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-memory-memory',
+ 'subsection' => $Lang::tr{'memory'},
+ 'item' => $Lang::tr{'memory'},
+ 'function' => \&memory );
+
+ main::add_mail_item( %common_options,
+ 'ident' => 'graph-memory-swap',
+ 'subsection' => $Lang::tr{'memory'},
+ 'item' => $Lang::tr{'swap'},
+ 'function' => \&swap );
+
+ #----------------------------------------------------------------------------
+ # Disks
+
+ foreach my $path (glob '/var/log/rrd/collectd/localhost/disk*')
+ {
+ my ($name) = $path =~ m/disk\-(\w+)/;
+
+ main::add_mail_item( %common_options,
+ 'ident' => "graph-disk-access-$name",
+ 'subsection' => $Lang::tr{'statusmail disk access'},
+ 'item' => $name,
+ 'function' => sub { my ($this) = @_; diskaccess( $this, $name ); } );
+
+ main::add_mail_item( %common_options,
+ 'ident' => "graph-disk-temp-$name",
+ 'subsection' => $Lang::tr{'statusmail disk temperature'},
+ 'item' => $name,
+ 'function' => sub { my ($this) = @_; disktemp( $this, $name ); } );
+ }
+
+# Other graphs that aren't available.
+# updatepinggraph( host, period ) : netother.cgi
+# updateprocessescpugraph( period )
+# updateprocessesmemorygraph( period )
+# updateqosgraph( device, period ) red0 | ppp0 | imq0 : qos.cgi
+# updatevpngraph( interface, period ) : netovpnrw.cgi
+# updatevpnn2ngraph( interface, period ) : netovpnsrv.cgi
+# updatewirelessgraph( interface, period )
+}
+
+############################################################################
+# Code
+############################################################################
+
+#------------------------------------------------------------------------------
+# sub add_graph( object, function, name, alternate[, params...] )
+#
+# Adds a graph to the mail message. This runs a sub-process to capture the
+# output from running the standard WUI's graphing function, which is sent to
+# stdout.
+#
+# Parameters:
+# this message object
+# function function producing graph
+# name name of graph file
+# alternate alternate text for image
+# params parameters to be passed to graph function
+#------------------------------------------------------------------------------
+
+sub add_graph( $$$$@ )
+{
+ my ($this, $function, $name, $alternate, @params) = @_;
+
+ my $from_child;
+
+ my $pid = open( $from_child, "-|" );
+
+ if ($pid)
+ { # parent
+ binmode $from_child;
+
+ $this->add_image( fh => $from_child,
+ alt => $alternate,
+ type => 'image/png',
+ name => $name );
+
+ waitpid( $pid, 0 );
+ close $from_child;
+ }
+ else
+ { # child
+ binmode( STDOUT );
+
+ my $period = $this->get_period();
+
+ &$function( @params, $period );
+
+ exit;
+ }
+}
+
+
+#------------------------------------------------------------------------------
+# sub ppp0( this )
+#
+# Adds a graph of the ppp0 interface throughput
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub ppp0( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateifgraph, 'ppp0_if.png', 'ppp0 interface throughput', 'ppp0' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub red0( this )
+#
+# Adds a graph of the red0 interface throughput
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub red0( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateifgraph, 'red0_if.png', 'red0 interface throughput', 'red0' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub green0( this )
+#
+# Adds a graph of the green0 interface throughput
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub green0( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateifgraph, 'green0_if.png', 'green0 interface throughput', 'green0' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub blue0( this )
+#
+# Adds a graph of the blue0 interface throughput
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub blue0( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateifgraph, 'blue0_if.png', 'blue0 interface throughput', 'blue0' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub orange0( this )
+#
+# Adds a graph of the orange0 interface throughput
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub orange0( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateifgraph, 'orange0_if.png', 'orange0 interface throughput', 'orange0' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub ipsec0( this )
+#
+# Adds a graph of the ipsec0 interface
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub ipsec0( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateifgraph, 'ipsec0_if.png', 'ipsec0 interface throughput', 'ipsec0' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub tun0( this )
+#
+# Adds a graph of the tun0 interface
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub tun0( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateifgraph, 'tun0_if.png', 'tun0 interface throughput', 'tun0' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub cpu_usage( this )
+#
+# Adds a graph of the CPU usage
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub cpu_usage( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatecpugraph, 'cpu_usage.png', "CPU $Lang::tr{'graph'}" );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub cpu_freq( this )
+#
+# Adds a graph of the CPU frequency
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub cpu_freq( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatecpufreqgraph, 'cpu_freq.png', "CPU $Lang::tr{'frequency'}" );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub cpu_load( this )
+#
+# Adds a graph of the CPU load
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub cpu_load( $$ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateloadgraph,, 'cpu_load.png', "Load $Lang::tr{'graph'}" );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub fw_hits( this )
+#
+# Adds a graph of the Firewall hits
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub fw_hits( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatefwhitsgraph, 'fw_hits.png', $Lang::tr{'firewallhits'} );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub therm( this )
+#
+# Adds a graph of the ACPI Thermal zone temperatures
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub therm( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatethermaltempgraph, 'therm.png', "ACPI Thermal-Zone Temp" );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub hwtemp( this )
+#
+# Adds a graph of the Hardware Temperatures
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub hwtemp( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatehwtempgraph, 'hw_temp.png', 'hwtemp' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub hwfan( this )
+#
+# Adds a graph of the Fan Speeds
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub hwfan( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatehwfangraph, 'hw_fan.png', 'hwfan' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub hwvolt( this )
+#
+# Adds a graph of the Hardware voltages
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub hwvolt( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatehwvoltgraph, 'hw_volt.png', 'hw volt' );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub entropy( this )
+#
+# Adds a graph of the Entropy
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub entropy( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateentropygraph, 'entropy.png', $Lang::tr{'entropy'} );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub memory( this )
+#
+# Adds a graph of the memory usage
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub memory( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updatememorygraph, 'memory.png', $Lang::tr{'memory'} );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub swap( this )
+#
+# Adds a graph of the swapfile usage
+#
+# Parameters:
+# this message object
+#------------------------------------------------------------------------------
+
+sub swap( $ )
+{
+ my ($this) = @_;
+
+ add_graph( $this, \&Graphs::updateswapgraph, 'swap.png', $Lang::tr{'swap'} );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub diskaccess( this, name )
+#
+# Adds a graph of the disk access rate
+#
+# Parameters:
+# this message object
+# name disk name
+#------------------------------------------------------------------------------
+
+sub diskaccess( $$ )
+{
+ my ($this, $name) = @_;
+
+ add_graph( $this, \&Graphs::updatediskgraph, "disk_access_$name.png", $name, $name );
+
+ return 1;
+}
+
+
+#------------------------------------------------------------------------------
+# sub updatehddgraph( this, name )
+#
+# Adds a graph of the disk temperature
+#
+# Parameters:
+# this message object
+# name disk name
+#------------------------------------------------------------------------------
+
+sub disktemp( $$ )
+{
+ my ($this, $name) = @_;
+
+ add_graph( $this, \&Graphs::updatehddgraph, "disk_temp_$name.png", $name, $name );
+
+ return 1;
+}
diff --git a/src/statusmail/plugins/hardware_media_space.pm b/src/statusmail/plugins/hardware_media_space.pm
new file mode 100644
index 000000000..ce3db2def
--- /dev/null
+++ b/src/statusmail/plugins/hardware_media_space.pm
@@ -0,0 +1,154 @@
+#!/usr/bin/perl
+
+############################################################################
+# #
+# Send log and status emails for IPFire #
+# #
+# This is free software; you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with IPFire; if not, write to the Free Software #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+# #
+# Copyright (C) 2018 - 2019 The IPFire Team #
+# #
+############################################################################
+
+use strict;
+use warnings;
+
+require "${General::swroot}/lang.pl";
+
+package Hardware_Media_Space;
+
+############################################################################
+# Function prototypes
+############################################################################
+
+sub space( $$ );
+sub inodes( $$ );
+
+############################################################################
+# BEGIN Block
+#
+# Register the log items available in this file
+############################################################################
+
+sub BEGIN
+{
+ main::add_mail_item( 'ident' => 'hardware-media-space',
+ 'section' => $Lang::tr{'statusmail hardware'},
+ 'subsection' => $Lang::tr{'media'},
+ 'item' => $Lang::tr{'disk usage'},
+ 'function' => \&space,
+ 'option' => { 'type' => 'integer',
+ 'name' => $Lang::tr{'statusmail max free percent'},
+ 'min' => 0,
+ 'max' => 100 } );
+
+ main::add_mail_item( 'ident' => 'hardware-media-inodes',
+ 'section' => $Lang::tr{'statusmail hardware'},
+ 'subsection' => $Lang::tr{'media'},
+ 'item' => 'inodes',
+ 'function' => \&inodes,
+ 'option' => { 'type' => 'integer',
+ 'name' => $Lang::tr{'statusmail max free percent'},
+ 'min' => 0,
+ 'max' => 100 } );
+}
+
+############################################################################
+# Code
+############################################################################
+
+#------------------------------------------------------------------------------
+# sub space( this, min_percent )
+#
+# Adds the disk usage in terms of space used.
+#
+# Parameters:
+# this message object
+# min_percent Only display information if this amount of space or less is
+# free
+#------------------------------------------------------------------------------
+
+sub space( $$ )
+{
+ my $message = shift;
+ my $min_percent = 100 - shift;
+ my @lines;
+
+ # Get the process information
+
+ foreach my $line (`df -BM`)
+ {
+ my @fields = split /\s+/, $line, 6;
+ if ($fields[4] =~ m/\d+\%/)
+ {
+ my ($percent) = $fields[4] =~ m/(\d+)\%/;
+ next if ($percent <= $min_percent);
+ }
+ push @lines, [ @fields ];
+ }
+
+ if (@lines > 1)
+ {
+ $message->add_table( @lines );
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#------------------------------------------------------------------------------
+# sub inodes( this, min_percent )
+#
+# Adds the disk usage in terms of inodes used.
+#
+# Parameters:
+# this message object
+# min_percent Only display information if this number of inodes or less is
+# free
+#------------------------------------------------------------------------------
+
+sub inodes( $$ )
+{
+ my $message = shift;
+ my $min_percent = 100 - shift;
+ my @lines;
+
+ # Get the process information
+
+ foreach my $line (`df -i`)
+ {
+ my @fields = split /\s+/, $line, 6;
+ next if ($fields[1] == 0);
+ if ($fields[4] =~ m/\d+\%/)
+ {
+ my ($percent) = $fields[4] =~ m/(\d+)\%/;
+ next if ($percent <= $min_percent);
+ }
+ push @lines, [ @fields ];
+ }
+
+ if (@lines > 1)
+ {
+ $message->add_table( @lines );
+
+ return 1;
+ }
+
+ return 0;
+}
+
+1;
diff --git a/src/statusmail/plugins/network_firewall.pm b/src/statusmail/plugins/network_firewall.pm
new file mode 100644
index 000000000..1abe4e482
--- /dev/null
+++ b/src/statusmail/plugins/network_firewall.pm
@@ -0,0 +1,357 @@
+#!/usr/bin/perl
+
+############################################################################
+# #
+# Send log and status emails for IPFire #
+# #
+# This is free software; you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with IPFire; if not, write to the Free Software #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+# #
+# Copyright (C) 2018 - 2019 The IPFire Team #
+# #
+############################################################################
+
+require "${General::swroot}/lang.pl";
+
+use strict;
+use warnings;
+
+package Network_Firewall;
+
+use Time::Local;
+
+require "${General::swroot}/geoip-functions.pl";
+
+############################################################################
+# BEGIN Block
+#
+# Register the log items available in this file
+############################################################################
+
+sub BEGIN
+{
+ main::add_mail_item( 'ident' => 'network-firewall-ipaddresses',
+ 'section' => $Lang::tr{'network'},
+ 'subsection' => $Lang::tr{'firewall'},
+ 'item' => $Lang::tr{'ip address'},
+ 'function' => \&addresses,
+ 'option' => { 'type' => 'integer',
+ 'name' => $Lang::tr{'statusmail firewall min count'},
+ 'min' => 1,
+ 'max' => 1000 } );
+
+ main::add_mail_item( 'ident' => 'network-firewall-ports',
+ 'section' => $Lang::tr{'network'},
+ 'subsection' => $Lang::tr{'firewall'},
+ 'item' => $Lang::tr{port},
+ 'function' => \&ports,
+ 'option' => { 'type' => 'integer',
+ 'name' => $Lang::tr{'statusmail firewall min count'},
+ 'min' => 1,
+ 'max' => 1000 } );
+
+ main::add_mail_item( 'ident' => 'network-firewall-countries',
+ 'section' => $Lang::tr{'network'},
+ 'subsection' => $Lang::tr{'firewall'},
+ 'item' => $Lang::tr{country},
+ 'function' => \&countries,
+ 'option' => { 'type' => 'integer',
+ 'name' => $Lang::tr{'statusmail firewall min count'},
+ 'min' => 1,
+ 'max' => 1000 } );
+
+ main::add_mail_item( 'ident' => 'network-firewall-reason',
+ 'section' => $Lang::tr{'network'},
+ 'subsection' => $Lang::tr{'firewall'},
+ 'item' => $Lang::tr{'statusmail firewall reason'},
+ 'function' => \&reasons,
+ 'option' => { 'type' => 'integer',
+ 'name' => $Lang::tr{'statusmail firewall min count'},
+ 'min' => 1,
+ 'max' => 1000 } );
+}
+
+
+############################################################################
+# Functions
+############################################################################
+
+sub get_log( $ );
+sub addresses( $$ );
+
+#------------------------------------------------------------------------------
+# sub get_log( this )
+#
+# Gets information on blocked packets from the system log and caches it.
+#
+# Parameters:
+# this message object
+#
+# Returns:
+# reference to hash of information
+#------------------------------------------------------------------------------
+
+sub get_log( $ )
+{
+ my ($this, $name) = @_;
+
+ my $data = $this->cache( 'network-firewall' );
+
+ return $data if (defined $data);
+
+ my %info;
+ my $line;
+
+ while ($line = $this->get_message_log_line)
+ {
+ next unless ($line);
+ next unless ($line =~ m/kernel: DROP/);
+
+ my ($time, $rule, $interface, $src_addrs, $dst_port) =
+ $line =~ m/(\w+\s+\d+\s+\d+:\d+:\d+).*DROP_(\w+?)\s*IN=(\w+).*SRC=(\d+\.\d+\.\d+\.\d+).*(?:DPT=(\d*))/;
+# mmm dd hh:mm:dd ipfire kernel: DROP_SPAMHAUS_EDROPIN=ppp0 OUT= MAC= SRC=999.999.999.999 DST=888.888.888.888 LEN=40 TOS=0x00 PREC=0x00 TTL=248 ID=35549 PROTO=TCP SPT=47851 DPT=28672 WINDOW=1024 RES=0x00 SYN URGP=0 MARK=0xd2
+
+ next unless ($src_addrs);
+
+ my $country = GeoIP::lookup( $src_addrs ) || $src_addrs;
+
+ $info{'by_address'}{$src_addrs}{'count'}++;
+ $info{'by_address'}{$src_addrs}{'first'} = $time unless ($info{'by_address'}{$src_addrs}{'first'});
+ $info{'by_address'}{$src_addrs}{'last'} = $time;
+
+ if ($dst_port)
+ {
+ $info{'by_port'}{$dst_port}{'count'}++ ;
+ $info{'by_port'}{$dst_port}{'first'} = $time unless ($info{'by_port'}{$dst_port}{'first'});
+ $info{'by_port'}{$dst_port}{'last'} = $time;
+ }
+
+ if ($country)
+ {
+ $info{'by_country'}{$country}{'count'}++;
+ $info{'by_country'}{$country}{'first'} = $time unless ($info{'by_country'}{$country}{'first'});
+ $info{'by_country'}{$country}{'last'} = $time;
+ }
+
+ $info{'by_rule'}{$rule}{'count'}++;
+ $info{'by_rule'}{$rule}{'first'} = $time unless ($info{'by_rule'}{$rule}{'first'});
+ $info{'by_rule'}{$rule}{'last'} = $time;
+
+ $info{'total'}++;
+ };
+
+ $this->cache( 'network-firewall', \%info );
+
+ return \%info;
+}
+
+
+#------------------------------------------------------------------------------
+# sub addresses( this, min_count )
+#
+# Output information on blocked addresses.
+#
+# Parameters:
+# this message object
+# min_count only output blocked addresses occurring at least this number of
+# times
+#------------------------------------------------------------------------------
+
+sub addresses( $$ )
+{
+ my ($self, $min_count) = @_;
+ my @table;
+
+ use Sort::Naturally;
+
+ push @table, ['|', '|', '|', '|', '|', '|'];
+ push @table, [ $Lang::tr{'ip address'}, $Lang::tr{'country'}, $Lang::tr{'count'}, $Lang::tr{'percentage'}, $Lang::tr{'first'}, $Lang::tr{'last'} ];
+
+ my $stats = get_log( $self );
+
+ foreach my $address (sort { $$stats{'by_address'}{$b}{'count'} <=> $$stats{'by_address'}{$a}{'count'} ||
+ ncmp( $b, $a ) } keys %{ $$stats{'by_address'} } )
+ {
+ my $count = $$stats{'by_address'}{$address}{'count'};
+ my $country = GeoIP::lookup( $address );
+ my $first = $$stats{'by_address'}{$address}{'first'};
+ my $last = $$stats{'by_address'}{$address}{'last'};
+ my $percent = int( 100 * $count / $$stats{'total'} + 0.5);
+
+ last if ($count < $min_count);
+
+ my $name = $self->lookup_ip_address( $address );
+
+ $address = "$address\n$name" if ($name);
+
+ if ($country)
+ {
+ $country = GeoIP::get_full_country_name( $country) || $address;
+ }
+ else
+ {
+ $country = $Lang::tr{'unknown'};
+ }
+
+ push @table, [ $address, $country, $count, $percent, $first, $last ];
+
+ last if (@table > $self->get_max_lines_per_item + 2)
+ }
+
+ if (@table > 2)
+ {
+ $self->add_table( @table );
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#------------------------------------------------------------------------------
+# sub ports( this, min_count )
+#
+# Output information on blocked ports.
+#
+# Parameters:
+# this message object
+# min_count only output blocked ports occurring at least this number of
+# times
+#------------------------------------------------------------------------------
+
+sub ports( $$ )
+{
+ my ($self, $min_count) = @_;
+ my @table;
+
+ push @table, ['|', '|', '|', '|', '|'];
+ push @table, [ $Lang::tr{'port'}, $Lang::tr{'count'}, $Lang::tr{'percentage'}, $Lang::tr{'first'}, $Lang::tr{'last'} ];
+
+ my $stats = get_log( $self );
+
+ foreach my $port (sort { $$stats{'by_port'}{$b}{'count'} <=> $$stats{'by_port'}{$a}{'count'} ||
+ ncmp( $b, $a ) } keys %{ $$stats{'by_port'} } )
+ {
+ my $count = $$stats{'by_port'}{$port}{'count'};
+ my $first = $$stats{'by_port'}{$port}{'first'};
+ my $last = $$stats{'by_port'}{$port}{'last'};
+ my $percent = int( 100 * $count / $$stats{'total'} + 0.5);
+
+ last if ($count < $min_count);
+
+ push @table, [ $port, $count, $percent, $first, $last ];
+ }
+
+ if (@table > 2)
+ {
+ $self->add_table( @table );
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#------------------------------------------------------------------------------
+# sub countries( this, min_count )
+#
+# Output information on blocked countries.
+#
+# Parameters:
+# this message object
+# min_count only output blocked countries occurring at least this number of
+# times
+#------------------------------------------------------------------------------
+
+sub countries( $$ )
+{
+ my ($self, $min_count) = @_;
+ my @table;
+
+ push @table, ['<', '|', '|', '|', '|'];
+ push @table, [ $Lang::tr{'country'}, $Lang::tr{'count'}, $Lang::tr{'percentage'}, $Lang::tr{'first'}, $Lang::tr{'last'} ];
+
+ my $stats = get_log( $self );
+
+ foreach my $country (sort { $$stats{'by_country'}{$b}{'count'} <=> $$stats{'by_country'}{$a}{'count'} } keys %{ $$stats{'by_country'} } )
+ {
+ my $count = $$stats{'by_country'}{$country}{'count'};
+ my $first = $$stats{'by_country'}{$country}{'first'};
+ my $last = $$stats{'by_country'}{$country}{'last'};
+ my $percent = int( 100 * $count / $$stats{'total'} + 0.5);
+
+ last if ($count < $min_count);
+
+ my $full_country = GeoIP::get_full_country_name( $country) || $country;
+
+ push @table, [ $full_country, $count, $percent, $first, $last ];
+ }
+
+ if (@table > 2)
+ {
+ $self->add_table( @table );
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#------------------------------------------------------------------------------
+# sub reasons( this, min_count )
+#
+# Output information on blocked reasons (the IPtable blocking the packet).
+#
+# Parameters:
+# this message object
+# min_count only output blocked reasons occurring at least this number of
+# times
+#------------------------------------------------------------------------------
+
+sub reasons( $$ )
+{
+ my ($self, $min_count) = @_;
+ my @table;
+
+ push @table, ['<', '|', '|', '|', '|'];
+ push @table, [ $Lang::tr{'statusmail firewall reason'}, $Lang::tr{'count'}, $Lang::tr{'percentage'}, $Lang::tr{'first'}, $Lang::tr{'last'} ];
+
+ my $stats = get_log( $self );
+
+ foreach my $reason (sort { $$stats{'by_rule'}{$b}{'count'} <=> $$stats{'by_rule'}{$a}{'count'} } keys %{ $$stats{'by_rule'} } )
+ {
+ my $count = $$stats{'by_rule'}{$reason}{'count'};
+ my $first = $$stats{'by_rule'}{$reason}{'first'};
+ my $last = $$stats{'by_rule'}{$reason}{'last'};
+ my $percent = int( 100 * $count / $$stats{'total'} + 0.5);
+
+ last if ($count < $min_count);
+
+ push @table, [ $reason, $count, $percent, $first, $last ];
+ }
+
+ if (@table > 2)
+ {
+ $self->add_table( @table );
+
+ return 1;
+ }
+
+ return 0;
+}
+
+1;
--
2.16.4
next prev parent reply other threads:[~2019-04-05 17:29 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-05 17:29 [PATCH 00/12] statusmail: Status and Log Summary Emails Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 01/12] statusmail: Main script Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 02/12] statusmail: Perl module for encrypted Encrypted Mail Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 03/12] statusmail: WUI Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 04/12] statusmail: Supporting files Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 05/12] statusmail: Language files Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 06/12] statusmail: Infrastructure files Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 07/12] statusmail: Plugins for services Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 08/12] statusmail: Plugins for system Tim FitzGeorge
2019-04-05 17:29 ` Tim FitzGeorge [this message]
2019-04-05 17:29 ` [PATCH 10/12] statusmail: Graph infrastructure changes Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 11/12] statusmail: Plugin for apcupsd Tim FitzGeorge
2019-04-05 17:29 ` [PATCH 12/12] statusmail: Plugin for clamav Tim FitzGeorge
2019-04-08 16:10 ` [PATCH 00/12] statusmail: Status and Log Summary Emails Michael Tremer
2019-04-08 19:37 ` Tim FitzGeorge
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190405172940.13168-10-ipfr@tfitzgeorge.me.uk \
--to=ipfr@tfitzgeorge.me.uk \
--cc=development@lists.ipfire.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox