Script to monitor DNS logs
Below is a perl script written to monitor DNS log files for three events
- SERVFAIL Messages: If a zone's data is stale, you could see this type of error
- REFUSED Messages: Could refer to failed zone transfers
- Zone Transfers: Will match on successful zone transfers from our master dns server
The script runs daily via cron, after the daily rotating of dns log files.
The following variables/arguments/regex will need to be defined with real informaiton:
- Line 18: Location of logfile to parse
LInes 41 & 45: IP address of the Master DNS server
- Line 58: Location of output file to write information gathered from log
Lines 104 & 105, 107 & 108: Email recipients
- Lines 111, 112, 115, 118: smtp server, name of server sending email, sender of email and recipient that will show up in the To: field.
Perl Script
1 #!/usr/bin/perl -w 2 3 ## 4 ## May 27, 2008 5 ## [email protected] 6 ## 7 8 use strict; 9 use Net::SMTP; 10 use Date::Simple ('date', 'today'); 11 use vars qw(@lines @lines_email $file $file2 $a $b $c $i @mesg1 @mesg2 @mesg3 $index $size $size1 $size2 $size3 $smtp $body $today $date $recipient1 $recipient2); 12 13 #Retrieve Current Date for use in email subject 14 my $today = today(); 15 $date = (('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')[$today->day_of_week]); 16 17 ##Define and open log file 18 $file = "<LOGFILE_LOCATION>"; 19 open (FH, $file) or die "Error cannot open file: $!\n"; 20 21 ##Initialize variables 22 @lines = <FH>; 23 $size1 = @lines; 24 $a = 0; 25 $b = 0; 26 $c = 0; 27 my @mesg1= (); 28 my @mesg2= (); 29 my @mesg3= (); 30 31 ##Parse log file and extract lines which match one of three conditions 32 foreach $index (@lines) { 33 if ( $index =~ /(SERVFAIL)/ ) { 34 $mesg1[$a] = " SERVFAIL detected:\t$index\n"; 35 $a++; 36 } 37 if ( $index =~ /(REFUSED)/ ) { 38 $mesg2[$b] = " REFUSED from master detected:\t$index\n"; 39 $b++; 40 } 41 if ( ($index =~ /end of transfer/) && ($index =~ /MASTER_DNS/) ) { 42 $mesg3[$c] = " Zone transfer detected:\t$index\n"; 43 $c++; 44 } 45 elsif ( ($index =~ /failed while receiving responses/) && ($index =~ /MASTER_DNS/) ) { 46 $mesg3[$c] = " Zone XFER failed:\t$index\n"; 47 $c++; 48 } 49 } 50 ## Finished reading in logs, close file 51 close FH; 52 reset $size1; 53 $size1 = @mesg1; 54 $size2 = @mesg2; 55 $size3 = @mesg3; 56 57 ##Make sure that a previous run of this script txt file is deleted before we start writing to it 58 $file2 = "<LOGFILE_LOCATION>"; 59 unlink($file2); 60 ##Open File which we will write the body of the email to 61 open (writeEmail, '>>' . $file2) or die "Error cannot open file: $!\n"; 62 ##Print Heading for servfail, then messages. 63 print writeEmail "There were $size1 SERVFAIL messages:\n"; 64 $i = 1; 65 if ( $size1 != 0 ) { 66 for $index (@mesg1) { 67 print writeEmail $i . ". " . $index; 68 $i++; 69 } 70 } else { 71 print writeEmail "No SERVFAIL matches found\n"; 72 } 73 ##Print Heading for refused, then messages. 74 print writeEmail "\nThere were $size2 REFUSED messages:\n"; 75 $i = 1; 76 if ( $size2 != 0 ) { 77 for $index (@mesg2) { 78 print writeEmail $i . ". " . $index; 79 $i++; 80 } 81 } else { 82 print writeEmail "No REFUSED matches found"; 83 } 84 ##Print Heading for xfer, then messages. 85 print writeEmail "\nThere were $size3 XFER messages:\n"; 86 $i = 1; 87 if ( $size3 != 0 ) { 88 for $index (@mesg3) { 89 print writeEmail $i . ". " . $index; 90 $i++; 91 } 92 } else { 93 print writeEmail "No XFER matches found\n"; 94 } 95 ##Grab the number of lines written before file is closed 96 @lines_email = <writeEmail>; 97 $size = @lines_email; 98 print "$size\n"; 99 ##Close mesage file for writing 100 close (writeEmail); 101 #Open email message for reading, determine to whom message should be sent 102 open(emailMsg, $file2) or die "Cannot open email.txt for reading"; 103 if ($size == 0 ) { 104 $recipient1 = "SOMEONE\@SOMEWHERE.edu"; 105 $recipient2 = "SOMEONE\@SOMEWHERE.edu"; 106 } else { 107 $recipient1 = "SOMEONE\@SOMEWHERE.edu"; 108 $recipient2 = "SOMEONE\@SOMEWHERE.edu"; 109 } 110 ##Send Email if # of lines is not greater than 250 111 $smtp = Net::SMTP->new('YOURSMTP.SOMEWHERE.EDU', 112 Hello => 'YOUSERVER.SOMEWHERE.EDU', 113 Timeout => 30, 114 Debug => 1,) or die "Error creating SMTP obj: $!\n"; 115 $smtp->mail('[email protected]'); 116 $smtp->to($recipient1, $recipient2); 117 $smtp->data(); 118 $smtp->datasend("To: FROM\n"); 119 $smtp->datasend("Subject: DNS Report for $date\n"); 120 $smtp->datasend("\n"); 121 if ($size > 310) { 122 $smtp->datasend("Too many lines returned, see dns logs immediately"); 123 } else { 124 $smtp->datasend(<emailMsg>); 125 } 126 $smtp->dataend(); 127 $smtp->quit; 128 129 #Close email message, done reading 130 close (emailMsg);