Public Authoritative DNS with BIND on OpenBSD
- Assumptions
- Requirements & Costs
- BIND (named) on OpenBSD
- Primary nameserver (master)
- Secondary nameserver (slave)
- Verification
- Operation
- Additional resources
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).
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
- IPv4:
- The secondary (slave) nameserver here is
dns02.jkdata.de
- IPv4:
37.120.168.12
- IPv6:
2a03:4000:6:5049::1
- IPv4:
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
anddns02
are served from the same AS here. Currently not a problem for RIPEs reverse-dns validation - but not ideal.
- This means both
- 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
- RFC1034 - Domain Names - Concepts and Facilities
- RFC1035 - Domain Names - Implementation and Specification
- An Overview of BIND 9 Documentation - Internet Systems Consortium (ISC)
- BIND 9 Administrator Reference Manual - readthedocs.io
- "DNS and BIND" (Liu/ Albitz, O'Reilly, 2006)
- "DNS & BIND on IPv6" (Liu, O'Reilly, 2011)