IPv6 for the simple Debian based DNS server

The last post was about a simple DNS server installation using Debian / Raspbian and bind. I already mentioned that this approach has the advantage of greater flexibility and more features than the DNS functionality that may come with your NAS or router. Particularly regarding IPv6, and that is what we are going to add to the DNS server now.

One more thing about the Raspberry Pi: once you’re familiar with its OS & configuration and add DHCP, tftp and some helpers for Kickstart, you can use this tiny box to easily install a few dozen ESXi hosts in less than a day. Let me know if I should continue my series with that.

As a prerequisite I assume that your DNS server runs fine with the IPv4 addresses. If you chose a different network address please keep that in mind since the files or output given may contain the example values from my last post.

The first thing to do is to choose the IPv6 network prefix. For my homelab I decided (read: could not resist) to use the prefix 2001:db8:1ab::/48. The 2001:db8::/32 prefix is reserved for documentation purposes in RFC3849, which means it should rather not be used in real network setups, and should not be routed. Well, a blog post should count as “documentation”, and besides the mentioned restrictions the setup works perfectly in reality. That said you may use some other network prefix from the documentation range as well, or simply copy everything from this tutorial. A different prefix will make it a bit harder for you to build the bind configuration files, especially if you decide to use a /56 or /64 range instead. I suggest you stick with 2001:db8:abcd::/48 for now. In a few days I will post a script that creates the corresponding bind configuration and reverse zone files from a forward zone, so that you are free to choose.

One important warning: DO NOT use an IPv6 prefix you may have received from your ISP if your Internet connection is already IPv6 enabled. You first need to understand that there is nothing like NAT in IPv6 and your internal systems may be fully exposed to the Internet if you use addresses from those officially assigned ranges for your systems. The IPv6 stack and especially firewall functions of SoHo routers are still often buggy – at best.

So here’s what we’re going to implement:

Network prefix 2001:db8:1ab::/48
Administration subnet 2001:db8:1ab:16::/64

Why “16”? Because that’s the (decimal) VLAN ID I’m using for the administration network in my lab. Of course the correct hexadecimal value would be “10”, but with 64k of /64 subnets available I decided to keep things simple and easier to remember. Which is a good idea for real world large data centers as well BTW.

The same approach applies to the IP addresses of the hosts, where I simply use the last octet of their IPv4 address:

Hostname IPv6 address
dns 2001:db8:1ab:16::3/128
esxi01 2001:db8:1ab:16::11/128
esxi02 2001:db8:1ab:16::12/128
esxi03 2001:db8:1ab:16::13/128
esxi04 2001:db8:1ab:16::14/128
vcenter 2001:db8:1ab:16::20/128
vma 2001:db8:1ab:16::21/128

We now only need to add this to the forward lookup zone file /etc/bind/db.lab.local. These records are of type “AAAA”, whereas IPv4 entries are of type “A”:

dns             IN      AAAA    2001:db8:1ab:16::3
esxi01          IN      AAAA    2001:db8:1ab:16::11
esxi02          IN      AAAA    2001:db8:1ab:16::12
esxi03          IN      AAAA    2001:db8:1ab:16::13
esxi04          IN      AAAA    2001:db8:1ab:16::14
vcenter         IN      AAAA    2001:db8:1ab:16::20
vma             IN      AAAA    2001:db8:1ab:16::21

But a better way of doing this would be to add each IPv6 address below the IPv4 entry like this:

esxi01          IN      A       192.168.111.11
                IN      AAAA    2001:db8:1ab:16::11

You can now already check if the IPv6 name lookup works after restarting the daemon. Did you remember to update the serial? 😉

root@labsvc:/etc/bind# service bind9 restart

root@labsvc:/etc/bind# host esxi01
esxi01.lab.local has address 192.168.111.11
esxi01.lab.local has IPv6 address 2001:db8:1ab:16::11

The host command is a bit too user friendly in this case, same as nslookup on Windows. In fact it should not return both IPv4 and IPv6 addresses, but only the type of record requested, which would default to IPv4 (A). On Linux nslookup works correctly and you would need to add the “-query=aaaa” parameter to get the IPv6 (AAAA) record. If you want to try this out you need to install the dnsutils package first:

apt-get install dnsutils

Then check the different output:

root@labsvc:/etc/bind# nslookup esxi01
Server:         192.168.111.3
Address:        192.168.111.3#53

Name:   esxi01.lab.local
Address: 192.168.111.11

root@labsvc:/etc/bind# nslookup -query=aaaa esxi01
Server:         192.168.111.3
Address:        192.168.111.3#53

esxi01.lab.local        has AAAA address 2001:db8:1ab:16::11

The configuration of the reverse lookup is a bit more complicated. We first need to declare the additional address range in /etc/bind/named.conf.local. Add the following before the last line containing the include statement:

zone "b.a.1.0.8.b.d.0.1.0.0.2.ip6.arpa"
{
        type master;
        notify no;
        file "/etc/bind/b.a.1.0.8.b.d.0.1.0.0.2.ip6.arpa";
};

You will surely have noticed that the naming scheme with the network address written in reverse is very similar to IPv4 – but it’s longer with IPv6, and one has to remember that each hexadecimal block must be filled up with zeros to its nominal length of 4 characters / 16 bit. It’s convenient to omit these zeros when using an IPv6 address, but bind requires them. So we expand 2001:db8:1ab:: to 2001:0db8:01ab:: and then write it in reverse.

Create the new file /etc/bind/b.a.1.0.8.b.d.0.1.0.0.2.ip6.arpa with the following content:

$ORIGIN b.a.1.0.8.b.d.0.1.0.0.2.ip6.arpa.
$TTL    1d
@       IN      SOA     localhost. root.localhost. (
                        2014011501      ; Serial
                        86400           ; Refresh
                        7200            ; Retry
                        2592000         ; Expire
                        172800          ; Minimum TTL
                        )
        IN      NS      dns.lab.local.
; 2001:db8:1ab:16::/64
3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0 IN      PTR     dns.lab.local.
1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0 IN      PTR     esxi01.lab.local.
2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0 IN      PTR     esxi02.lab.local.
3.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0 IN      PTR     esxi03.lab.local.
4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0 IN      PTR     esxi04.lab.local.
0.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0 IN      PTR     vcenter.lab.local.
1.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0 IN      PTR     vma.lab.local.

This is less convenient than with IPv4. The basic principle is the same: the file name (and/or ORIGIN in the header) gives the network part. With IPv4 only one last octet, the host address, was required for each entry. But with IPv6 the host address part is 64 bit long, and again each block must be filled up with zeros. The same applies to the subnet part. So for example the address of the DNS server is expanded from [prefix 2001:db8:1ab] subnet 16 host ::3 to 0016:0000:0000:0000:0003 and then written in reverse with dots instead of colons.
Personally I think that bind should be enhanced to be able to parse the regular IPv6 format internally, instead of imposing this upon the DNS admin. But again: I’ll provide a script for this.

Restart the daemon a last time and check if everything works:

root@labsvc:/etc/bind# host ntp
ntp.lab.local is an alias for dns.lab.local.
dns.lab.local has address 192.168.111.3
dns.lab.local has IPv6 address 2001:db8:1ab:16::3

root@labsvc:/etc/bind# host 2001:db8:1ab:16::3
3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.1.0.0.b.a.1.0.8.b.d.0.1.0.0.2.ip6.arpa domain name pointer dns.lab.local.

Since we defined an IPv6 address for our DNS server it’s time to actually configure it on the system. Edit /etc/network/interfaces and search for eth0. The current config should look something like this:

# The primary network interface
allow-hotplug eth0
iface eth0 inet static
        address 192.168.111.3
        netmask 255.255.255.0
        gateway 192.168.111.1

There may be some “dns-something” setting in there which you can simply ignore. Go to the end of the file and add the following:

iface eth0 inet6 static
        address 2001:db8:1ab:16::3
        netmask 64

Just reboot the system (to keep it simple) and the new static IPv6 address wil be active:

root@labsvc:~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:0c:12:34:56:20
          inet addr:192.168.111.3  Bcast:192.168.111.255  Mask:255.255.255.0
          inet6 addr: 2001:db8:1ab:16::3/64 Scope:Global
          inet6 addr: fe80::20c:12ff:fe34:5678/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

Congratulations again. Your private DNS server is now able to handle IPv6 name and address lookup.

I hope you agree that this again was not to complicated, except for the lengthy addresses maybe. But to be perfectly honest static IPv6 addresses are not that exciting anyway, there’s much more interesting features in IPv6. Time to play around…

Leave a Reply

Your email address will not be published. Required fields are marked *

*

code