Perl contrib scripts
Russell Fulton
r.fulton at auckland.ac.nz
Wed Oct 11 20:21:13 EDT 2000
HI All,
With the imminent release of argus-2.0 I thought it would be a
good time to start polishing up some of my perl scripts for the contrib
directory. One reason I have not done this before is that most of my
scripts have lots of site dependent stuff scattered through them and
are thus not that 'portable'. I was forced to at least collect all the
site dependent bits of watcher (my scan detector) into one place when I
gave Neil a copy and this started me thinking about the "right" way to
do it.
Well this is what I have come up with:
Argus.pm defines a bunch of global variable that are likely to be used
by many scripts (things like your local domain, IP range etc. You can
also define sub packages for things specific to various scripts. This
becomes the configuration file for all argus scripts in the contrib
directory.
Another site dependency is how we layout our archives of argus data so
I have another module Argus::Archive.pm which currently has a single
function Get_file_list which takes either a start and finish date or a
time period (eg. today, yesterday, thisweek, lastweek etc) and returns a
list of files (in date order) to be feed to a client. Each site will
need to mung this routine to do the right thing with their directory
layout.
I think it might be useful to include some templates for unpack to aid
extracting data from various client output. (I have not done this yet).
Another possibility is a module that hides RA altogether
$input = $Argus::RA->new (Read=>$file, Opt=>$switches ) or die ...
while( $input->read ) {
}
read would read the pipe from ra and then unpack the record (exactly
how would depend on the switches supplied to ra). How best to return
results? via a list or global variables?
Lastly I have a very simple script that runs ra over a range of files
with user supplied filters as an example of the system in action. I'll
convert my watcher script to use the new scheme soon and post that when
I have it done.
I would appreciate some feedback on
a/ is this a good approach?
b/ if so then are there issues with the details of how I have done it.
c/ alernative approaches
I'm not wedded to any of this so please feel free to criticize ;-)
Russell
--------------------------------------------------------------------
Sample Argus.pm (for UoA ;-)
package Argus;
use vars qw ($Client_bin $RA $Local_IP_re $LocalTimeZone_re $Testing
$Local_domain_re $Def_Host $Def_Port $Archive_root $Error
@Errors);
$Testing = 0 unless defined $Testing;
$Client_bin = '/home/argus/bin'; # set by configure ??
$RA = "$Client_bin/ra";
$Local_IP_re = '^130\.216\.';
$LocalTimeZone_re = '\.nz$';
$Local_domain_re = 'auckland\.ac\.nz$';
$Def_Host = 'localhost';
$Def_Port = '561';
$Data_Root = '/home/argus/data';
sub Report { # stores errors in a stack, with the last in $Error
$Error = shift;
push( @Errors, $Error);
}
package Argus::Watcher; # config vars for particular scripts
use vars qw ($Def_ra_Filter %BUSY_MACHINES $Period $ReReport
$Local_Interest_Threshold $Remote_Interest_Threshold
$Packet_Save);
$Def_ra_Filter = '';
# local machines that talk to lots of others which need higher
reporting
# thresholds eg. network monitors web proxies, mail servers etc.
# The number is the modified reporting threshold.
%BUSY_MACHINES = (
"130.216.1.1" => 250, # net
"130.216.1.4" => 450, # mailhost
"130.216.191.4" => 360,
"130.216.1.6" => 400, # scream
"130.216.1.240" => 400,# surveyor
"130.216.191.46" => 550, # netacct
"130.216.191.26" => 350,
"130.216.35.100" => 600,#ec gateway
"130.216.191.53" => 200,#ec gateway
"130.216.35.201" => 250,#ec gateway
"130.216.34.10" => 250,
"130.216.193.45" => 700, # nix.tmk.auckland.ac
);
#Default reporting threshold etc.
$Period = $Argus::Testing ? 100 : 300; ## seconds -- reporting period
$ReReport = 3600; ## seconds - wait this long before sending more
# reports of continuing activity
# report when machine talks to more than this many port/addresses
# during $Period seconds
$LOCAL_INTEREST_THRESHOLD = $testing ? 10 : 100;
$REMOTE_INTEREST_THRESHOLD = $testing ? 20 : 40;
$Packet_Save = 20; ## Only save this many sample packets
-------------------------------------------------------------------------------
Argus/Archive.pm again specific to UoA
package Argus::Archive;
use strict;
use Argus;
use Date::Manip;
Date_Init("DateFormat = NONUS"); #change to US for mm/dd
# Takes two dates or a special period names and returns a list of
# argus archive files that cover the period
sub Get_File_List {
my ($first, $last ) = @_;
my @files;
my ( $sdate, $fdate);
my $today = ParseDate('today');
if( ! defined $first ) {
Argus::Report("No start date given");
return undef;
}
if ( $first eq 'thisweek' ){
$sdate = Date_GetPrev($today, 'Mon', 1);
$fdate = Date_GetNext($today, 'Mon', 0);
} elsif( $first eq 'thismonth' ){
$sdate = ParseDate('1st');
$fdate = ParseDate('today') ;
$fdate = Date_SetTime($fdate, '23:59:59');
} elsif( $first eq 'lastweek' ){
$fdate = Date_GetPrev($today, 'Mon', 1);
$sdate = Date_GetPrev($fdate, 'Mon', 0);
} elsif( $first eq 'lastmonth' ){
$fdate = ParseDate('1st');
$sdate = DateCalc($fdate, '- 1 month');
} else {
$sdate =ParseDate($first);
Argus::Report( "Invalid date '$first'") if ! $sdate;
if( defined $last ) {
$fdate =ParseDate($last);
Argus::Report( "Invalid finish date '$last'") if ! $fdate;
} else {
$fdate = $sdate;
}
}
for (my $date=Date_SetTime($sdate, '00:00:00');
$date le $fdate; $date=DateCalc($date, '+ 1 day')) {
my $name =UnixDate($date, "%Y.%m.%d" );
if( -d "$Argus::Data_Root/$name" ) { # it was a directory
if( opendir(DIR, "$Argus::Data_Root/$name") ) {
foreach my $f ( sort grep(/^argus.*\.gz$/,
readdir(DIR))){
push(@files, "$Argus::Data_Root/$name/$f");
}
closedir(DIR);
} else {
Argus::Report ("Failed to open ".
$Argus::Data_Root/$name:$!");
return undef;
}
}
}
return @files;
}
1;
------------------------------------------------------------------------
My look_for script modified to use the module files (I guess we all
have one of these ;-)
#!/usr/bin/perl -w
#
# usage look_for [<options>] files or directories....
#
use lib "/home/argus/bin"; # set by configure ????
use strict;
use Getopt::Std;
use Argus;
use Argus::Archive;
use vars qw($opt_f $opt_F $opt_s $opt_D $opt_o $opt_q $opt_P $opt_w
$opt_t);
getopts("D:s:f:o:F:qw:t:P:") || die "Invalid options found";
# D <directory>-- Directory where data is held
# s <date> -- Start date
# f <date> -- Finish date
# F <file> -- read filter from <file>
# o <options> -- options for ra (default -nc)
# P <file> -- function to post filter
# w <filename> -- Output to filename
# q -- quite mode
# t <timezone> -- print times relative to alternate timezone eg UTC
my $opts = defined $opt_o ? "-$opt_o" : '-znc';
$Argus::Data_Root = $opt_D if defined $opt_D;
my $filter = defined $opt_F ? "-F $opt_F" : join(' ', @ARGV);
if (defined $opt_w) {
open(OUT, ">$opt_w") || die "failed to open '$opt_w':$!";
} else {
open(OUT, ">-") || die "failed to open 'stdout':$!";
}
if( defined $opt_t ) {
$ENV{TZ} = $opt_t ;
}
$opt_s = 'yesterday' unless defined $opt_s;
my @files = Argus::Archive::Get_File_List($opt_s, $opt_f );
if( ! defined @files ) {
die "$Argus::Error";
}
foreach my $fn ( @files ) {
print "$fn\n" if ! defined $opt_q;
open(SW, "$Argus::RA -r $fn $opts $filter |" ) ||
die "can't open ra:$!";
while (<SW>) {
if( defined $opt_P ) {
next if post_filter($_);
}
print OUT;
}
}
More information about the argus
mailing list