(2) checking dns records from named.conf (incl script)

Evren Yurtesen yurtesen at ispro.net.tr
Tue Jul 22 01:05:49 PDT 2003


OK So I finished working on it :) I think you will find this script very
useful. Now it opens the named.conf file and checks all the domains if
they show your name servers or not.

Any comments or suggestions?

I still wonder how you manage the domain files of 350000 domains?

Evren

On Mon, 21 Jul 2003, Peter McGarvey wrote:

> * Evren Yurtesen <yurtesen at ispro.net.tr> [2003-07-21 14:57:35 BST]:
> > I have about 1000 domain names in my named.conf file.
> > I wonder if it would be possible to check the validity of these domains
> > or even if they are pointing to my name server or not easily...
> > Is there a ready script or something somebody knows here?
> >
>
> Well, I'm trying to combine the DNS platforms of 4 different companies
> onto a single standard platform.  I've got over 350,000 domains....  all
> of which need redelegating.  And just to make life fun these 4 different
> platforms have all been left to rot for years.
>
> None of the tools I've found have provided me with any of the
> information I need to speed up the process.  So I've resorted to using a
> variety of tools, and writing my own.
>
> For checking the actual zonefiles, I tend to use named-checkzone which
> is part of the bind distribution - but not part of the BSD install
> unfortunately.
>
> As for my scripts...  well they are rather nasty :-(
>
> But I've attached a re-hacked hack of a hack script of mine that may be
> useful.
>
>     cat domainlist | perl auths.pl
>
>
>
> --
> TTFN, FNORD
>
> Peter McGarvey
> Freelance FreeBSD Hacker
> (will work for bandwidth)
>
-------------- next part --------------
#!/usr/bin/perl

#   
#
# Creation Date: 21st July 2003
#
#       Author:
#       Peter P. McGarvey <xaphod at techie.com>
#       
#       Additional Code:
#       Evren Yurtesen <yurtesen at ispro.net.tr>
#
# VERSION HISTORY                            
#                
#       format x.y.z
#               - x = Major version number
#               - y = Minior version number           
#               - z = Burst number                    
#                       I work in bursts.  Weekend here, couple of hours a night
#                       there, then a night (a week etc.) off to think.  The
#                       `burst number' helps me keep track of different versions
#                       methinks CVS would be a good idea one day.
#                                                     
#    0.0.1  2003-07-21  - Peter P. McGarvey <xaphod at techie.com>
#			  * A NASTY hack of a perl script.
#    0.1.1  2003-07-22  - Evren Yurtesen <yurtesen at ispro.net.tr>
#                         * Added named.conf file parsing
#                         * Added automatical nameserver checking
#                                                     
use vars qw($VERSION);                                
$VERSION = '0.1.1';                                   
#                                                     
# =============================================================================

#location of named.conf file
$named_conf="/etc/namedb/named.conf";

#the name servers you expect to see
@name_servers=('ns1.ispro.net','ns2.ispro.net','dns1.ispro.net.tr','dns2.ispro.net.tr');

#the min number name servers must be set in domain correctly
$name_server_num=2;

#debugging level (the higher, the more text!)
#0 only shows errors
#10 shows if domain is OK too
#20 shows name servers too
#30 shows everything
$debug=0;

# =============================================================================
# Starting the Code


use Net::DNS;         
                     

my $timeout=0;

my @domainlist = &get_domain_list;

foreach my $zone (&get_domain_list) {
#while(my $zone = <domainlist>) {
  $error=0;
  $rightdns=0;

  #find parent zone
  my ($parent_zone) = $zone =~ /^[^\.]*\.(.*)/;

  #get auth primary
  my $parent_auth_primary = &get_auth_primary($parent_zone, $timeout);

  #get name server list
  if ($parent_auth_primary != -1) {
    @auth_servers = &get_ns_list($zone, $parent_auth_primary, $timeout);
  } else {
    $error=1;
  }

  #if there are no ns servers then error  
  if (scalar(@auth_servers) == 0) {
    $error=1;
  }
  foreach my $ns (@auth_servers) {
    chop($ns);
    foreach my $nserver (@name_servers) {
      if(lc($nserver) eq lc($ns)) {
        $rightdns+=1;
      }
    }
  }
  if ( $rightdns < $name_server_num) {
    $error=1;
  }

  #print our findings
  if ($debug >= 10 && $error == 0) {
    print ("\n# zone\tOK\t\t\t: $zone\n");
  }
  if ($error != 0) {
    print ("\n# zone\t!!! ERROR !!!\t\t: $zone\n");
  }
  if ($debug >= 30) {
    print "# parent zone\t\t\t: $parent_zone\n";
    if ($parent_auth_primary != -1) { 
      print "# parent auth primary is\t: $parent_auth_primary\n";
    }
  }
  if ($parent_auth_primary == -1) {
    print "# error\t\t\t\t\t: DEAD ZONE - ABORT\n";
  }
  if ($debug >= 20 && ! ($rightdns < $name_server_num) && (scalar(@auth_servers) != 0) && $parent_auth_primary != -1) {
    $num=0;
    foreach my $ns (@auth_servers) {
      $num+=1;
      print ("# nameserver $num\t\t\t: $ns\n");
    }
  }
  if ((scalar(@auth_servers)) == 0 && $parent_auth_primary != -1) { 
    print ("# error\t\t\t\t: NO AUTH SERVERS - DEAD ZONE\n");
  } elsif ( $rightdns < $name_server_num && $parent_auth_primary != -1) {
    print ("# error\t\t\t\t: NAME SERVERS SET INCORRECTLY\n");
    $num=0;
    foreach my $ns (@auth_servers) {
      $num+=1;
      print ("# nameserver $num\t\t\t: $ns\n");
    }
  } 
}

# =============================================================================
# End of the Code	- Start of the Sub-Functions
# &get_domain_list	- Returns the list of domains from named.conf.file
# &get_auth_primary	- Takes the name of a zone               
#			  Return the MNAME field from the SOA
# &get_ns_list		- Returns the list of NS records reported by that server

# =============================================================================
# Returns the list of domains from named.conf file
sub get_domain_list {
  open(NAMED_CONF,"< $named_conf") or die "Can not open $named_conf";
  #set some variables to 0
  $comment_block_starting=0;
  $comment_block_started=0;
  #make a list of domains
  while($line=<NAMED_CONF>) {
    #find if there is double backslash and use only left of it
    #we must put newline
    if($line =~ /\/\//) {
      $line=(split /\/\//,$line)[0]."\n";
    }
    #find if there is both /* my text */ in $line and use only outside 
    if ($line =~ /\/\*/ && $line =~ /\*\//) {
       @values1=split(/\/\*/,$line);
       @values2=split(/\*\//,$line);
       $line=$values1[0].$values2[1];
    } else { #find if there is only one of them?
      #if there is only /* take left side and wait until finding */
      if($line =~ /\/\*/) {
        $line=(split /\/\*/,$line)[0];
        #count the occurances in case if they are nested
        $comment_block_starting+=1;
      }
      #if there is only */ then stop waiting and take right side
      if($line =~ /\*\//) {
        $line=(split /\*\//,$line)[1];
        if(($comment_block_starting-=1) == 0) {
          $comment_block_started=0;
        }
      }
    }
    if (($comment_block_started=$comment_block_starting) == 0) {
      if($line =~ /zone.+\".+\"/ && ! ($line =~ /zone.+\"."/ || $line =~ /zone.+\".*ARPA\"/i)) {
        $line=(split /\"/,$line)[1];
        #cut out left and right spaces just to be sure
        $line =~ s/^\s+|\s+$//g;
        push(@domainlist,$line);
      }
    }
  }
  close(NAMED_CONF);
  return sort @domainlist;
}

# =============================================================================
# Takes the name of a zone
# Return the MNAME field from the SOA
sub get_auth_primary {
    my $zone = shift;
    my $tcp_timeout = shift;
    
    my $res = new Net::DNS::Resolver;
    my $packet = new Net::DNS::Packet($zone, "SOA", "IN");
        
    $res->tcp_timeout($tcp_timeout) if $tcp_timeout;

    my $req = $res->send($packet);

    return -1
        unless defined($req);
    return -1
        unless ( ($req->header->ancount >= 1)
              && (($req->answer)[0]->type eq "SOA") );
    return ($req->answer)[0]->mname . ".";
            # Return the FQDN
}

# =============================================================================
# Returns the list of NS records reported by that server
sub get_ns_list {
    my $zone = shift;            
    my $server = shift;
    my $tcp_timeout = shift;
 
    my @ns_list;
                          
    my $res = new Net::DNS::Resolver;
         
    $res->tcp_timeout($tcp_timeout) if $tcp_timeout;
       
    #die "FAIL: NS has no address (" . $res->errorstring . ")"                 
    return @ns_list       
         unless $res->nameservers($server);

    my $req = $res->query($zone, "NS");
    
    #die "WARN: NS query results were bad (" . $res->errorstring . ")"
    return @ns_list                  
           unless ( defined($req)
                 && ($req->header->ancount > 0) );
    
    foreach my $rr_ns ($req->answer) {
        push @ns_list, $rr_ns->nsdname . "."; #FQDN!
    }
    return sort @ns_list;
}


More information about the freebsd-isp mailing list