Static DNS Openbsd

This is a short digest of this video with my own adaptations for working with a reverse proxy.. What I mean by “static DNS” is basically a DNS server that consults other DNS servers on the internet with some static exceptions.

The exceptions I make here are for domain names that I own myself (and thus avoids conflicts with stuff on the internet). It will probably not take much work to turn this into a recursive DNS server (speeding up resolve times), but that’s not the focus here.

On OpenBSD

OpenBSD ships with unbound (one of many DNS servers) running sort of sandboxed. This can be seen by that the configuration file is found in the following directory:

/var/unbound/etc/unbound.conf

as opposed to the normal

/etc/<service>/<service>.conf
  1. Back-up the default configuration file:

    doas -s
    cd /var/unbound/etc
    cp unbound.conf unbound.conf.bak
    
  2. Clear file contents and enter something like this:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    server:
         interface: 0.0.0.0
         access-control: 0.0.0.0/0 deny
         access-control: ::/0 deny
         access-control: 192.168.1.0/24 allow
         access-control: 127.0.0.1 allow
         access-control: ::1 allow
    
         local-zone: "sub.domain.tld" static
         local-data: "sub.domain.tld IN A 192.168.1.2"
    
     forward-zone:
         name: "."
         forward-addr: 1.1.1.1
         forward-addr: 1.1.1.2
         forward-first: yes
    

    The interface setting limits what interfaces unbound listens on (in this case no limits). All the access-control settings define what we allow and deny to query the server. In-short I basically deny everything except the network 192.168.1.0/24 as well as IPv4 and IPv6 loopback.

    The interesting stuff is local-zone and local-data. With local-zone you can specify a domain-name that unbound will resolve by itself to whatever you put in local-data. In this example you can see how you can set up a domain on the local network that points to the IP-address 192.168.1.2.

  3. Run the following commands to enable unbound:

    unbound-checkconf # Resolve any syntax-errors listed here
    rcctl enable unbound
    rcctl start unbound
    

On Arch Client

Run something equivalent to the following commands to test unbound:

sudo pacman -S bind
dig @192.168.1.1 sub.domain.tld

In this context unbound is running on a network interface with IP-address 192.168.1.1. The output should look something like this:

; <<>> DiG 9.20.6 <<>> @192.168.1.1 sub.domain.tld
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56485
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;sub.domain.tld.                IN      A

;; ANSWER SECTION:
sub.domain.tld. 3600    IN      A       192.168.1.2

;; Query time: 1 msec
;; SERVER: 192.168.1.1#53(192.168.1.1) (UDP)
;; WHEN: Mon Mar 10 17:27:32 CET 2025
;; MSG SIZE  rcvd: 67

The important thing is that feeding it sub.domain.tld should give you back 192.168.1.2