# TrafficCapture.pl # Starts a tcpdump capture when traffic is received on a specified local port # The tcpdump capture file is automatically tagged with a date/timestamp # When traffic ceases, the tcpdump capture is killed and traffic is looked for again...ad infinitum. # # Usage: # perl TrafficCapture.pl use IO::Socket; use IO::Select; $Timeout = 120; $WriteLogFile = 1; $MaxCaptureSize = 120000000; # max size of capture file, in bytes if (! ($^O =~ /[nN].[xX]/)) { die "\n\nThis script works only on Linux since Windows has flaky child process handling\n\n"; } if (@ARGV[0] eq "") { print "\nNo port specified.\n"; print "Usage: perl TrafficCapture.pl \n (where is the local port on which to listen)\n\n"; die; } else { $ListenOnPort = @ARGV[0]; } $ChildPid = -1; $ParentPid = $$; LogAndPrint(GetTime() . ": TrafficCapture.pl started with ParentPid=$ParentPid\n"); LogAndPrint(GetTime() . ": Listening on local port $ListenOnPort...\n"); $sock = IO::Socket::INET->new(LocalPort => $ListenOnPort, Proto => 'udp'); $readable_handles = new IO::Select(); $FirstPkt = 1; $readable_handles->add($sock); while (1) { $new_readable = IO::Select->select($readable_handles, undef, undef, $Timeout); if ($new_readable == 0) { if ($FirstPkt == 0) { if ($ChildPid != -1) { # make sure we don't kill PID = -1 $temp = GetTime() . ": No longer receiving packets on port $ListenOnPort, killing pid=$ChildPid\n"; LogAndPrint($temp); kill 9, $ChildPid; $ChildPid = -1; $FirstPkt = 1; } } } else { $sock->recv($rawdata,128); #this removes it from the select queue...resetting select if ($FirstPkt) { $FN_Capture = "TrafficCapture".GetTime().".dmp"; $SysCmd = "tcpdump -i eth1 -nN -C200 -w \"$FN_Capture\" \"udp port $ListenOnPort\""; $ChildPid = fork(); if ($$ == $ParentPid) { $temp = GetTime() . ": Observed traffic initiated on port $ListenOnPort, executing \"$SysCmd\" with pid=$ChildPid\n"; LogAndPrint($temp); } if ($$ != $ParentPid) { #child process exec $SysCmd; } $FirstPkt = 0; } ($FS_dev,$FS_ino,$FS_mode,$FS_nlink,$FS_uid,$FS_gid,$FS_rdev,$FS_size,$FS_atime,$FS_mtime,$FS_ctime,$FS_blksize,$FS_blocks) = stat($FN_Capture); if ($FS_size > $MaxCaptureSize) { if ($ChildPid != -1) { # make sure we don't kill PID = -1 $temp = GetTime() . ": Capture file $FN_Capture exceeded $MaxCaptureSize bytes, killing pid=$ChildPid\n"; LogAndPrint($temp); kill 9, $ChildPid; $ChildPid = -1; # if you want a new capture to start every time the MaxCaptureSize is exceeded, uncomment the line below #$FirstPkt = 1; } } } } sub LogAndPrint { print @_[0]; if ($WriteLogFile) { open (LOGFILE, ">>TrafficCapture.log") or die("Cannot open log file\n"); print LOGFILE @_[0]; close(LOGFILE); } } sub GetTime { ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); $year += 1900; $mon += 1; $temp = sprintf("%4d-%02d-%02d-%02d%02d%02dLT",$year,$mon,$mday,$hour,$min,$sec); return $temp }