#!/usr/bin/perl 

use Time::Local;
use File::stat;

#  Linux IPTables DShield Client. V 0.0.1
#
#    This script will extract relevant lines from the log file and
# send them to 'reports@dshield.org'.
#
#   IMPORTANT: CHANGE THE '$filter' below with a marker that can 
#              be found in all log lines you would like to submit.
#              e.g.: IN=eth0 or something like that.
#              you don't need this if you write your firewall logs
#              to a separate file. 
#
#    It should run from cron regularly to look for new entries. See
# 'parameters' for more details.
#
#    Important: Linux syslog files do not keep track of the year.
#               remember to rotate your logs at the end of the year.
#

$EXT_IP=`/sbin/ifconfig | head -2 | grep 'inet addr' | awk '{print \$2}' | sed -e 's/.*://'`;
#print "external IP =($EXT_IP)\n";
chomp $EXT_IP;
#print "external IP =($EXT_IP)\n";
#exit;

#print "before setting filter\n";

$filter="IN=eth0";    # replace with pattern that occurs in all iptables lines
$logfile="/var/log/messages";  # location of log file.

#print "filter = $filter\n";
#print "logfile = $logfile\n";


#
#  Parameters:
#

$userid="86579302";                 # replace with your userid if you have one.
#$email='root@localhost';               # replace with your e-mail address.
$email='lchialing@yahoo.com';               # replace with your e-mail address.
$to='reports@dshield.org';    # send log to this address. Change for testing. 
#$cc_flag=TRUE;
$cc_flag=0;
$tz="-05:00";                # setup your time zone here. Use offset from
                             # GMT. E.g: +01:00 for Central Europe,
                             #           -05:00 for Easter US.  

# Subject line. No need to change
$subject="FORMAT IPTABLES USERID $userid TZ $tz";
$local_log='/tmp/dshield.log';  # keep a local copy here for revie

#
# End of parameter. Skip through the section below for local abnomalities.
#

%months = (Jan=>0, Feb=>1, Mar=>2, Apr=>3, May=>4, Jun=>5, Jul=>6, Aug=>7, Sep=>8, Oct=>9, Nov=>10, Dec=>11);



$state="/var/tmp/dshield";   # file that is used to store timestamp of log file.

$rolllogfile="/var/log/messages.1";  # location of last log file.

#
# Nothing should need changing beyond this point.
#


# setup a halfway safe /tmp file

srand(time);
$tmp="/tmp/dshield".$$.rand(1000);
$tmp2="/tmp/dshield_cllee".$$.rand(1000);


#
#  the 'state' file contains the timestamp
# of the log file the last time the script ran.
#

$last_date=0;
if ( -e $state ) {
        $last_date = `cat $state`;
}

#
#  get the current mod date of the logfile
#

if ( -f $logfile ) {
    $stat=stat($logfile);
    $curr_date=$stat->ctime;
} else {
    die ("Can't find LogFile $logfile\n");
}


#
# if current date stamp older than last,
# either nothing written or something screwy - abort.
#

if ($curr_date <= $last_date) {
    die ("Nothing written to log file since last export. Check if the correct logfile is used ($logfile)\n"); 
}

#
# remove stale tmp files. This should never happen, as
# the temp file name is generated randomly

if (-s $tmp2) {
    system ("rm $tmp2");
}

#
# remove stale tmp files. This should never happen, as
# the temp file name is generated randomly

if (-s $tmp) {
    system ("rm $tmp");
}

#
#  create empty 600 file..
#  make sure it is still empty and 600 after we 
# created it. 

system ("touch $tmp; chmod 600 $tmp");
if (-s $tmp) {
    die "TMP file grew after creation.\n";
}
#
#  create empty 600 file..
#  make sure it is still empty and 600 after we 
# created it. 

system ("touch $tmp2; chmod 600 $tmp2");
if (-s $tmp2) {
    die "TMP2 file grew after creation.\n";
}

#
# check to see if logfile rolled since last run
# and parse if so.
#

$roll_date = 0;
$stat=stat($rolllogfile);
$roll_date=$stat->ctime;
if ($roll_date >= $last_date) {
    parselog ($rolllogfile, $last_date, $tmp);
}

#
# Parse current log file
#

parselog ($logfile, $last_date, $tmp);

# send the file. Only bother if there is something to
# report.

if ( -s $tmp) {
    open (MAIL,"| /usr/sbin/sendmail -t -oi");
    print MAIL "To: $to\n";
    print MAIL "From: $email\n";
    if ($cc_flag) {print MAIL "Cc: $email\n";}
    print MAIL "Subject: $subject\n\n";
    print MAIL `cat $tmp`;
    close MAIL;
    if ($local) {
        open (MAIL,"> $local");
        print MAIL "To: $to\n";
        print MAIL "From: $email\n";
        if ($cc_flag) {print MAIL "Cc: $email\n";}
        print MAIL "Subject: $subject\n\n";
        print MAIL `cat $tmp`;
        close MAIL;
    }
}

#
# Parse current log file - filter out NetBios and send to me
#

parselog_cllee ($logfile, $last_date, $tmp2);

# send the file. Only bother if there is something to
# report.

if ( -s $tmp2) {
    open (MAIL,"| /usr/sbin/sendmail -t -oi");
    print MAIL "To: $email\n";
    print MAIL "From: $email\n";
    #if ($cc_flag) {print MAIL "Cc: $email\n";}
    print MAIL "Subject: cllee $subject\n\n";
    print MAIL `cat $tmp2`;
    close MAIL;
    if ($local) {
        open (MAIL,"> $local");
        print MAIL "To: $email\n";
        print MAIL "From: $email\n";
        #if ($cc_flag) {print MAIL "Cc: $email\n";}
        print MAIL "Subject: cllee $subject\n\n";
        print MAIL `cat $tmp2`;
        close MAIL;
    }
}

#
# cleanup the temp file and write a new state file
#

system ("rm $tmp");
system ("rm $tmp2");
system ("echo $curr_date > $state");

sub parselog {
    local($logfile,$last_date,$tmpfile) = @_;

    (undef,undef,undef,undef,$cur_month,$year,undef) = localtime(time);
    $cur_month++;
    @lines = `grep "$filter" $logfile | grep IN=eth0 | grep -v SRC=$EXT_IP | grep -v SRC=151.191.1.10 | grep -v SRC=151.191.1.12 | grep -v SRC=151.191.175.7 | grep -v SPT=80`;
    open (LOGFILE, "<$logfile");
    open (TMPFILE, ">>$tmpfile");
    foreach $line (@lines) {
        $line =~  /(\w{3}) ([ \d]{2}) (\d{2}):(\d{2}):(\d{2}) /;
        $dateline = timelocal ($5, $4, $3, $2, $months{$1}, ($months{$1}>$cur_month) ? $year-1 : $year );
        if ($dateline >= $last_date) {
            print TMPFILE $line;
        }
    }
    close (TMPFILE);
    close (LOGFILE);
}

sub parselog_cllee {
    local($logfile,$last_date,$tmpfile) = @_;

    (undef,undef,undef,undef,$cur_month,$year,undef) = localtime(time);
    $cur_month++;
    @lines = `grep "$filter" $logfile | grep IN=eth0 | grep 'BAD SRC'`;
    open (LOGFILE, "<$logfile");
    open (TMPFILE, ">>$tmpfile");
    foreach $line (@lines) {
        $line =~  /(\w{3}) ([ \d]{2}) (\d{2}):(\d{2}):(\d{2}) /;
        $dateline = timelocal ($5, $4, $3, $2, $months{$1}, ($months{$1}>$cur_month) ? $year-1 : $year );
        if ($dateline >= $last_date) {
            print TMPFILE $line;
        }
    }
    close (TMPFILE);
    close (LOGFILE);
}


1