#!/bin/perl
#tcpdump script which detects network activity
#Courtesy of Programmaton, Gestion et Consultation, Informatique, INC.
#http://www.pgci.ca 
#Copyright (C) 1998 gilbert@pgci.ca

#This program 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 program 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 this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  
use Socket;
use Sys::Syslog;

# modify these for your particular network

@ex = (53,80,113);		
$net = "207.253.13.5";			

$line="";
$dup="127.0.0.1";
while (@ex) {
 $port = shift @ex;
 # ignore packets to defined ports and tack on the line
 $line="$line and not port $port";
}

# all icmp packets: icmp
# all udp packets: udp
# TCP packets with no ACK: tcp[13]&16!=16
# fragmented IP packets: ip[6:2]&16383!=0
# IP packets with options: ip[0]!=69
# packets with X.X.X.255 destination: ip[19]=255
# packets with X.X.X.0 destination: ip[19]=255

$tcpdump="tcpdump -n -q -l icmp or udp or 'tcp[13]&16!=16' or 'ip[6:2]&16383!=0' or 'ip[0]!=69' or 'ip[19]=255' or 'ip[19]=0' and src net not $net $line";

open (TCPDUMP, "$tcpdump |") || die "couldn't execute tcpdump: $!\n";
	while ($dumpline = <TCPDUMP>) {
	($time, $src, $junk, $dest, $proto, $junk, $junk, $flag) = split (/ /, $dumpline);
	($gmt,$micro) = split(/\./,$time);
        $proto =~ s/://g;
		if($proto eq "icmp") {
		($a, $b, $c, $d) = split (/\./, $src);
                }
		if(($proto eq "tcp") || ($proto eq "udp")) {
		($a, $b, $c, $d, $srcport) = split (/\./, $src);
                }
 	@ip_src = ($a,$b,$c,$d);
 	$hostname = pack("C4",@ip_src);
	$srcname = gethostbyaddr($hostname, &AF_INET);
	$ipsrc = join '.',$a,$b,$c,$d;
		if ($srcname eq "") {
		$srcname = $ipsrc;
 		}
 	$dest =~ s/://g;
		if($proto eq "icmp") {
                ($e, $f, $g, $h) = split (/\./, $dest);
                }
                if(($proto eq "tcp") || ($proto eq "udp")) {
                ($e, $f, $g, $h, $dstport) = split (/\./, $dest);
                }
 	@ip_dst = ($e,$f,$g,$h);
	$destname = pack("C4",@ip_dst);
 	$dstname = gethostbyaddr($destname, &AF_INET);
 	$destip = join '.',$e,$f,$g,$h;                           
 		if ($dstname eq "") {
 		$dstname = $destip;
 		}
        #we are using 1 second flood buffers
 	$current = join  '.',$gmt,$srcname,$dstname,$dstport;

 	#we are logging to local0.notice, so don't forget to add it to syslog.conf
 	#local0.notice					/var/adm/synlog

        #if the packet is for our $net, and has not been seen in the past second with the same src,dst and port.
 	if ((index($destip, $net,0) >= 0) && (index($current,$dup)<0)){
         	if(($proto eq "tcp") || ($proto eq "udp")) {
		#remove the cons keyword if you do not want it logged to the console
 		openlog("syn.pl", "cons,pid","local0");
 		syslog("notice","%s:%s to %s:%s, %s\n", $srcname,$srcport,$dstname,$dstport,$proto); 
 		closelog();
                }
		if($proto eq "icmp") {
                openlog("syn.pl", "cons,pid","local0");
                syslog("notice","%s to %s, %s\n", $srcname,$dstname,$proto);
                closelog();
                $dstport = 0;
                }
 	$old_srcname = $srcname;
 	$old_dstname = $dstname;
 	$old_dstport = $dstport;
 	$dup = join '.',$gmt,$old_srcname,$old_dstname,$old_dstport;
	}
}
