Run in a chroot

chroot: "/etc/unbound"

Drop privileges to unbound user


Address/interface to listen on

Use to listen on all

# interface:

Egress interface

We also have the option of specifying the outgoing interface
This is applicable if you have multiple links to the internet
and wish to restrict vpn traffic to a particular one


Types of queries to accept

do-ip6: no
do-ip4: yes
do-udp: yes
do-tcp: yes

Access control

Specify the CIDR blocks to allow or deny
On an internet reachable host, use iptables too

access-control:     allow
access-control:      allow
access-control:  allow
access-control:   allow
access-control:       refuse

Root hints:

Next, we manually download the root hints
"wget -qO root.hints"

root-hints: "/etc/unbound/root.hints"

Trust anchors:

The trust anchors are taken care of by the unbound-anchor utility. It runs a cron job to ensure they are up-to-date

What are trust anchors? In DNSSEC, there is a chain of trust.

The parent zone must have records that verify the child zone
These are generally DS records which are hashes of the Zone signing key

A traversal works like this
DS records in root verify the DNSKEYs for .net
DS records in .net verify the DNSKEYs for
The DNSKEYs for verify the resource records.

So the chain of trust needs a starting point,
this key provided by ICANN is used to verify the root zone

auto-trust-anchor-file: "/etc/unbound/root.key"

Hide our peers from seeing info about this instance

hide-identity:  yes
hide-version :  yes

Will trust glue only if it is within the servers authority.

Suppose I want to set as the NS for,
then I need to set recotd 'ns' as a glue record


A zone we expect to be secure only responds with non-secure/conventional DNS. What to do?

By default, we repudiate the non-secure records, rendering the domain unreachable. This is the same behavior as receiving dnssec data that cannot be validated by the anchor

If set to no, it just accepts the unverified data at face value
behaving as though it was a conventional dns zone

Keep this set to yes


When sending a query to the authority NS,

PeRtUrB cAsE of rhw queries.
Best to leave this set to "no" (default) as it can cause unreliability


Performance and computational options.

If you don't have a multicore/hyperthreaded machine (e.g. running on embedded router) then set num-threads to 1 (disable multithreading )

The slabs must take a value approximately double the number of threads
this value must be a power of 2

num-threads:        4
msg-cache-slabs:    2        
rrset-cache-slabs:  2  
key-cache-slabs:    2
infra-cache-slabs:  2

RRset size

The RRset cache record values like A,NS
These values are appropriate for a desktop or server

On a small embedded device like a router, use values like 2m


Message cache size.

Msg cache contains metadata, things like AD bit etc
This should be 1/2 the size of the rrset-cache


Prefetch the message cache

When popular entries are about to expire, we

prefetch: yes

Override records with short TTL (time to live)

we do --not-- update records below this time
Don't make it longer than ~300s, you may get stale records


Override records with long TTL
Don't keep cached records for longer than 30h (10800)


Custom records

Forward zone

Suppose you have a special dns provider for accessing US netflix
You can set a forward zone here so that queries to netflix are selectively forwarded to that server

    name:           ""

Stub zones

There is also a type of zone known as a stub zone.
A forward zone is expected to be recursive and can completely answer queries

A stub zone points to the 'next hop'

    name: ""
    stub-addr: ""

Internal records

local-data:      "gateway IN A"
local-data:      "foo-pc  IN A"
local-data:      "bar-pc  IN A"
local-data-ptr:  "gateway IN A"

We can split our config into multiple files.

Let's add a file containing local records to block ad domains

include: /etc/unbound/ads.conf

Forward along to another server.

If you don't want to look up recursive queries yourself

        name:          "."