Setting Up a DNS Server (BIND/Unbound)

Deploy and configure authoritative and recursive DNS servers using BIND and Unbound. Cover zones, records, forwarding, DNSSEC, and caching.

Authoritative vs Recursive DNS

There are two fundamentally different types of DNS servers:

Type Purpose Examples
Authoritative Answers queries for domains it owns (e.g., your domain) BIND, PowerDNS, Knot DNS
Recursive Resolves queries by walking the DNS tree on behalf of clients Unbound, BIND (resolver mode), Knot Resolver

Most organizations need both. An authoritative server for their domain, and a recursive resolver for internal clients.

Unbound: Recursive Resolver

Unbound is the recommended recursive resolver — lightweight, secure, and focused on one job:

# Install on Ubuntu
sudo apt install unbound

# /etc/unbound/unbound.conf
server:
    interface: 0.0.0.0
    port: 53
    access-control: 10.0.0.0/8 allow
    access-control: 127.0.0.0/8 allow
    access-control: 0.0.0.0/0 refuse

    # Performance
    num-threads: 2
    msg-cache-size: 64m
    rrset-cache-size: 128m
    cache-min-ttl: 300
    cache-max-ttl: 86400

    # Security
    hide-identity: yes
    hide-version: yes
    harden-glue: yes
    harden-dnssec-stripped: yes

    # DNSSEC validation
    auto-trust-anchor-file: "/var/lib/unbound/root.key"

    # Privacy: DNS-over-TLS forwarding
    tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt

forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 1.0.0.1@853#cloudflare-dns.com

This configuration creates a caching, DNSSEC-validating resolver that forwards queries to Cloudflare over encrypted TLS.

BIND: Authoritative Server

BIND is the most widely used authoritative DNS server:

# Install on Ubuntu
sudo apt install bind9 bind9-utils

# /etc/bind/named.conf.local
zone "example.com" {
    type master;
    file "/etc/bind/zones/db.example.com";
    allow-transfer { 10.0.0.2; };  # Secondary DNS server
};

Zone File

; /etc/bind/zones/db.example.com
$TTL    3600
@       IN      SOA     ns1.example.com. admin.example.com. (
                        2026022501  ; Serial (YYYYMMDDNN)
                        3600        ; Refresh
                        900         ; Retry
                        604800      ; Expire
                        86400 )     ; Negative cache TTL

; Name servers
@       IN      NS      ns1.example.com.
@       IN      NS      ns2.example.com.

; A records
@       IN      A       203.0.113.10
www     IN      A       203.0.113.10
api     IN      A       203.0.113.20

; CNAME
blog    IN      CNAME   www.example.com.

; MX records
@       IN      MX  10  mail.example.com.
mail    IN      A       203.0.113.30

; TXT records (SPF, DKIM, DMARC)
@       IN      TXT     "v=spf1 mx ~all"

Important: Increment the serial number every time you edit the zone file. Secondary servers use this to detect changes.

DNSSEC

DNSSEC adds cryptographic signatures to DNS responses, preventing tampering:

# Unbound validates DNSSEC automatically with:
auto-trust-anchor-file: "/var/lib/unbound/root.key"

# Test DNSSEC validation
dig @127.0.0.1 cloudflare.com +dnssec
# Look for "ad" flag (Authenticated Data) in the response

For authoritative DNSSEC signing with BIND, generate keys with dnssec-keygen and sign zones with dnssec-signzone. Most operators use their registrar or DNS provider for DNSSEC signing due to the complexity of key management.

Testing DNS Servers

# Query your recursive resolver
dig @10.0.0.1 google.com

# Query your authoritative server
dig @ns1.example.com example.com SOA

# Check zone transfer
dig @ns1.example.com example.com AXFR

# Verify DNSSEC chain
delv @10.0.0.1 example.com +rtrace

See Also