DNS Backup Script

I would like to start this post with an admission of guilt.

Hello, my name is swarleyman and I’m an arstechnicaholic.

Please don’t judge me.

Anyways, I was reading it a few days ago and read an article about how Anonymous plans to dos worldwide DNS. All the politics of this topic aside, it got me thinking. We are so incredibly reliant on DNS that if it went down, it could have catastrophic effects on society. Okay, so not being able to access your Facebook page for a few days might be a good thing. What about paying your bills (though if your bill pay system can’t access their payment processing service, it doesn’t really matter anyways)? With that, I decided to research a good way to back up DNS.

After some searching I was, of course, disappointed. There is apparently no way to back up DNS. You would think that there should be some way to make a third-party copy, especially since it’s such a vital service that’s supposed to be relatively open. Either way, we still have a few tools to work with to make at least a semi-thorough backup.

The tools I chose to use were perl and nslookup. Unless I’m missing something, I think nslookup is really the only good way to get relatively complete DNS data. I know you can dig stuff, but i’m not looking to back up people’s cname, aaa, a, srv, etc. records (perhaps I’ll come back and write up a script for that too). With that, to run this script you need a 'nix system with perl and nslookup installed (in the dnsutils package).

What this script does is run nslookup on every host in a text file (for example ./dnsbak.pl hostlist.txt), parse the text and format it in a hosts file format. All you should need to do is take the output from this script and append it to your hosts file and you should be back up and running.

Here’s teh codez!

#!/usr/bin/perl -w
sub main () {
  open hosts_list, $ARGV[0] or die("\nNo file specified or file does not exist\n");
  # ONE HOST PER LINE
  my @hosts=<hosts_list>;
  close(hosts_list);
  for (my $i=0; $i<scalar(@hosts); $i++) {
    my $nslookup=`nslookup $hosts[$i]`;
    my $site = new Site($nslookup);
    $site->parse();
    sleep(1);
  }
}
main();
print "\n\n";

package Site;
sub new {
  my $class = shift;
  my $self = { _nslookupData=>shift };
  bless $self, $class;
  return $self;
}

sub parse() {
  my ( $self )=@_;
  my $data=$self->{_nslookupData};
  my @data=split("\n", $data);
  my @addresses;
  my $server;
  for (my $i=0; $i<scalar(@data); $i++) {
    if ($i>=3) {
      # MATCH THE HOSTNAME
      if ($data[$i]=~/Name:\s(\w+\.\w+)/) { $server=$1; }
      # MATCH THE IP ADDRESSES
      if ($data[$i]=~/Address:\s{1,3}(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) { push(@addresses, $1); }
    }
  }
  if (scalar(@data) > 4) {
    print join("\t".$server."\n", @addresses);
    print "\t".$server;
    print "\n\n";
  }
}

Please leave some comments on my script if you have any. I still consider myself quite the perl noob as I am completely self taught and don’t really have all of the super pro +1 up perl one-liner guru experience that you perl veterans can has. I look forward to hearing some feedback on my seemingly too long and verbose script.

Ensign, engage.

Category:Backups Category:Perl Category:Scripting