Hello Marcel,
> does ClamAV provide SNMP support? My idea is that ClamAV sends snmp
> traps with all information (like the results at the prompt) to a snmp
> server like OpenNMS, when a virus was found. OpenNMS is a network
> management system. Primary it monitors network infrastructures. But
> you can also handle snmp traps from printers, servers, programs and
> and and...
> So why not from ClamAV?
You're talking about the command line (prompt) so I guess you are not scanning
emails but
rather directories... but, who knows, this might give you ideas.
I use ClamAV for mail scanning and I don't send traps on mail viruses and spams
as there
are too many of them, but I let my management system query the mail relay via
SNMP every
5 minutes.
I added this to my snmpd.conf:
exec 1.3.6.1.4.1.2021.8.990 mailstat.pl /usr/sbin/mailstat.pl -t
exec 1.3.6.1.4.1.2021.8.991 mailstat.pl /usr/sbin/mailstat.pl -v
And I created the mailstat.pl as follows. Of course, depending on your needs
and on the tools
you use, you might have to tune this... It computes statistics out of
/var/log/syslog and out of
the output of /usr/bin/mailstats (that you might need to initialize first, and
reset at midnight for
instance). Persistent counters are saved in /var/log/mailstats.
--mailstat.pl---------------------------
#!/usr/bin/perl
# Dhn, 2008/06/30
# Script used by snmpd to collect and return mail statistics but
# it can run from the CLI too.
# Usage: mailstat.pl [-t] [-v]
# Returns the "title:value" statistics by defaults, or only the titles (-t)
# or only the values (-v). The statistics are always displayed in the
# same order (see @keys array).
#use strict;
# Defaults
my $in="/var/log/syslog"; # log pipe
my $stats="/var/log/mailstats"; # persistent counters
my $fl = ""; # flags for output (''|t|v)
my %ctr = (); # current counters
my $w = 0; # write flag
my @ln = (); # splitted line
my @arr = (); # splitted word
my @stat = (); # file stats
my $key = ""; # one hash key
my $out = ""; # buffer for outputt
#my $pos = 0; # current position
my @keys = qw/accepted blacklisted discard greeting ham mail pca seen spam
unknown
virus bytesfr bytesto msgsfr msgsto connfr connto mailq inode position
zlast/;
# Functions / handlers
sub writestats {
$ctr{"seen"} = $ctr{"greeting"} + $ctr{"blacklisted"} + $ctr{"unknown"} +
$ctr{"spam"} +
+ $ctr{"virus"} + $ctr{"ham"};
$ctr{"accepted"} = $ctr{"spam"} - $ctr{"discard"} + $ctr{"ham"};
$ctr{"pca"} = int(($ctr{"seen"} != 0) ? (10000 * $ctr{"accepted"} /
$ctr{"seen"}) : 0)/100;
#$ctr{"position"} = $pos;
open OUT, ">", $stats or die "Cannot open $stats for writing: $!\n";
$out = "";
#foreach $key (sort keys %ctr) {
foreach $key (@keys) {
if ($key eq "zlast") {
printf OUT "%12s: %-60s\n", $key, $ctr{$key};
} else {
printf OUT "%12s: %12d\n", $key, $ctr{$key};
}
&saveout($key);
}
close OUT;
$w = 0;
}
sub saveout {
my $key = @_[0];
return if ($key eq "inode" || $key eq "position" || $key eq "zlast");
if ($fl eq "t") {
$out .= "$key\n";
} elsif ($fl eq "v") {
$out .= "$ctr{$key}\n";
} else {
$out .= sprintf("%12s: %12d\n", $key, $ctr{$key});
}
}
sub computestats {
seek IN, $ctr{"position"}, SEEK_SET;
#$pos = $ctr{"position"};
while (<IN>) {
#$pos += length($_);
$ctr{"position"} += length($_);
$ctr{"zlast"} = substr($_, 0, 60);
@ln = split;
if (/ sendmail.* reject=550 5.7.1 Spam blocked /) {
$ctr{"blacklisted"}++; $w++;
} elsif (/ sendmail.* reject=550 5.1.1 .* User unknown/) {
$ctr{"unknown"}++; $w++;
} elsif (/ sendmail.* due to pre-greeting traffic/) {
$ctr{"greeting"}++; $w++;
} elsif ($ln[4] =~ /^mimedefang.pl/ && $ln[8] =~ /^MDLOG,/) {
@arr = split /,/, $ln[8];
#if ($arr[2] eq "spam" && $arr[3] > 9) {
# $ctr{"spam"}++; $ctr{"discard"}++; $w++;
if ($arr[2] eq "spamd") {
$ctr{"spam"}++; $ctr{"discard"}++; $w++;
} elsif ($arr[2] eq "spam") {
$ctr{"spam"}++; $w++;
} elsif ($arr[2] eq "virus") {
if ($arr[3] =~ /^Sanesecurity/) {
$ctr{"spam"}++; $ctr{"discard"}++; $w++;
} else {
$ctr{"virus"}++; $w++;
}
} elsif ($arr[2] eq "ham") {
$ctr{"ham"}++; $w++;
} elsif ($arr[2] eq "mail_in") {
$ctr{"mail"}++; $w++;
}
}
&writestats if ($w >= 100);
}
}
sub sendmailstats {
open STATS, "/usr/bin/mailstats|" or die "$0: mailstats error
/usr/bin/mailstats: $!";
while (chomp ($line = <STATS>)) {
if ($. > 2) {
($m, $line) = split(' ', $line, 2);
if ($m eq "T") {
($msgsfr, $bytesfr, $msgsto, $bytesto) = (split (/ +/, $line))[0,1,2,3];
chop $bytesfr; # remove "K"
chop $bytesto;
} elsif ($m eq "C") {
($connfr, $connto, $connrej) = split (/ +/, $line);
}
}
}
close STATS;
$ctr{"bytesfr"} = $bytesfr * 1024;
$ctr{"bytesto"} = $bytesto * 1024;
$ctr{"msgsfr"} = $msgsfr;
$ctr{"msgsto"} = $msgsto;
$ctr{"connfr"} = $connfr;
$ctr{"connto"} = $connto;
$mailq = qx:ls /var/spool/mqueue/q* 2>/dev/null | wc -l:;
$mailq =~ s/\s//g;
$ctr{"mailq"} = $mailq;
$w++;
}
sub terminate {
&writestats if ($w >= 1);
print $out;
exit 0;
}
$SIG{"INT"} = \&terminate;
$SIG{"QUIT"} = \&terminate;
$SIG{"TERM"} = \&terminate;
$SIG{"HUP"} = \&writestats;
# Parse arguments
while ($o = shift @ARGV) {
if ($o eq "-t") {
$fl = "t";
} elsif ($o eq "-v") {
$fl = "v";
} else {
print "Usage: $0 [-t|-v]\n";
print " Compute mail statistics and display the result (counters).\n";
print " -t display only titles, -v display only values\n";
exit 1;
}
}
# Read current counters
open IN, $stats or die "Cannot open $stats for reading: $!\n";
while (chomp($_ = <IN>)) {
/^ *(\S+): +(.+)$/;
$ctr{$1} = $2;
&saveout($1);
}
close IN;
&sendmailstats;
# Compute new totals
open IN, $in or die "Cannot open $in for reading: $!\n";
@stat = stat IN;
$ctr{"inode"} = @stat[1] unless (defined $ctr{"inode"});
$ctr{"position"} = 0 unless (defined $ctr{"position"});
if ($stat[1] != $ctr{"inode"}) {
close IN;
open IN, "$in.0" or die "Cannot open $in.0 for reading: $!\n";
&computestats;
close IN;
open IN, $in or die "Cannot open $in for reading: $!\n";
$ctr{"inode"} = @stat[1];
$ctr{"position"} = 0;
#$pos = 0;
&writestats;
}
&computestats;
close IN;
&terminate;
# End of script
-----------------------------------
I give no guarantee on this script... and I don't say it is the best ever
written but it works well
here.
HTH,
Pierre
_______________________________________________
Help us build a comprehensive ClamAV guide: visit http://wiki.clamav.net
http://www.clamav.net/support/ml