Julius Kaiser
Leipzig, Germany
jkdata@mailbox.org


Title: Public Authoritative DNS...
Status: Release

Published: 03 Oct 2022
Updated: 10 Sep 2023

Public Authoritative DNS with BIND on OpenBSD

Running authoritive nameservers for a few zones isn’t a complicate or expensive thing to do. This guide will get you through the basic steps to setup a high availability pair of two nameservers using BIND on OpenBSD - complete with forward and reverse mapping zones.

The configuration shown here is pretty much what I’ve set up to provide domain name services for the zones jkdata.de (forward mapping) and 8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa (reverse mapping for the IPv6 prefixes 2001:67c:2708::/48 and below).

Table of Contents

Assumptions

  • You know how the domain name system (DNS) works in theory.
  • You know how to set up a basic system with OpenBSD.
  • You can set NS records for your forward mapping zones; jkdata.de. in this guide.
  • Your reverse mapping zones (8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa and below in this guide) are delegated by your RIR; That means a domain-object exists for the shortest applicable prefix and refers to the proper nameservers.
  • The primary (master) nameserver here is dns01.jkdata.de
    • IPv4: 185.16.61.168
    • IPv6: 2a03:4000:a:2fc::1
  • The secondary (slave) nameserver here is dns02.jkdata.de
    • IPv4: 37.120.168.12
    • IPv6: 2a03:4000:6:5049::1

Requirements & Costs

  • Providing public, authoritative name services requires at least two hosts with static, public IP addresses in different subnets & preferably in different autonomous systems. I’m using two virtual private servers (VPS) hosted at netcup.de, for less than 5 EUR in total per month.
    • This means both dns01 and dns02 are served from the same AS here. Currently not a problem for RIPEs reverse-dns validation - but not ideal.
  • Unless you do not want to become a DENIC member and register your forward-mapping-zones yourselves - which is quite pricey for my conditions - you’ll need a registar. My domains are registered via selfhost.de for 1 EUR per .de-Domain. You’ll probably find cheaper providers with even better webdesigns, but selfhost.de’s services and support never let me down in more than ten years. (And they’re from Saxony - so I just support my local registrar!)
  • To delegate name services for a reverse mapping zone you’ll need administrative access to the domain objects for your prefixes at your local Internet registry (LIR) - RIPE NCC in this case. Unless you’re a paying RIPE member - which is quite pricey for my conditions, too - the costs for this depend on whatever your sponsoring LIR is charging you. If you’re doing things for fun or as part of a wider contractual relationship, chances are good you’re getting this for free or as part of things you’re paying for anyways. I’ll assume 0 EUR for this here.

In total I spend about 6 EUR per month for this setup.

Here’s the domain-object for my personal /48 from the RIPE database:

domain:          8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa
nserver:         dns01.jkdata.de
nserver:         dns02.jkdata.de
admin-c:         JA9284-RIPE
tech-c:          JA9284-RIPE
zone-c:          JA9284-RIPE
mnt-by:          jkdata-de-mnt
created:         2022-11-13T22:18:40Z
last-modified:   2022-11-13T22:18:40Z
source:          RIPE

BIND (named) on OpenBSD

OpenBSD runs BIND in a chroot environment with /var/named/ as its root directory. Log messages are sent to /var/log/daemon. This is the default directory structure:

/var/named/
/var/named/etc/
/var/named/var/
/var/named/tmp/

Conventionally these are the directories people create for zonefiles:

/var/named/master/    // directory for handcrafted zonefiles on your master
/var/named/slaves/    // directory for generated zonefiles on your slave

A working BIND configurarion consists of the zonefiles you need for your use-case and a named.conf that glues everything together, here namely:

  • /var/named/master/jkdata.de
  • /var/named/master/8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa
  • /var/named/master/a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa
  • /var/named/etc/named.conf

The filenames for zonefiles are arbitrary. I prefer to just name them after the zones they are representing.

Primary nameserver (master)

Install bind from OpenBSD’s repositories:

dns01# pkg_add isc-bind

Create master directory for zonefiles:

dns01# mkdir /var/named/master

Zonefiles

A zone file is simply a text file that describes a DNS zone; e.g. a sub-domain and its resources (records). See Wikipedia’s article on zone files for a brief overview, syntax and example records.

jkdata.de

File: dns01:/var/named/master/jkdata.de

$ORIGIN .
$TTL 86400          ; 1 day
jkdata.de           IN SOA  dns01.jkdata.de. jkdata.posteo.de. (
                            2022100702 ; serial
			    10800      ; refresh (3 hours)
			    3600       ; retry (1 hour
			    604800     ; expire (1 week)
			    86400      ; minimum (1 day)
			    )
                    NS      dns01.jkdata.de.
		    NS      dns02.jkdata.de.
		    A       185.199.108.153
		    A       185.199.109.153
		    A       185.199.110.153
		    A       185.199.111.153
		    AAAA    2606:50c0:8000:0000:0000:0000:0000:0153
		    AAAA    2606:50c0:8001:0000:0000:0000:0000:0153
		    AAAA    2606:50c0:8002:0000:0000:0000:0000:0153
		    AAAA    2606:50c0:8003:0000:0000:0000:0000:0153

$ORIGIN jkdata.de.
dns01                   A       185.16.61.168
                        AAAA    2a03:4000:000a:02fc:0000:0000:0000:0001
dns02                   A       37.120.168.12
                        AAAA    2a03:4000:0006:5049:0000:0000:0000:0001
www                     CNAME   jlsksr.github.io.

8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa

Reverse mapping for prefix: 2001:67c:2708::/48

File: dns01:/var/named/master/8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa

$TTL 86400 ; 1 day @ IN SOA dns01.jkdata.de. jkdata.posteo.de. ( 2022112201 ; serial 10800 ; refresh (3 hours) 3600 ; retry (1 hour) 604800 ; expire (1 week) 86400 ; minimum (1 day) ) IN NS dns01.jkdata.de. IN NS dns02.jkdata.de.

; IPv6 PTR entries
$ORIGIN 8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0    IN PTR    er61.jkdata.de.

a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa

Reverse mapping for prefix: 2001:67c:2708:a::/64

File: dns01:/var/named/master/a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa

$TTL 86400 ; 1 day ; origin added to names not ending with a dot: ; a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa @ IN SOA dns01.jkdata.de. jkdata.posteo.de. ( 2022112201 ; serial 10800 ; refresh (3 hours) 3600 ; retry (1 hour) 604800 ; expire (1 week) 86400 ; minimum (1 day) ) IN NS dns01.jkdata.de. IN NS dns02.jkdata.de.

; IPv6 PTR entries
$ORIGIN a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0     IN PTR    er61.jkdata.de.

named.conf for master

File: dns01:/var/named/etc/named.conf

acl clients {
    localnets; ::1;
};

acl jka_dns_servers {
    185.16.61.168; 2a03:4000:a:2fc::1;
    37.120.168.12; 2a03:4000:6:5049::1;
};

options {
    directory "/tmp";
    version "";
    listen-on    { any; };
    listen-on-v6 { any; };
    empty-zones-enable yes;
    allow-recursion { clients; };
    dnssec-enable yes;
    dnssec-validation yes;
};

zone "jkdata.de" IN { type master; file "../master/jkdata.de"; allow-transfer { jka_dns_servers; }; };
zone "8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa" IN { type master; file "../master/8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa"; allow-transfer { jka_dns_servers; }; };
zone "a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa" IN { type master; file "../master/a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa"; allow-transfer { jka_dns_servers; }; };

Secondary nameserver (slave)

Setting up a slave nameserver basically works like setting up a primary one; A nameserver can be slave for some zones and master for others. The role is set in the zone statements within the named.conf file. Zonefiles are not to be created manually on slaves - they are generated as a result of successful zone-transfers.

Install bind from OpenBSD’s repositories:

dns02# pkg_add isc-bind

Create slaves directory for zonefiles and chown it to _bind:

dns02# mkdir /var/named/slaves
dns02# chown _bind:_bind /var/named/slaves

named.conf for slave

File: dns02:/var/named/etc/named.conf

acl clients {
    localnets; ::1;
};

masters jka_dns_masters {
    185.16.61.168; 2a03:4000:a:2fc::1;
};

options {
    directory "/tmp";
    version "";
    listen-on    { any; };
    listen-on-v6 { any; };
    empty-zones-enable yes;
    allow-recursion { clients; };
    dnssec-enable yes;
    dnssec-validation yes;
};

zone "jkdata.de" IN { type slave; file "../slaves/jkdata.de"; masters{ jka_dns_masters; }; allow-transfer { none; }; };
zone "8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa" IN { type slave; file "../slaves/8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa"; masters{ jka_dns_masters; };  allow-transfer { none; }; };
zone "a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa" IN { type slave; file "../slaves/a.0.0.0.8.0.7.2.c.7.6.0.1.0.0.2.ip6.arpa"; masters{ jka_dns_masters; };  allow-transfer { none; }; };

Verification

forward

$ ping er61.jkdata.de
PING er61.jkdata.de(er61.jkdata.de (2001:67c:2708:a::1)) 56 data bytes
64 bytes from er61.jkdata.de (2001:67c:2708:a::1): icmp_seq=1 ttl=58 time=17.4 ms

reverse

# traceroute --icmp 2001:67c:2708:a::1
traceroute to 2001:67c:2708:a::1 (2001:67c:2708:a::1), 30 hops max, 80 byte packets
 1  2a03:4000:4b::3 (2a03:4000:4b::3)  0.186 ms  0.214 ms  0.211 ms
 2  2a00:11c0:47:3::fa (2a00:11c0:47:3::fa)  0.356 ms  0.429 ms  0.426 ms
 3  2a00:11c0:47:1:47::141 (2a00:11c0:47:1:47::141)  3.452 ms  3.490 ms  3.529 ms
 4  Te0-0-0-0-pr2.FRA.router.colt.net (2001:7f8::201c:0:2)  3.905 ms  3.928 ms  3.926 ms
 5  fe80::2a0:a50f:fc90:c7d2%ens3 (fe80::2a0:a50f:fc90:c7d2%ens3)  10.977 ms  10.991 ms  11.022 ms
 6  2001:920:19d0::77d (2001:920:19d0::77d)  17.066 ms  16.884 ms  16.992 ms
 7  er61.jkdata.de (2001:67c:2708:a::1)  17.234 ms  17.297 ms  17.314 ms

Operation

  • Changes to zones are only done on the primary (master) nameserver
  • rcctl restart isc_named
  • watch /var/log/daemon
  • don’t forget to update zone serial on changes

Additional resources