Configuring IPv6 rDNS using NSD
Overview
Many internet protocols require your address' rDNS to match forward DNS to work properly. For IRC, proper rDNS is required for your vhost to load properly. For email, proper rDNS is required to avoid being marked as spam. In this guide, we use nsd, an authoritative name server, to provide rDNS.
Installation
nsd comes as part of openbsd base so no installation will be necessary.
NOTE: This guide assumes you have already configured nsd for forward DNS resolution.
Docs and references
Consult the man pages for [nsd|https://man.openbsd.org/nsd]], nsd.conf, [nsd-checkconf, and [nsd-checkzone. Consult the man pages for [nsd|https://man.openbsd.org/nsd]], nsd.conf, [nsd-checkconf, and [nsd-checkzone.
DNS for Rocket Scientists and [The TCP/IP Guide are helpful resources for further reading. DNS for Rocket Scientists and [The TCP/IP Guide are helpful resources for further reading.
Configuration
IPv6 Subnet
Suppose we have been delegated the rDNS zone for our IPv6 subnet, 2001:db8:1::/48. To find out our zone, we need to fill in all the missing zeros, put periods between each digit, reverse the digits, then add ip6.arpa:
WARNING: You must fill in all missing zeros!
2001:db8:1:: # original subnet is /48
2001:0db8:0001:: # fill in the missing zeros up to the /48 subnet
2.0.0.1.0.d.b.8.0.0.0.1 # add periods between each digit
1.0.0.0.8.b.d.0.1.0.0.2 # reverse the digits
1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa # add ip6.arpa
Here's a second example with the subnet 2602:fccf:1:1::/64:
2602:fccf:1:1:: # original subnet
2602:fccf:0001:0001:: # fill in the missing zeros up to the /64 subnet
2.6.0.2.f.c.c.f.0.0.0.1.0.0.0.1 # add periods between each digit
1.0.0.0.1.0.0.0.f.c.c.f.2.0.6.2 # reverse the digits
1.0.0.0.1.0.0.0.f.c.c.f.2.0.6.2.ip6.arpa # add ip6.arpa
NOTE: Your zone must have subnet divided by 4 number of hex digits. If you have a /48 subnet, this means you will have 48/4 = 12 hex digits. If you have a /64 subnet, you will have 64/4 = 16 hex digits.
Here is a command to do this:
$ perl -e 'print substr(join(".",(split//,sprintf("%25032s", scalar reverse(join("", map(sprintf("%2504s", $_), split(":", "<IP6>"))))))),(64-<SUBNET>/2)).".ip6.arpa.\n";'
You need to replace
$ perl -e 'print substr(join(".",(split//,sprintf("%25032s", scalar reverse(join("", map(sprintf("%2504s", $_), split(":", "2001:db8:1::"))))))),(64-48/2)).".ip6.arpa\n";'
1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa
So, you know the name of your zone file is /var/nsd/zones/master/1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa
(:if false:)
echo "
grep inet6.*48 /etc/hostname.vio0|awk '{print$2}'|rev|sed "s/://g;s/(.)/\1./g;s/$/ip6.arpa/"
(:ifend:)
Zone File
Inside the zone file /var/nsd/zones/master/1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa, we create these records:
$ORIGIN 1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
@ 3600 IN SOA ns1.example.com. admin.example.com. (
2021082301 1800 3600 1209600 3600 )
3600 IN NS ns1.example.com.
3600 IN NS ns2.example.com.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 3600 IN PTR user1.example.com.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 3600 IN PTR user2.example.com.
The records must have 32 - $SUBNET/4 hex digits. For example, if your subnet is length 48, then your records will have 32 - 48/4 = 20 hex digits. If you subnet length is 64, then your records will have 32 - 64/4 = 16 hex digits.
NOTE: All of the PTR records should have values that end with a final dot . -- they should be fully qualified domain names. Without a terminating dot, a record like:
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 3600 IN PTR user2
would have $ORIGIN appended to it, so it would be interpreted as user2.1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. This is probably not what you intended!
/var/nsd/etc/nsd.conf
Now we need to add this section to /var/nsd/etc/nsd.conf:
zone:
name: "1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa"
zonefile: "master/1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa"
Restart nsd and test
$ doas rcctl restart nsd
Results
We now test using host or [dig: We now test using host or [dig:
host 2001:db8:1:: <nameserver-ip>
Replace
You can then test if both forward and reverse DNS lookup work by using netcat to connect to IRC.
(:if false:)
Troubleshooting
Primary and secondary server
If you need a secondary server to host the zone, you can do this as follows. Add to the block that describes your master zone, records about the secondary zone as in the example:
zone:
name: "example.net"
zonefile: "master/example.net"
notify: 20.20.20.20 NOKEY
provide-xfr: 20.20.20.20 NOKEY
Create a new block in the secondary server config file, as in the example:
zone:
name: "example.net"
zonefile: "slave/example.net"
allow-notify: 10.10.10.10 NOKEY
request-xfr: 10.10.10.10 NOKEY
The zone file for NSD
The next step is to write the zone files for NSD. First the forward lookup zone example.net:
; Domain file from My project
example.net. 3600 SOA ns.example.net. admin.example.net. (
2020070701 ; serial YYYYMMDDnn
10800 ; refresh
3600 ; retry
604800 ; expire
86400 ) ; minimum TTL
example.net. NS ns.example.net.
example.net. NS ns.secondary.net.
ns A 10.10.10.10
example.net. A 10.10.10.10
www A 10.10.10.10
irc A 10.10.10.10
imap A 10.10.10.10
smtp A 10.10.10.10
example.net. mx 10 smtp.example.net.
Save this zone file as /var/nsd/zones/master/example.net
Configuration check and start
NSD bring along a tool to check the configuration file before you start or reload the daemon:
$ doas nsd-checkconf /var/nsd/etc/nsd.conf
Any errors are reported, so no news are good news. You can go ahead and start NSD:
$ doas rcctl enable nsd
$ doas rcctl start nsd
If there are issues you can start nsd in debug mode
doas nsd -d -V 3
https://www.denic.de/en/service/tools/nast/
$ORIGIN 1.0.0.0.2.0.4.3.0.5.5.0.1.0.0.2.ip6.arpa.
@ 3600 IN SOA ns1.ircnow.org. admin.ircnow.org. (
2020112906 1800 3600 1209600 3600 )
3600 IN NS cherry.ircnow.org.
3600 IN NS pear.ircnow.org.
3600 IN NS mango.ircnow.org.
3600 IN NS peach.ircnow.org.
3600 IN NS banana.ircnow.org.
3600 IN NS guava.ircnow.org.
3600 IN NS jujube.ircnow.org.
3600 IN NS plum.ircnow.org.
3600 IN NS fig.ircnow.org.
3600 IN NS orange.ircnow.org.
3600 IN NS lemon.ircnow.org.
3600 IN NS grape.ircnow.org.
3600 IN NS coconut.ircnow.org.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 3600 IN PTR www.example.com.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 3600 IN PTR www.example.org.
In /var/nsd/etc/nsd.conf:
zone:
name: "1.0.0.0.2.0.4.3.0.5.5.0.1.0.0.2.ip6.arpa"
zonefile: "master/1.0.0.0.2.0.4.3.0.5.5.0.1.0.0.2.ip6.arpa"
include-pattern: "ircnow.org"
(:ifend:)