changeset 380:21686c6a9ac4

Fix and expand PHP logwatch config * PHP-FPM logs (or newer PHP?) are formatted slightly differently * Added separate "service" to summarise contact form anti-spam (Added actual scripts and config - 63adae1a374a just had Puppet. This is what happens when you commit & push in one!)
author IBBoard <dev@ibboard.co.uk>
date Sat, 16 Oct 2021 15:43:04 +0100
parents 63adae1a374a
children a4867ea13d84
files common/logwatch/contact-form common/logwatch/php common/logwatch/services_contact-form.conf
diffstat 3 files changed, 300 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/logwatch/contact-form	Sat Oct 16 15:43:04 2021 +0100
@@ -0,0 +1,128 @@
+###############################################################################
+#
+# IBBoard's customised version of the Logwatch service for php error logs
+# that extracts the anti-spam logging from his contact form
+#
+# Processes all anti-spam messages and summarizes them
+# Each message is given with a timestamp and RMS
+
+#######################################################
+## Copyright (C) 2006 by Jeremias Reith <jr@terragate.net>
+## Covered under the included MIT/X-Consortium License:
+##    http://www.opensource.org/licenses/mit-license.php
+## All modifications and contributions by other persons to
+## this script are assumed to have been donated to the
+## Logwatch project and thus assume the above copyright
+## and licensing terms.  If you want to make contributions
+## under your own copyright or a different license this
+## must be explicitly stated in the contribution an the
+## Logwatch project reserves the right to not accept such
+## contributions.  If you have made significant
+## contributions to this script and want to claim
+## copyright please contact logwatch-devel@lists.sourceforge.net.
+#########################################################
+
+use strict;
+use Logwatch ':dates';
+use Time::Local;
+use POSIX qw(strftime);
+
+my $date_format = '%d-%b-%Y %H:%M:%S';
+my $filter = TimeFilter($date_format);
+my $detail = exists $ENV{'LOGWATCH_DETAIL_LEVEL'} ? $ENV{'LOGWATCH_DETAIL_LEVEL'} : 0;
+
+# we do not use any Date:: package (or strptime) as they are probably not available
+my %month2num = ( Jan => 0, Feb => 1, Mar => 2, Apr => 3,
+                  May => 4, Jun => 5, Jul => 6, Aug => 7,
+                  Sep => 8, Oct => 9, Nov => 10, Dec => 11 );
+
+my $antispam_line = qr/Abuse of contact form with name '[^']+' by ([^ ]+) \(score ([0-9\.]+)/;
+my $ips = {};
+
+# counting messages
+while(<>) {
+    my $line = $_;
+    # skipping messages that are not within the requested range
+    # the last part of the regex matches optionally occurring specification
+    # of timezones, either in Continent/City or abbrevations like UTC
+    next unless $line =~ /^\[($filter)(?: \w+(?:\/\w+)?)?\]/o;
+    $1 =~ /(\d+)-(\w+)-(\d+) (\d+):(\d+):(\d+)/;
+    my $time;
+
+    {
+        # timelocal is quite chatty
+        local $SIG{'__WARN__'}  = sub {};
+        $time = timelocal($6, $5, $4, $1, $month2num{$2}, $3-1900);
+    }
+
+    if ($line =~ $antispam_line) {
+        $ips->{$1} = {count => '0',
+                       score => 0,
+                       first_occurrence => $time,
+                       sum => 0,
+                       sqrsum => 0} unless exists $ips->{$1};
+        $ips->{$1}->{'count'}++;
+        $ips->{$1}->{'score'} += $2;
+        # summing up timestamps and squares of timestamps
+        # in order to calculate the rms
+        # using first occurrence of message as offset in calculation to
+        # prevent an integer overflow
+        $ips->{$1}->{'sum'} += $time - $ips->{$1}->{'first_occurrence'};
+        $ips->{$1}->{'sqrsum'} += ($time - $ips->{$1}->{'first_occurrence'}) ** 2;
+    }
+}
+
+
+# generating summary
+    my $last_count = 0;
+
+    # sorting messages by count
+    my @sorted_ips = sort { $ips->{$b}->{'count'} <=> $ips->{$a}->{'count'} } keys %{$ips};
+
+    foreach my $ip (@sorted_ips) {
+        # grouping messages by number of occurrence
+        print "\n", $ips->{$ip}->{'count'}, " times:\n" unless $last_count == $ips->{$ip}->{'count'};
+        my $rms = 0;
+
+
+        # printing timestamp
+        print '[';
+
+        if($ips->{$ip}->{'count'} > 1) {
+            # calculating rms
+            $rms = int(sqrt(
+                           ($ips->{$ip}->{'count'} *
+                            $ips->{$ip}->{'sqrsum'} -
+                            $ips->{$ip}->{'sum'}) /
+                           ($ips->{$ip}->{'count'} *
+                            ($ips->{$ip}->{'count'} - 1))));
+
+            print strftime($date_format, localtime($ips->{$ip}->{'first_occurrence'}+int($rms/2)));
+
+            print ' +/-';
+
+            # printing rms
+            if($rms > 86400) {
+                print int($rms/86400) , ' day(s)';
+            } elsif($rms > 3600) {
+                print int($rms/3600) , ' hour(s)';
+            } elsif($rms > 60) {
+                print int($rms/60) , ' minute(s)';
+            } else {
+                print $rms, ' seconds';
+            }
+        } else {
+            # we have got this message a single time
+            print strftime($date_format, localtime($ips->{$ip}->{'first_occurrence'}));
+        }
+
+        print '] ', $ip, " with average score ", $ips->{$ip}->{'score'} / $ips->{$ip}->{'count'}, "\n";
+        $last_count = $ips->{$ip}->{'count'};
+    }
+
+# vi: shiftwidth=3 tabstop=3 et
+# Local Variables:
+# mode: perl
+# perl-indent-level: 3
+# indent-tabs-mode: nil
+# End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/logwatch/php	Sat Oct 16 15:43:04 2021 +0100
@@ -0,0 +1,157 @@
+###############################################################################
+# $Id$
+###############################################################################
+# $Log: php,v $
+# Revision 1.2  2008/03/24 23:31:26  kirk
+# added copyright/license notice to each script
+#
+# Revision 1.1  2006/11/12 18:28:31  bjorn
+# New php service, by Jeremias Reith.
+#
+###############################################################################
+#
+# Logwatch service for php error logs
+#
+# Processes all messages and summarizes them
+# Each message is given with a timestamp and RMS
+
+#######################################################
+## Copyright (C) 2006 by Jeremias Reith <jr@terragate.net>
+## Covered under the included MIT/X-Consortium License:
+##    http://www.opensource.org/licenses/mit-license.php
+## All modifications and contributions by other persons to
+## this script are assumed to have been donated to the
+## Logwatch project and thus assume the above copyright
+## and licensing terms.  If you want to make contributions
+## under your own copyright or a different license this
+## must be explicitly stated in the contribution an the
+## Logwatch project reserves the right to not accept such
+## contributions.  If you have made significant
+## contributions to this script and want to claim
+## copyright please contact logwatch-devel@lists.sourceforge.net.
+#########################################################
+
+use strict;
+use Logwatch ':dates';
+use Time::Local;
+use POSIX qw(strftime);
+
+my $date_format = '%d-%b-%Y %H:%M:%S';
+my $filter = TimeFilter($date_format);
+my $detail = exists $ENV{'LOGWATCH_DETAIL_LEVEL'} ? $ENV{'LOGWATCH_DETAIL_LEVEL'} : 0;
+
+# we do not use any Date:: package (or strptime) as they are probably not available
+my %month2num = ( Jan => 0, Feb => 1, Mar => 2, Apr => 3,
+		  May => 4, Jun => 5, Jul => 6, Aug => 7,
+		  Sep => 8, Oct => 9, Nov => 10, Dec => 11 );
+
+# array of message categories (we do not use a hash to keep the order)
+# first element: catorory name
+# second element: matching regexp ($1 should contain the message)
+# third element: anonymous hash ref (stores message  counts)
+my @message_categories = (['Fatal errors', qr/\] (?:PHP (?:Fatal|Parse) error|ERROR): (.*)$/o, {}],
+			  ['Warnings', qr/\] (?:PHP (?:Warning|Deprecated)|WARNING): (.*)$/o, {}],
+			  ['Notices', qr/\] (?:PHP Notice|NOTICE): (.*)$/o, {}]);
+
+# skipping categories depending on detail level
+pop(@message_categories) if $detail < 10;
+pop(@message_categories) if $detail < 5;
+
+
+# counting messages
+while(<>) {
+    my $line = $_;
+    # skipping messages that are not within the requested range
+    # the last part of the regex matches optionally occurring specification
+    # of timezones, either in Continent/City or abbrevations like UTC
+    next unless $line =~ /^\[($filter)(?: \w+(?:\/\w+)?)?\]/o;
+    $1 =~ /(\d+)-(\w+)-(\d+) (\d+):(\d+):(\d+)/;
+    my $time;
+
+    {
+	# timelocal is quite chatty
+	local $SIG{'__WARN__'}  = sub {};
+	$time = timelocal($6, $5, $4, $1, $month2num{$2}, $3-1900);
+    }
+
+    foreach my $cur_cat (@message_categories) {
+	if($line =~ /$cur_cat->[1]/) {
+	    my $msgs = $cur_cat->[2];
+	    $msgs->{$1} = {count => '0',
+			   first_occurrence => $time,
+			   sum => 0,
+			   sqrsum => 0} unless exists $msgs->{$1};
+	    $msgs->{$1}->{'count'}++;
+	    # summing up timestamps and squares of timestamps
+	    # in order to calculate the rms
+	    # using first occurrence of message as offset in calculation to
+	    # prevent an integer overflow
+	    $msgs->{$1}->{'sum'} += $time - $msgs->{$1}->{'first_occurrence'};
+	    $msgs->{$1}->{'sqrsum'} += ($time - $msgs->{$1}->{'first_occurrence'}) ** 2;
+	    last;
+	}
+    }
+}
+
+
+# generating summary
+foreach my $cur_cat (@message_categories) {
+    # skipping non-requested message types
+    next unless keys %{$cur_cat->[2]};
+    my ($name, undef, $msgs) = @{$cur_cat};
+    print $name, ":\n";
+    my $last_count = 0;
+
+    # sorting messages by count
+    my @sorted_msgs = sort { $msgs->{$b}->{'count'} <=> $msgs->{$a}->{'count'} } keys %{$msgs};
+
+    foreach my $msg (@sorted_msgs) {
+	# grouping messages by number of occurrence
+	print "\n", $msgs->{$msg}->{'count'}, " times:\n" unless $last_count == $msgs->{$msg}->{'count'};
+	my $rms = 0;
+
+
+	# printing timestamp
+        print '[';
+
+	if($msgs->{$msg}->{'count'} > 1) {
+	    # calculating rms
+	    $rms = int(sqrt(
+			   ($msgs->{$msg}->{'count'} *
+			    $msgs->{$msg}->{'sqrsum'} -
+			    $msgs->{$msg}->{'sum'}) /
+			   ($msgs->{$msg}->{'count'} *
+			    ($msgs->{$msg}->{'count'} - 1))));
+
+	    print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}+int($rms/2)));
+
+	    print ' +/-';
+
+	    # printing rms
+	    if($rms > 86400) {
+		print int($rms/86400) , ' day(s)';
+	    } elsif($rms > 3600) {
+		print int($rms/3600) , ' hour(s)';
+	    } elsif($rms > 60) {
+		print int($rms/60) , ' minute(s)';
+	    } else {
+		print $rms, ' seconds';
+	    }
+	} else {
+	    # we have got this message a single time
+	    print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}));
+	}
+
+	print '] ', $msg, "\n";
+	$last_count = $msgs->{$msg}->{'count'};
+    }
+
+    print "\n";
+}
+
+# vi: shiftwidth=3 tabstop=3 et
+# Local Variables:
+# mode: perl
+# perl-indent-level: 3
+# indent-tabs-mode: nil
+# End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/logwatch/services_contact-form.conf	Sat Oct 16 15:43:04 2021 +0100
@@ -0,0 +1,15 @@
+#
+# Service definition for the contact form anti-spam
+#
+# File to be placed in
+#	/etc/logwatch/conf/services/contact-form.conf
+#
+
+Title = contact-form
+
+# Which logfile group...
+LogFile = php
+
+# 
+Detail = High
+