#! /usr/bin/perl -w
use strict;
use Net::DNS;
use Email::Sender::Simple qw(sendmail);
use Email::Simple;
use Email::Simple::Creator;
if (($ARGV[0] !~ /(?=^.{1,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)/)){
print "usage: ./dnswatch.pl <domain> <watch timer> <notification email>\n",
"example: ./dnswatch.pl linuxwall.info 600 julien\@linuxwall.info (verify domain linuxwall.info every 10 minutes and notify julien\@linuxwall.info if needed)\n",
"\nif no watch timer is specified, the script will loop every 10 seconds undefinitely\n";
exit 1;
}
my $watch_timer = 10;
if(defined($ARGV[1])){
if ($ARGV[1] !~ /^\d+$/){
print "invalid timer value !\n";
exit 1;
}
$watch_timer = $ARGV[1];
print "Starting DNS Watch with $watch_timer seconds interval\n";
}
my $notification_email = "";
if(defined($ARGV[2])){
$notification_email = $ARGV[2];
print "Alarms and notifications will be send to $notification_email\n";
}
my $domain_name = $ARGV[0];
my %domain_ns;
my %domain_mx;
sub dns_alarm{
my @args = @_;
my $notification_message = "";
if($args[2] eq "added"){
$notification_message = "ALARM: entry $args[0] with ip $args[1] has been added to the domain\n";
}
elsif($args[2] eq "changed"){
$notification_message = "ALARM: entry $args[0] with ip $args[1] has been changed to $args[2]\n";
}
else{
print "unknown alarm\n";
return 1;
}
print $notification_message;
if($notification_email ne ""){
my $email = Email::Simple->create(
header => [
To => $notification_email,
From => $notification_email,
Subject => "DNSWATCH alarm for $domain_name",
],
body => $notification_message,
);
sendmail($email);
}
return 0;
}
my $res = Net::DNS::Resolver->new;
my $query = $res->query($domain_name, "NS");
if ($query) {
foreach my $fqdn_rr (grep { $_->type eq 'NS' } $query->answer) {
$query = $res->search($fqdn_rr->nsdname);
if ($query) {
foreach my $host_rr ($query->answer) {
next unless $host_rr->type eq "A";
print "NS server\t-> fqdn=",$fqdn_rr->nsdname, " ip=",$host_rr->address,"\n";
$domain_ns{$fqdn_rr->nsdname} = $host_rr->address;
}
} else {
warn "query failed: ", $res->errorstring, "\n";
}
}
}
else {
warn "query failed: ", $res->errorstring, "\n";
}
my $first_round = 1;
while(1){
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
print "\n----interation date: $mday/",$mon+1,"/",$year+1900," - $hour h $min m $sec s -----------\n";
foreach my $domain_ns (keys %domain_ns)
{
print "using $domain_ns as nameserver\n";
$res->nameservers($domain_ns);
my @mx = mx($res, $domain_name);
if (@mx) {
foreach my $fqdn_rr (@mx) {
$query = $res->search($fqdn_rr->exchange);
if ($query) {
foreach my $host_rr ($query->answer) {
next unless $host_rr->type eq "A";
print "MX server\t-> priority=",$fqdn_rr->preference, " fqdn=", $fqdn_rr->exchange, " ip=",$host_rr->address,"\n";
if(exists($domain_mx{$fqdn_rr->exchange})){
if($domain_mx{$fqdn_rr->exchange} ne $host_rr->address){
dns_alarm($fqdn_rr->exchange,$domain_mx{$fqdn_rr->exchange},$host_rr->address,"changed");
}
}
else{
unless($first_round == 1){
dns_alarm($fqdn_rr->exchange,$host_rr->address,"added");
}
else{
$domain_mx{$fqdn_rr->exchange} = $host_rr->address;
}
}
}
} else {
warn "query failed: ", $res->errorstring, "\n";
}
}
} else {
warn "Can't find MX records for $domain_name: ", $res->errorstring, "\n";
}
$first_round = 0;
}
sleep $watch_timer;
}