Bowie Bailey wrote:

Jason Gerfen wrote:
Bowie Bailey wrote:
Jason Gerfen wrote:
Bowie Bailey wrote:
Jason Gerfen wrote:
I am looking to do something which I am not sure perl can do.
I would like to be able to issue a system command ex. tail -f
/file and loop over that command while sorting the output. Is this possible? And if so could I see an example?
 open(LOG, "tail -f /var/log/messages |");
 while (<LOG>) {
     if (/something important/) {
         print "Found something...\n";
     }
 }
 close LOG; # Never get here, but for completeness...

I'm not sure what you mean by sorting the output.  Since there
is continuous input, there will be continuous output.  You
could sort and display aggregated output at intervals rather
than having a real-time output stream.
I have a few programs that do this exact thing.  They tail the log
file and page or email me when they find something.  The only
problem I have had is that it seems like the pipe will eventually
break if you leave it running for long enough.
Well I am 'attempting' to write a simple perl daemon that will listen
or 'tail -f /var/log/messages' for any iptables log which matches a
'DROP'ed packet.

That's simple enough.  Just follow my code above.

Upon seeing a matching condition it will fork a new process and then
begin sorting the data and send me alerts etc.

Fork a new process?  Why?

It sounds like you just want to watch for DROPs and send alerts.  Why
the complication?

Does that help explain it a bit more?  I can include code if
needed.

Code might help.  Some sample output would help more.  What exactly
are you expecting this program to send you?

I am going to include code, but for the record I am not a pro perl guru nor is my code the most effecient. This is what I am hoping to accomplish:

Run this perl script in a 'daemon' mode to look for dropped packets from the iptables, count 'x' amount of attempts per IP/host then depending on a config file or optional arguments the script will do a WHOIS on the offender and simply log it to a new file.

Here is the code thus far:

#!/usr/bin/perl

use strict;
use Getopt::Long;
use POSIX qw( strftime );
use Fcntl ':flock';
use Net::Whois::ARIN;
use Carp;
use IO::Socket;

my( @config,
   @data,
   @hosts,
   @drop,
   @date,
   @in,
   @out,
   @src,
   @dst,
   @prot,
   @spt,
   @dpt,
   @temp ) = '';

GetOptions( "config=s"      => \my $config,
       "firewall=s"    => \my $firewall,
           "report=s"      => \my $report,
           "thresh-hold=n" => \my $thresh,
           "whois=s"       => \my $whois,
       "ports=s"       => \my $ports,
           "email=s"       => \my $email,
       "daemon=s"      => \my $daemon );

if( !defined( $config ) ) {
   $config = "smnad.conf";
}
if( !defined( $thresh ) ) {
   $thresh = 3;
}
if( !defined( $whois ) ) {
   $whois = "FALSE";
}
if( !defined( $audit ) ) {
   $audit = "FALSE";
}
if( !defined( $config ) ) {
   $config = "portdefs";
}
if( !defined( $daemon ) ) {
   $daemon = "FALSE";
}
if( ( defined( $firewall ) ) || ( defined( $config ) ) ) {
   print "=============================================================\n";
   &Main;
   print "=============================================================\n";
} else {
   &ShowSyntax;
}

sub GetDate
{
   my $date = strftime( '%b %e', localtime() );
   return $date;
}

sub ChkString( $string )
{
   my $string = shift;
   if( $string =~ /(\w+)/i ) {
       return 0;
   } else {
       return 1;
   }
}

sub ChkFile
{
   my $file = shift;
   if( -e $file ) {
       if( -w $file ) {
           return 0;
       } else {
           return 1;
       }
   } else {
       return 0;
   }
}

sub ReadConfig
{
   my $config = shift; my $ret = 1;
   if( ChkFile( $config ) == 0 ) {
   open( FILE, $config ) || print "SMNAD: Could not open '$config' file\n";
   flock( FILE, LOCK_EX );
   while( my $data = <FILE> ) {
       if( $data =! /#/i ) {
       push( @temp, $data );
       }
   }
   flock( INFILE, LOCK_UN );
   close( INFILE );
   $ret = 0;
   } else {
   $ret = 1;
   }
   return $ret;
}

sub ParseConfig
{
   my $ret = 1; my @tmp;
   for( my $x = 0; $x < $#temp; $x++ ) {
   if( $temp[$x] =! /#/i ) {
       push( @config, chomp( $temp[$x] ) );
   }
   }
   for( my $x = 0; $x < $#temp; $x++ ) {
   @tmp = split( /: /, $config[$x] );
   $ret = 0;
   }
   return $ret;
}

sub ReadFirewall
{
   my $firewall = shift; my $ret = 1;
   if( ChkFile( $firewall ) == 0 ) {
   if( $daemon eq "TRUE" ) {
open( FILE, "tail -f $firewall |" ) || print "SMNAD: Could not open '$firewall' file\n";
       while( my $data = <FILE> ) {
       if( $data ne "" ) {
           chomp( $data );
           push( @data, $data );
           $ret = 0;
       }
       }
   } else {
open( FILE, $firewall ) || print "SMNAD: Could not open '$firewall' file\n";
       while( my $data = <FILE> ) {
       if( $data ne "" ) {
           chomp( $data );
           push( @data, $data );
           $ret = 0;
       }
       }
   }
   } else {
   $ret = 1;
   }
   return $ret;
}

sub SortData
{
   my $ret = 0;
   my $date = &GetDate;
   for( my $x = 0; $x < $#data; $x++ ) {
   if( ( $data[$x] =~ /$date/i ) && ( $data[$x] =~ /DROP/i ) ) {
if( $data[$x] =~ /(($date\s\d+\:\d+\:\d+).*IN=([eth]+[\d+]| ).*OUT=([eth]+[\d+]| ).*SRC=([\d+]{1,3}\.[\d+]{1,3}\.[\d+]{1,3}\.[\d+]{1,3}).*DST=([\d+]{1,3}\.[\d+]{1,3}\.[\d+]{1,3}\.[\d+]{1,3}).*PROTO=(UDP|TCP).*SPT=(\d+).*DPT=(\d+).*)/i ) {
               if( $9 ne "53" ) {
                   push( @drop, $1 );
                   push( @date, $2 );
                   push( @in,   $3 );
                   push( @out,  $4 );
                   push( @src,  $5 );
                   push( @dst,  $6 );
                   push( @prot, $7 );
                   push( @spt,  $8 );
                   push( @dpt,  $9 );
       }
       }
   }
   }
   return $ret;
}

sub Main
{
   if( &ReadConfig( $config ) == 0 ) {
   if( &ParseConfig == 0 ) {
       if( &ReadFirewall( $firewall ) == 0 ) {
       if( &SortData == 0 ) {
# for( my $x = 0; $x < $#drop; $x++ ) {
#            print $drop[$x] . "\n";
#            }
       } else {
print "SMNAD: Error occured while sorting data from '$firewall'.\n";
       }
       } else {
       print "SMNAD: Error opening firewall logs from '$firewall'.\n";
       }
   } else {
       print "SMNAD: Error sorting configuration data from '$config'.\n";
   }
   } else {
   print "SMNAD: Error opening config file '$config'.\n";
   }

}

sub ShowSyntax
{
   print <<EOF;

Usage: ./SMNAD --config=[path/to/config] Specify an alternate config file

--firewall=[path/to/logfile] Specify the logfile path and filename

--report=[path/to/output/file] Specify the report file to log results to

--thresh-hold=[n](def. 3) Specify the threshold of attempts per IP to be obtained from firewall log

--whois=[TRUE|FALSE] Perform a WHOIS lookup on offending host(s)

[EMAIL PROTECTED] Send the resulting output from the resulting report to offending host(s) ISP

--daemon=[TRUE|FALSE] Run this application in DAEMON mode

----------------------------------------------------------------------------
EOF
exit;
}

--
Jason Gerfen

"When asked what love is:
Love is the Jager talking."
~Craig Baldo

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to