AAAA tale of two DNS

Since getting IPv6 up and running, I’ve been trying to figure out a way to map domain names to hosts no matter if they have statically assigned addresses or dhcp/radv generated ones. Additionally, I didn’t want to purchase a new domain. Instead I opted to create a new subdomain and delegated authority to my home IPv6 router’s name server.

In my first attempt, I was using a public FQDN. This presented a problem when using BIND’s allow-update as the private IPv4 range was now public and doesn’t help when trying to access my home computers. After some digging I found update-policy, but this required that each host made use of DNSSEC/TSIG/SIG…something I couldn’t guarantee on my network…yet. So it was back to allow-update.

A couple days later after some further thought, I settled on using a .local domain and via a script, copy the AAAA records to a public domain. This solution gives me easy access to my servers, without exposing the private IPv4 addresses. Even better, the script can be extended to include additional records or rules. For instance, don’t want to map android phones? Cisco switches? Cross reference the IPs to macs and filter away.

Zone config

//public
zone "home.example.com" {
	type master;
	file "/var/lib/bind/master/home.example.com.conf";
	//Only allow the updates from the local machine.
	allow-update { localhost; };
	//Only allow the axfr from the local machine.
	allow-transfer { localhost; };
};

//private
zone "home.example.local" {
	type master;
	file "/var/lib/bind/master/home.example.local.conf";
	//Allow local network hosts with static addresses to update the zone.
	allow-update { LocalIPv6/64; LocalIPv4/24; localhost; };
	//Only allow the axfr from the local machine.
	allow-transfer { localhost; };
};

The actual zone files are your regular zone files, nothing special.

Script

The script to update the public zone with AAAA records in the private. This is a cron job that only runs every hour as I’m not motivated enough at the moment to create higher res crontab.

#!/usr/bin/php
<?php
//get the aaaa records that have been registered with the local domain...minus the ns records.
$c = "dig @::1 home.example.local. axfr | grep AAAA | grep -v ns.home.example.local";
$out = array();
exec($c, $out);
$hosts = array();

//build array with hostnames for keys pointing to an array of associated ipv6 addresses.
foreach($out as $v) {
	$hn = substr($v,0,strpos($v,'.'));
	if(!isset($hosts[$hn])) {
		$hosts[$hn] = array();
	}
	$ipv6 = preg_split("/( |\t){1,}/", $v);
	$ipv6 = $ipv6[count($ipv6)-1];
	$hosts[$hn][] = $ipv6;
}

//Now take that array and pump it into nsupdate.
foreach($hosts as $k => $v) {
	$cmds = array("echo server ::1", "echo zone home.example.com", "echo update delete {$k}.home.example.com. AAAA");

	foreach($v as $ipv6) {
		$cmds[] = "echo update add {$k}.home.example.com. 86400 AAAA {$ipv6}";
	}
	$cmds[] = "echo send";
	$cmd = implode("\r\n", $cmds);
	exec("(". $cmd . ") | nsupdate", $out2);
	//var_dump("(". $cmd . ") | nsupdate");
	//var_dump(implode("\r\n", $out2));
}
?>

SnojNS 0.2: Still has a lame name

After many an hour pouring over the code and running tests galore, I think I’ve resolved some of the major issues from version 0.1. Like how it would just randomly crash when the forward lookup hosts decided they had had enough. Now it’ll recover from it and chug along.

There is now some simple compression. So now instead of having 6 “google.com” entires, we now have 1 with references to that first occurrence. Down the road, I plan on adding better compression so that parts of domains can be compressed. For instance “someSubdomain.josherickson.org” becomes “someSubdomain.{reference to first josherickson.org}”.

Commit comments:

fixed: non-coded types returned empty from outside sources.
fixed: crash when socket was interupted.
added: m attribute to tags. <a m="somehost" ip="1.1.1.1" />
added: beginning dns compression...I think. at least it appears to work.
notes: improved xml lookups. now can easily add xpath based lookups.
notes+: might need to improve this further to allow other filter types.
notes: rm attributes will likely wait until xpath fn:matches function is available.

Issues:

I’ve noticed while using HE’s IPv6 Tunnel Broker service, that I can’t surf IPv6 sites while using snojns. Not sure why this is, but I wonder if there needs to be an IPv6 socket listener as well.

Download:

If you’re smart enough to run this, you’ll know which you’ll want to get.

snojns 0.2.0: Release, Debug, Source.

Its a mnemonic kind of thing, a dns kind of thing

Hosts files are great, you can specify any host to IP combination, overriding anything.

But what about other types of records? Hosts files can’t do service, text, pointer records, etc? So what to do if you want to test these record types? You could setup your own DNS server, create a new zone, add the records to test, while mail, chat, and other services fail left and right on your machine. Or you could use SnojNS.

SnojNS sits between you and your current DNS server. It can add or change domains much like the hosts file, but it can do so much more, like CNAME, PTR, or SRV record types. I’m hoping to add more at later dates, but not to worry, when it comes across a request it doesn’t understand, it just forwards it and relays the info back so you’re never without internet access.

Running it:

Unzip it or compile, edit the hosts.config, open a command prompt, and run. Or if you’re feeling brave, double click to run it and forget about logging any errors that pop up.

sample output of snojns.

Issues:

Seems to have an issue when there is a lot of requests. That is…it’ll crash. Though the data suggests that it has to do with the forward lookup rejecting udp connections and we can’t yet recover from the error.

Download:

If you’re smart enough to run this, you’ll know which you’ll want to get.

snojns 0.1.0: ReleaseDebugSource

Features:

  • define a, cname, ptr, and srv resource records
  • forward lookups for undefined domains and unknown resource record types
  • define forward lookups based on requested domain
    • somehost.com can use google’s servers (8.8.8.8) while someotherhost.com uses opendns’ (208.67.222.222)
  • a lot of unused code and commented out sections.

Features Road map:

Not all may happen, but ideas I’d like to explore.

  • config file watch: try reloading the hosts file after a save operation so there’s no need to restart.
  • more record types: like AAAA (ipv6), TXT, and MX.
  • separate dns packet parsing into its own dll
  • create an actual windows service?
  • cache! need that cache.
  • ttl definitions for local records?
  • plugin system to introduce new record types and classes (though who would use anything other than IN?)
  • TCP
  • lookups over ssh: ‘cuz we can’t trust the transit (I’m looking at you Hak5, with your pineapple).
  • DNSSEC
  • load balancing round robins for both answers and forward lookups.

 

 

Also, if someone comes up with a better name than “SnojNS” that I like, I’ll buy you $10-15 something from woot.com or amazon as thanks….so thanks! Just post it in the comments or something, as long as I get your email and address.