initial commit of file from CVS for smeserver-zabbix-agent on Sat Sep 7 21:17:46 AEST 2024

This commit is contained in:
Trevor Batley
2024-09-07 21:17:46 +10:00
parent c771a7111d
commit 127b1311fe
51 changed files with 1771 additions and 2 deletions

View File

@@ -0,0 +1 @@
disabled

View File

@@ -0,0 +1 @@
127.0.0.1

View File

@@ -0,0 +1 @@
10050

View File

@@ -0,0 +1 @@
private

View File

@@ -0,0 +1 @@
enabled

View File

@@ -0,0 +1 @@
service

View File

@@ -0,0 +1,21 @@
#Only non rpm owned files are backupe there
{
use RPM2;
my $rpm_db = RPM2->open_rpm_db();
my @dirs = qw(
/etc/zabbix
/etc/zabbix/zabbix_agentd.conf.d/
/var/lib/zabbix/bin/
);
foreach my $some_dir (@dirs) {
next unless ( -e $some_dir );
opendir(my $dh, $some_dir) || die "Can't open $some_dir: $!";
while ( (my $file = readdir $dh) ) {
next if $file =~ /^\.{1,2}$/;
$OUT .= "$some_dir/$file\n" unless $rpm_db->find_by_file("$some_dir/$file");
}
closedir $dh;
}
}

View File

@@ -0,0 +1,20 @@
{
if ((${'zabbix-agent'}{'status'} || 'disabled') eq 'enabled'){
$OUT .=<<"HERE";
# Parse mail logs and write stats in zabbix tmp directory
*/10 * * * * root /var/lib/zabbix/bin/util_count_mail_in
*/10 * * * * root /var/lib/zabbix/bin/util_count_mail_out
HERE
if ((${'zabbix-agent'}{'StatusMail'} || 'disabled' ) eq 'enabled'){
$OUT .=<<'HERE';
# Send a status mail
*/15 * * * * root sleep $[ $RANDOM \% 120 ]; /var/lib/zabbix/bin/util_send_status_mail
HERE
}
}
}

View File

@@ -0,0 +1,2 @@
Cmnd_Alias ZABBIX_AGENT = /var/lib/zabbix/bin/*_sudo

View File

@@ -0,0 +1,2 @@
zabbix ALL=(root) NOPASSWD: ZABBIX_AGENT

View File

@@ -0,0 +1,28 @@
{
if ( -x '/usr/sbin/asterisk' ){
my $login = "";
my $user = ${'zabbix-agent'}{'AsteriskManagerLogin'} || '';
my $pass = ${'zabbix-agent'}{'AsteriskManagerPassword'} || '';
if ($user ne ''){
$login .= "--user=$user";
}
if ($pass ne ''){
$login .= " --secret=$pass";
}
$OUT.=<<"HERE"
# Type: Agent or Agent (active)
# Key: asterisk[key] where key can be max_latency, sip_peers, channels, internal_calls,
# outgoing_calls, incoming_calls, external_calls, duration_internal or duration_external
# Type of information: Numeric (integer 64bit)
# Units: depends on the key
# Custom multiplier: Do not use
# Store Value: As is
UserParameter=asterisk[*],/var/lib/zabbix/bin/check_asterisk $login --what=\$1
HERE
}
}

View File

@@ -0,0 +1,13 @@
{
$OUT = '';
qx(zabbix_agentd -t vfs.dev.discovery -c /dev/null | grep -q ZBX_NOTSUPPORTED);
if ($? != 0){
$OUT .= '# vfs.dev.discovery is natively supported, not UserParameter needed';
} else{
$OUT .=<<'_EOF';
# Discover block devices
UserParameter=vfs.dev.discovery,/var/lib/zabbix/bin/disco_block_devices
_EOF
}
}

View File

@@ -0,0 +1,14 @@
# Number of CPU
# Description: Number of CPU
# Type: Agent or Agent (active)
# Key: cpu.number
# Type of information: Numeric (integer 64bit)
# Units: cpu
# Use multiplier: do not use
# Update interval: 86400 (once a day)
# Store Value: As is
# Show Value: As is
UserParameter=cpu.number,cat /proc/cpuinfo | grep processor | wc -l

View File

@@ -0,0 +1,24 @@
# Amount of used memory (the agent lacks this stats)
# Description: Used Memory
# Type: Agent or Agent (active)
# Key: vm.memory.size.used
# Type of information: Numeric (integer 64bit)
# Units: B
# Use multiplier: do not use
# Store Value: As is
# Show Value: As is
UserParameter=vm.memory.size.used,free -b | grep 'buffers/cache' | awk '\{print $3\}'
# Amount of used memory in % (the agent lacks this stats)
# Description: Used Memory in %
# Type: Agent or Agent (active)
# Key: vm.memory.size.pused
# Type of information: Numeric (integer 64bit)
# Units: %
# Use multiplier: do not use
# Store Value: As is
# Show Value: As is
UserParameter=vm.memory.size.pused,echo $(($(free -b | grep 'buffers/cache' | awk '\{print $3\}')*100/$(free -b | grep 'Mem' | awk '\{print $2\}')))

View File

@@ -0,0 +1,62 @@
# Some networks statistics
# zabbix agent support natively interface stats, but, it's hard to create templates for a lot of
# SME Servers which can use different interface name (External can be eth0, eth1, ppp0 etc...)
# This way, net.if.in.internal, net.if.in.external, net.if.out.internal and net.if.out.external
# will always refers to the correct interface.
{
my $internal = $InternalInterface{'Name'} || 'eth0';
my $external = $ExternalInterface{'Name'} || 'eth1';
# Do we use the bridge contrib ?
# If yes, we reports only the traffic on the real ethernet interface.
if ( (($bridge{'status'} || 'disabled') eq 'enabled') && (defined $bridge{'ethernetInterface'}) ){
$internal = $bridge{'ethernetInterface'};
}
$OUT .=<<"HERE";
# Description: In Internal
# Type: Agent or Agent (active)
# Key: net.if.in.internal
# Type of information: Numeric (float)
# Units: b/s
# Custom multiplier: 8 (if you want the value in bits/s instead of Bytes/s)
# Store Value: Delta (speed per second)
UserParameter=net.if.in.internal,cat /proc/net/dev | grep $internal | cut -d":" -f2 | awk '{print \$1}'
# Description: Out Internal
# Type: Agent or Agent (active)
# Key: net.if.out.internal
# Type of information: Numeric (float)
# Units: b/s
# Custom multiplier: 8 (if you want the value in bits/s instead of Bytes/s)
# Store Value: Delta (speed per second)
UserParameter=net.if.out.internal,cat /proc/net/dev | grep $internal | cut -d":" -f2 | awk '{print \$9}'
HERE
if (($SystemMode || 'serveronly') ne 'serveronly'){
$OUT .=<<"HERE";
# Description: In External
# Type: Agent or Agent (active)
# Key: net.if.in.external
# Type of information: Numeric (float)
# Units: b/s
# Custom multiplier: 8 (if you want the value in bits/s instead of Bytes/s)
# Store Value: Delta (speed per second)
UserParameter=net.if.in.external,cat /proc/net/dev | grep $external | cut -d":" -f2 | awk '{print \$1}'
# Description: Out External
# Type: Agent or Agent (active)
# Key: net.if.out.external
# Type of information: Numeric (float)
# Units: b/s
# Custom multiplier: 8 (if you want the value in bits/s instead of Bytes/s)
# Store Value: Delta (speed per second)
UserParameter=net.if.out.external,cat /proc/net/dev | grep $external | cut -d":" -f2 | awk '{print \$9}'
HERE
}
}

View File

@@ -0,0 +1,12 @@
# Amount of used swap in bytes
# Description: Used swap space
# Type: Agent or Agent (active)
# Key: system.swap.size.used
# Type of information: Numeric (integer 64bit)
# Units: B
# Multiplier: do not use
# Store Value: As is
# Show Value: As is
UserParameter=system.swap.size.used,free -b | grep Swap | awk '\{print $3\}'

View File

@@ -0,0 +1,9 @@
# Retrieve real external IP
# Description: Ext IP
# Type: Agent or Agent (active)
# Key: ip.external
# Type of information: Character
# Show Value: As is
UserParameter=ip.external,/usr/bin/curl --connect-timeout 5 -s -o - -k "http://www.wimip.fr/?t="

View File

@@ -0,0 +1,15 @@
# Incomming mails statistics
# Description: Incoming Mail <key>
# Type: Agent or Agent (active)
# Key: mail.in[<key>] (for example mail.in[dnsbl])
# Type of information: Numeric (integer 64bit)
# Units: mails/h
# Use multiplier: Custom multiplier
# Custom multiplier: 6
# Update interval: 600
# Store Value: As is
# Show Value: As is
UserParameter=mail.in[*],cat /var/lib/zabbix/tmp/mail.in.$1

View File

@@ -0,0 +1,16 @@
# Outgoing mails statistics
# Description: Incoming Mail <key>
# Type: Agent or Agent (active)
# Key: mail.out.[<key>] (for example mail.out[total])
# Type of information: Numeric (integer 64bit)
# Units: mails/h
# Use multiplier: Custom multiplier
# Custom multiplier: 6
# Update interval: 600
# Store Value: As is
# Show Value: As is
UserParameter=mail.out[*],cat /var/lib/zabbix/tmp/mail.out.$1

View File

@@ -0,0 +1,15 @@
# Some stats about MySQL
# Description: MySQL <key>
# Type: Agent or Agent (active)
# Type of information: Numeric (float)
# Unit: <depend on the key> (for example, qps)
# Use multiplier: do not use
# Store Value: As is
UserParameter=mysql.uptime,/usr/bin/sudo /var/lib/zabbix/bin/check_mysqladmin_status_sudo | cut -d" " -f2
UserParameter=mysql.threads,/usr/bin/sudo /var/lib/zabbix/bin/check_mysqladmin_status_sudo | cut -d" " -f5
UserParameter=mysql.questions,/usr/bin/sudo /var/lib/zabbix/bin/check_mysqladmin_status_sudo | cut -d" " -f8
UserParameter=mysql.slowqueries,/usr/bin/sudo /var/lib/zabbix/bin/check_mysqladmin_status_sudo | cut -d" " -f12
UserParameter=mysql.qps,/usr/bin/sudo /var/lib/zabbix/bin/check_mysqladmin_status_sudo | cut -d" " -f29

View File

@@ -0,0 +1,23 @@
{
if (-e '/opt/phpki/phpki-store/CA/index.txt'){
$OUT .=<<'EOF';
# Discovery of certificates and their status
# Key: pki.certs.discovery
# Macro:
# - {#CRTCN} : contains the common name
# - {#CRTSERIAL} : the serial number
# - {#CRTSTATUS} : the status, as a string (valid, revoked, expired)
# Available arguments:
# --index : path to the index file
# --path : directory where certificatres are stored, certificates should be named $serial.pem (in PEM format)
UserParameter=pki.certs.discovery,/usr/bin/sudo /var/lib/zabbix/bin/disco_certs_sudo --index=/opt/phpki/phpki-store/CA/index.txt --path=/opt/phpki/phpki-store/CA/newcerts/
UserParameter=pki.certs[*],/usr/bin/sudo /var/lib/zabbix/bin/check_certs_sudo --what=$1 --cert=$2
EOF
}
$OUT .= '';
}

View File

@@ -0,0 +1,2 @@
# Check if nmbd is available and working
UserParameter=samba.nmbd.status,/var/lib/zabbix/bin/check_nmblookup --server=127.0.0.1 --host={$smb{ServerName};}

View File

@@ -0,0 +1,2 @@
Server={ (${'zabbix-agent'}{'Servers'} || '127.0.0.1'); }

View File

@@ -0,0 +1,6 @@
{
my $host = (${'zabbix-agent'}{'Hostname'} || $SystemName.".".$DomainName);
$OUT = "Hostname=$host\n";
}

View File

@@ -0,0 +1,11 @@
ListenPort={ (${'zabbix-agent'}{'TCPPort'} || '10050'); }
{
my $access = ${'zabbix-agent'}{'access'} || 'private';
my $listen = '127.0.0.1';
$listen = $LocalIP if ($access eq 'private');
$listen = '' if ($access eq 'public');
$OUT .= "ListenIP=$listen\n" if ($listen ne '');
}

View File

@@ -0,0 +1 @@
StartAgents=5

View File

@@ -0,0 +1,2 @@
BufferSend=30
BufferSize=100

View File

@@ -0,0 +1,5 @@
{
if ((${'zabbix-agent'}{'ServerActive'} || '') ne ''){
$OUT .= "ServerActive=${'zabbix-agent'}{'ServerActive'}\n";
}
}

View File

@@ -0,0 +1 @@
EnableRemoteCommands={ (${'zabbix-agent'}{'RemoteCommands'} || 'disabled') eq 'enabled' ? '1':'0'; }

View File

@@ -0,0 +1,5 @@
DebugLevel=3
PidFile=/var/run/zabbix/zabbix_agentd.pid
LogFile=/var/log/zabbix/zabbix_agentd.log
LogFileSize=10

View File

@@ -0,0 +1 @@
Include=/etc/zabbix/zabbix_agentd.conf.d/

View File

@@ -0,0 +1,5 @@
# Spend no more than Timeout seconds on processing
# Must be between 1 and 30
Timeout={${'zabbix-agent'}{'TimeOut'} || '3'}

View File

@@ -0,0 +1,33 @@
{
my @encryptions = ();
my $psk_file = ${'zabbix-agent'}{'TLSPSKFile'} || '/etc/zabbix/zabbix_agentd.psk';
my $psk_id = ${'zabbix-agent'}{'TLSPSKIdentity'} || $SystemName . '.' . $DomainName . '-agent';
if (-s $psk_file){
push @encryptions, 'psk';
$OUT .=<<_EOF;
TLSPSKFile=$psk_file
TLSPSKIdentity=$psk_id
_EOF
}
my $cert = ${'zabbix-agent'}{'TLSCertFile'} || '/etc/zabbix/zabbix_agentd.crt';
my $key = ${'zabbix-agent'}{'TLSKeyFile'} || '/etc/zabbix/zabbix_agentd.key';
my $ca = ${'zabbix-agent'}{'TLSCAFile'} || '/etc/zabbix/zabbix_agentd.ca';
if (-s $cert && -s $key && -s $ca){
push @encryptions, 'cert';
$OUT .=<<_EOF;
TLSCertFile=$cert
TLSKeyFile=$key
TLSCAFile=$ca
_EOF
my $issuer = ${'zabbix-agent'}{'TLSServerCertIssuer'} || '';
my $subject = ${'zabbix-agent'}{'TLSServerCertSubject'} || '';
$OUT .= "TLSServerCertIssuer=$issuer\n" if ($issuer ne '');
$OUT .= "TLSServerCertSubject=$subject\n" if ($subject ne '');
}
my $encryptions = (scalar @encryptions > 0) ? join(',', @encryptions) : '';
$OUT .=<<_EOF if ($encryptions ne '');
TLSConnect=$encryptions
TLSAccept=$encryptions
_EOF
}

View File

@@ -0,0 +1,2 @@
[Install]
WantedBy=sme-server.target

View File

@@ -0,0 +1,210 @@
#!/usr/bin/perl -w
use Asterisk::AMI::Common;
use Getopt::Long;
open STDERR, '>/dev/null';
# Set some default
my $host = '127.0.0.1';
my $port = '5038';
my $user = 'zabbixagent';
my $secret = 'zabbixsecret';
my $what = 'sip_peers';
GetOptions(
"host=s" => \$host,
"port=s" => \$port,
"user=s" => \$user,
"secret=s" => \$secret,
"what=s" => \$what
);
our $ast = Asterisk::AMI::Common->new(
PeerAddr => $host,
PeerPort => $port,
Username => $user,
Secret => $secret
);
die "Unable to connect to asterisk manager" unless ($ast);
sub help{
print<<"EOF";
usage: $0 --host=asterisk.domain.tld --port=5038 --user=manager --secret=azerty --what=sip_peers
--what can take the following argument:
* sip_peers: number of connected sip peers
* max_latency: highest latency of connected sip_peers
* channels: total number of active channels
* internal_calls: number of active internal calls
* outgoing_calls: number of active outgoing calls (external)
* incoming_calls: number of active incoming calls (external)
* external_calls: number of external calls (in + out)
* duration_internal: actual highest duration of internal calls
* duration_external: actual highest duration of external calls
EOF
}
if ($what eq 'sip_peers'){
print get_connected_peers_num('sip');
}
elsif ($what eq 'max_latency'){
print get_max_peer_latency();
}
elsif($what eq 'channels'){
print get_active_channels_num();
}
elsif ($what eq 'internal_calls'){
print get_internal_call_num();
}
elsif ($what eq 'outgoing_calls'){
print get_outgoing_call_num();
}
elsif ($what eq 'incoming_calls'){
print get_incoming_call_num();
}
elsif ($what eq 'external_calls'){
print get_outgoing_call_num() + get_incoming_call_num();
}
elsif ($what eq 'duration_internal'){
print get_max_duration_internal();
}
elsif ($what eq 'duration_external'){
print get_max_duration_external();
}
else{
help();
$ast->disconnect();
exit (1);
}
$ast->disconnect();
exit(0);
# Return the number of connected peers for
# the specified protocol (only SIP supporteed for now)
sub get_connected_peers_num{
my $proto = shift;
my $peers;
if ($proto eq 'sip'){
$peers = get_sip_peers();
}
else{
return 'unsupported protocol';
}
my $num = 0;
foreach my $peer (keys %{$peers}){
my $status = $peers->{$peer}->{'Status'};
$num++ if ($status =~ m/^OK/);
}
return $num;
}
# Return the list of SIP peers (as a hashref)
sub get_sip_peers{
return $ast->sip_peers();
}
# Return the highest latency of all the peers
sub get_max_peer_latency{
my $peers = get_sip_peers();
my $latency = 0;
foreach my $peer (keys %{$peers}){
my $status = $peers->{$peer}->{'Status'};
$status =~ /\((\d+)\sms\)/;
$latency = $1 if ($1 > $latency);
}
return $latency;
}
# Return channels list as a hashref
sub get_channels(){
return $ast->channels();
}
# Return the number of channels
sub get_active_channels_num{
my $channels = get_channels();
my $num = 0;
foreach my $chan (keys %{$channels}){
$num++;
}
return $num;
}
# Return the number of active channels
sub get_up_channels_num{
my $channels = get_channels();
my $num = 0;
foreach my $chan (keys %{$channels}){
my $status = $channels->{$chan}->{'State'};
$num++ if ($status eq 'Up');
}
return $num;
}
# Return the number of outgoing calls
sub get_outgoing_call_num{
my $channels = get_channels();
my $num = 0;
foreach my $chan (keys %{$channels}){
my $context = $channels->{$chan}->{'Context'};
my $status = $channels->{$chan}->{'State'};
$num++ if ($context eq 'macro-dialout-trunk' and $status eq 'Up');
}
return $num;
}
# Return the number of incoming calls
sub get_incoming_call_num{
my $channels = get_channels();
my $num = 0;
foreach my $chan (keys %{$channels}){
my $context = $channels->{$chan}->{'Context'};
my $status = $channels->{$chan}->{'State'};
$num++ if ($context =~ /^from\-(trunk|pstn|zaptel|dahdi)/ and $status eq 'Up');
}
return $num;
}
# Return the number of internal calls
sub get_internal_call_num{
my $channels = get_channels();
my $num = 0;
foreach my $chan (keys %{$channels}){
my $context = $channels->{$chan}->{'Context'};
my $status = $channels->{$chan}->{'State'};
$num++ if (($context eq 'macro-dial' or $context eq 'from-internal') and $status eq 'Up');
}
return $num
}
# Return the max duration of current internal calls
sub get_max_duration_internal{
my $channels = get_channels();
my $max = 0;
foreach my $chan (keys %{$channels}){
my $dur = $channels->{$chan}->{'Seconds'};
my $context = $channels->{$chan}->{'Context'};
$max = $dur if (($context eq 'macro-dial' or $context eq 'from-internal') and $dur > $max);
}
return $max
}
# Return the max duration of current external calls (in or out)
sub get_max_duration_external{
my $channels = get_channels();
my $max = 0;
foreach my $chan (keys %{$channels}){
my $dur = $channels->{$chan}->{'Seconds'};
my $context = $channels->{$chan}->{'Context'};
$max = $dur if (($context eq 'macro-dialout-trunk' or $context =~ /^from\-(trunk|pstn|zaptel|dahdi)/) and $dur > $max);
}
return $max
}

View File

@@ -0,0 +1,33 @@
#!/usr/bin/perl -w
# Check a PEM certificate
# --what: what to monitor. Only expire is supported for now, and returns the number of day before expiration
# --cert: the path to the certificate you want to check
use strict;
use warnings;
use Crypt::OpenSSL::X509;
use Date::Parse;
use Getopt::Long;
my $what = 'expire';
my $cert = '';
GetOptions(
"cert=s" => \$cert,
"what=s" => \$what
);
die "Usage: $0 --what=status --cert=/path/to/pem/certificate\n" unless
(-f $cert);
$cert = Crypt::OpenSSL::X509->new_from_file( "$cert" );
my $expire_in = int ((str2time($cert->notAfter())-time())/(3600*24));
if ($what eq 'expire'){
print $expire_in;
}
else{
die "Only expire is supported for now";
}

View File

@@ -0,0 +1,5 @@
#!/bin/sh
HOME=/root
exec /usr/bin/mysqladmin status

View File

@@ -0,0 +1,49 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Crypt::OpenSSL::X509;
use Date::Parse;
use Getopt::Long;
use JSON;
my $index = '/opt/phpki/phpki-store/CA/index.txt';
my $path = '/opt/phpki/phpki-store/CA/newcerts';
GetOptions(
"index=s" => \$index,
"path=s" => \$path
);
open INDEX, "$index" or die "Couldn't open $index\n";
my $json;
foreach my $l (<INDEX>){
next unless $l =~ m/^([VR])\t\d+Z\t(\d+Z)?\t(\w+)\tunknown\t.*/;
my $status = $1;
my $serial = $3;
my $cert = Crypt::OpenSSL::X509->new_from_file( "$path/$serial.pem" );
my $expire_in = int ((str2time($cert->notAfter())-time())/(3600*24));
if ($status eq 'V'){
$status = 'valid';
}
elsif ($expire_in lt 0){
$status = 'expired';
}
else{
$status = 'revoked';
}
my $subject = $cert->subject;
$subject =~ m/.*\sCN=(.*),/;
my $cn = $1;
push @{$json->{data}}, {
"{#CRTCN}" => $cn,
"{#CRTSERIAL}" => $serial,
"{#CRTSTATUS}" => $status,
};
}
close INDEX;
print to_json($json);

View File

@@ -0,0 +1,13 @@
#!/bin/bash
BINDIR='/var/lib/zabbix/bin'
LOGTAIL=$BINDIR'/util_logtail'
PARSER=$BINDIR'/util_parse_mail_in'
LOGFILE='/var/log/qpsmtpd/current'
TMPDIR='/var/lib/zabbix/tmp/'
for WHAT in $($BINDIR/util_parse_mail_in keys); do
$LOGTAIL $LOGFILE $TMPDIR/mail.in.$WHAT.offset | $PARSER $WHAT > $TMPDIR/mail.in.$WHAT
done

View File

@@ -0,0 +1,11 @@
#!/bin/bash
BINDIR='/var/lib/zabbix/bin'
LOGTAIL=$BINDIR'/util_logtail'
PARSER=$BINDIR'/util_parse_mail_out'
LOGFILE='/var/log/qmail/current'
TMPDIR='/var/lib/zabbix/tmp/'
for WHAT in failure deferral success total; do
$LOGTAIL $LOGFILE $TMPDIR/mail.out.$WHAT.offset | $PARSER $WHAT > $TMPDIR/mail.out.$WHAT
done

View File

@@ -0,0 +1,95 @@
#!/usr/bin/perl
# Copyright (C) 2009 Daniel Berteaud <daniel@firewall-services.com>
# Copyright (C) 2003 Jonathan Middleton <jjm@ixtab.org.uk
# Copyright (C) 2001 Paul Slootman <paul@debian.org>
# This file is part of Logcheck.
# Modifications for integration with smeserver-zabbix-agent
# Logcheck 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 2 of the License, or
# (at your option) any later version.
# Logcheck 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 Foobar; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
my ($logfile, $offsetfile) = @ARGV;
if (! -f $logfile) {
print "File $logfile cannot be read.\n";
exit 66;
}
unless ($offsetfile) {
# offsetfile not given, use .offset/$logfile in the same directory
$offsetfile = $logfile . '.offset';
}
unless (open(LOGFILE, $logfile)) {
print "File $logfile cannot be read.\n";
exit 66;
}
my ($inode, $offset) = (0, 0);
if (open(OFFSET, $offsetfile)) {
$_ = <OFFSET>;
unless (! defined $_) {
chomp $_;
$inode = $_;
$_ = <OFFSET>;
unless (! defined $_) {
chomp $_;
$offset = $_;
}
}
}
my ($ino, $size);
unless ((undef,$ino,undef,undef,undef,undef,undef,$size) = stat $logfile) {
print "Cannot get $logfile file size.\n", $logfile;
exit 65;
}
if ($inode == $ino) {
exit 0 if $offset == $size; # short cut
if ($offset > $size) {
$offset = 0;
#print "***************\n";
#print "*** WARNING ***: Log file $logfile is smaller than last time checked!\n";
#print "*************** This could indicate tampering.\n";
}
}
if ($inode != $ino || $offset > $size) {
$offset = 0;
}
seek(LOGFILE, $offset, 0);
while (<LOGFILE>) {
print $_;
}
$size = tell LOGFILE;
close LOGFILE;
unless (open(OFFSET, ">$offsetfile")) {
print "File $offsetfile cannot be created. Check your permissions.\n";
exit 73;
}
unless (chmod 0600, $offsetfile) {
print "Cannot set permissions on file $offsetfile\n";
exit 65;
}
print OFFSET "$ino\n$size\n";
close OFFSET;
exit 0;

View File

@@ -0,0 +1,129 @@
#!/usr/bin/perl -w
# Copyright (C) 2009-2016 Daniel Berteaud <daniel@firewall-services.com>
# This file is part of smeserver-zabbix-agent package.
# This script 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 2 of the License, or
# (at your option) any later version.
# This script 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 Foobar; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# This script parse qpsmtpd logs (which must be sent to STDIN), and count the number
# of emails rejected by each plugins, and those accepted. You need to logterse plugin enabled
my $what = $ARGV[0] || '';
# This is the list of plugins we can get stats for
# you can set the regex used to identify a line in the logs
my %denied = (
dnsbl => qr{(dnsbl\s+90|naughty\s+90\d\s+\(dnsbl\))},
rhsbl => qr{rhsbl\s+90},
uribl => qr{uribl\s+90},
clamav => qr{virus::clam(av|dscan)\s+90},
check_earlytalker => qr{(check_)?earlytalker\s+90},
check_basicheaders => qr{(check_basic)?headers\s+90},
check_goodrcptto => qr{(check_)?goodrcptto\s+90},
check_spamhelo => qr{((check_spam)?helo\s+90|naughty\s+90\d\s+\(helo\))},
fcrdns => qr{fcrdns\s+90},
karma => qr{(karma\s+90|naughty\s+90\d\s+\(karma\))},
spf => qr{(sender_permitted_from|spf_deny)\s+90},
dmarc => qr{dmarc\s+90},
tls_failed => qr{tls\s+90},
resolvable_fromhost => qr{(require_)?resolvable_fromhost}
);
my @others = qw(total_denied spam_denied other_denied spam_queued queued total);
# If arg is keys, just print the supported keys and exit
if ($what eq "keys"){
print join "\n", (keys %denied, @others);
exit (0)
}
my %cnt;
foreach (keys %denied, @others){
$cnt{$_} = 0;
}
while (<STDIN>) {
my $line = $_;
# We only want logterse lines like
# @400000004994ad092afa867c 18386 logging::logterse plugin:
# The format can slightly change depending on qpsmtpd version
next unless $line =~ m/^\@[0-9a-f]{24} \d+( \((queue|deny)\))? logging::logterse/;
# Lets count all the message which have been denied 'msg denied before queued'
if ($line =~ m/msg denied before queued/){
$cnt{total_denied}++;
# Now try to find the plugin responsible for the deny
foreach (keys %denied){
if ($line =~ m/$denied{$_}/){
$cnt{$_}++;
}
}
next;
}
# Rejected by spamassassin because spam score is too high
elsif ($line =~ m/spam score exceeded threshold/){
$cnt{spam_denied}++;
next;
}
# Tagged as spam, but kept accepted
elsif ($line =~ m/queued\s+<.*>\s+Yes,\s+(score|hits)=/){
$cnt{spam_queued}++;
next;
}
# Queued, not tagged as spam (or spam filtering disabled), those are the clean emails
elsif ($line =~ m/queued\s+<.*>(\s+No,\s+(score|hits)=.+)?/){
$cnt{queued}++;
next;
}
}
# Now lets count other_denied, which is total_denied minus
# all the known plugins denied
$cnt{other_denied} = $cnt{total_denied};
foreach (keys %denied){
$cnt{total} = $cnt{total} + $cnt{$_};
$cnt{other_denied} = $cnt{other_denied} - $cnt{$_};
}
foreach (@others){
$cnt{total} = $cnt{total} + $cnt{$_} if ($_ !~ /total/);
}
# The print argument prints all on stdout
if ($what eq "print"){
foreach (keys %denied,@others){
print "$_: $cnt{$_}\n";
}
}
# If the arg is a known plugin, prints only its value
elsif (defined $cnt{$what}){
print "$cnt{$what}\n";
}
# Else, print an error
else{
print "supported items are: ";
foreach (keys %denied, @others){
print "$_ ";
}
print "\n";
exit 1;
}
exit 0;

View File

@@ -0,0 +1,70 @@
#!/usr/bin/perl -w
# Copyright (C) 2009 Daniel Berteaud <daniel@firewall-services.com>
# This file is part of smeserver-zabbix-agent package.
# This script 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 2 of the License, or
# (at your option) any later version.
# This script 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 Foobar; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
my $what = $ARGV[0] || '';
# On initialise nos compteurs a 0
my @results = qw(failure deferral success total);
my %cnt;
foreach (@results){
$cnt{$_} = 0;
}
while (<STDIN>) {
my $line = $_;
# on limites aux lignes concernant l'envoie
# @400000004994ad092afa867c delivery 96906: success etc...
next unless $line =~ m/^\@[0-9a-f]{24} delivery \d+: (success|failure|deferral).*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|CNAME_lookup_failed_temporarily)/;
my $result = $1;
$cnt{$result}++;
}
# Caclul des totaux:
foreach (@results){
$cnt{total} = $cnt{total} + $cnt{$_} if $_ !~ /total/;
}
# Si l'argument est "print" on affiche toutes les stats
if ($what eq "print"){
foreach (@results){
print "$_: $cnt{$_}\n";
}
}
# Si l'argument correspond a un compteur definit
# On affiche uniquemment cette valeur
elsif (defined $cnt{$what}){
print "$cnt{$what}\n";
}
# Sinon, on quitte avec une erreur
else{
print "supported items are: ";
foreach (@results){
print "$_ ";
}
print "\n";
exit 1;
}
exit 0;

View File

@@ -0,0 +1,31 @@
#!/usr/bin/perl -w
use esmith::ConfigDB;
use MIME::Lite;
use Net::SMTP;
my $c = esmith::ConfigDB->open_ro();
my $domain = $c->get('DomainName')->value();
my $host = $c->get('SystemName')->value();
my $z = $c->get('zabbix-agent');
my $dest = $z->prop('StatusRecipient') || 'admin@' . $domain;
my $smtp = Net::SMTP->new('localhost');
my $mail = MIME::Lite->new(
From => 'smeserver-status@' . $domain,
To => $dest,
Subject => "[STATUS] $host.$domain",
Data => localtime(time)."\n" .
"\n#>tail /var/log/messages :\n" .
`/usr/bin/tail \$(readlink /var/log/messages)` .
"\n#>netstat --numeric-hosts -tpu :\n" .
`/bin/netstat --numeric-hosts -tpu`
);
$smtp->mail('smeserver-status@' . $domain);
$smtp->recipient($dest);
$smtp->data();
$smtp->datasend($mail->as_string);
$smtp->dataend();
$smtp->quit;