on Ubuntu Server xenial or artful

Preliminary Step

Make sure you do NOT have those installed: dnsmasq, resolvconf, NetworkManager. If so, disable or remove them.

Installation

Either install some binary package,

apt install unbound

Or build from scratch as follows.

Install a few required libraries,

apt install libevent-dev libexpat1-dev

Note. libevent is optional but as stated in the README, it may be useful in case of using many outgoing ports (1000+). Use with --with-libevent at compilation time.

Package description (apt show libevent-dev) says,

Description: Asynchronous event notification library (development files)
 Libevent is an asynchronous event notification library that provides a
 mechanism to execute a callback function when a specific event occurs
 on a file descriptor or after a timeout has been reached.
 .
 This package includes development files for compiling against libevent.

Fetch the latest version of Unbound and compile it,

wget https://www.unbound.net/downloads/unbound-1.6.5.tar.gz
#SHA256 checksum: e297aa1229015f25bf24e4923cb1dadf1f29b84f82a353205006421f82cc104e
sha256sum unbound-1.6.5.tar.gz
tar xzf unbound-1.6.5.tar.gz
cd unbound-1.6.5/
./configure --with-libevent
make
make install

Create a system user for Unbound to drop its priviledges,

useradd -r unbound
grep unbound /etc/passwd
grep unbound /etc/group

Generate the TLS key files for the unbound-control tool to work,

unbound-control-setup
ls -lhF /usr/local/etc/unbound/unbound*.{key,pem}

Configuration

Check how many cores you have got,

grep ^processor /proc/cpuinfo

Setup the caching name server,

cd /etc/
#ln -s /usr/local/etc/unbound
cd /etc/unbound/
wget https://www.internic.net/domain/named.cache
mkdir trash/
mv unbound.conf unbound.conf.d/ trash/

#grep -Ev '^[[:space:]]*(#|$)' unbound.conf > unbound.conf.dist.clean
vi unbound.conf

server:
        verbosity: 2
        num-threads: HOW_MANY_CORES
        interface: 0.0.0.0
        interface: ::0
        access-control: 0.0.0.0/0 allow_snoop
        access-control: ::/0 allow_snoop
        pidfile: "/var/run/unbound.pid"
        root-hints: "named.cache"
        hide-identity: yes
        hide-version: yes
        #do-not-query-localhost: no
        #rrset-roundrobin: yes
        qname-minimisation: yes
        auto-trust-anchor-file: "/var/lib/unbound/root.key"
        domain-insecure: "example.local"
        domain-insecure: "1.1.10.in-addr.arpa"
        local-zone: "1.1.10.in-addr.arpa." transparent

remote-control:
        control-enable: yes

stub-zone:
        name: "example.local"
        stub-addr: 10.1.1.253

stub-zone:
        name: "1.1.10.in-addr.arpa."
        stub-addr: 10.1.1.253

Operations

Always watch the logs in another window,

tail -F /var/log/syslog

Check the configuration,

unbound-checkconf /etc/unbound/unbound.conf

Run the daemon,

#unbound-control start
systemctl restart unbound

Check the status and see if port 53 is used,

unbound-control status
ls -alhF /var/run/unbound.pid
cat /var/run/unbound.pid
ps auxfw | grep ^unbound
netstat -antupe --inet --inet6 | grep -E ':53[[:space:]]'

To load the configuration changes,

unbound-control reload

Acceptance

Testing local-zone,

host localhost localhost
host 127.0.0.1 localhost

Testing cached public zone,

host mx.nethence.com localhost
host 62.210.110.7 localhost

Testing cashed stub-zone,

host example.local localhost
host pxe.example.local localhost
host 10.1.1.1 localhost

Troubleshooting

If Unbound service is listening but refusing to answer queries, fix access-control: as shown in the example above.

References