Unbound DNS resolver? Cut out the middleman!

Software · 5 mins read

Why be exposed to privacy risks by using public DNS servers when you can have your own proper validating, recursive, caching DNS resolver? In the following guide we will install and configure our own instance of a popular DNS resolver. We will use Unbound from NLnet Labs on a Debian based linux distro, but you can use this same configuration file across kernels and other supported operating systems.

To install, open the terminal and paste the following command:

sudo apt install unbound

Some error messages may appear. Since there is no configuration file present, Unbound will not be able to start. To create the Unbound configuration file create “example.conf” in the following directory:


You can use nano or any other file editor utility to copy and save the content below:


verbosity: 0

port: 5678
do-ip4: yes
do-udp: yes
do-tcp: yes
do-ip6: no
prefer-ip6: no

root-hints: "/var/lib/unbound/root.hints"

harden-glue: yes
harden-large-queries: yes
harden-dnssec-stripped: yes
harden-algo-downgrade: yes
harden-referral-path: no
harden-short-bufsize: yes

rrset-roundrobin: yes
unwanted-reply-threshold: 10000000

hide-identity: yes
hide-version: yes
identity: "Server"

deny-any: yes
do-daemonize: no
minimal-responses: yes
use-caps-for-id: no

prefetch: yes
prefetch-key: yes
cache-min-ttl: 300
cache-max-ttl: 28800
serve-expired: no
msg-cache-size: 50m
rrset-cache-size: 100m
edns-buffer-size: 1472
so-rcvbuf: 4m
so-sndbuf: 4m
neg-cache-size: 4m

so-reuseport: yes
qname-minimisation: yes
val-clean-additional: yes

num-threads: 1
msg-cache-slabs: 1
rrset-cache-slabs: 1
infra-cache-slabs: 1
key-cache-slabs: 1

log-queries: no
log-replies: no
log-servfail: no
log-local-actions: no
logfile: /dev/null

private-address: fd00::/8
private-address: fe80::/10

Next step will be to pull the root.hints file from the domain authority for the first time. Execute these two separate commands:

curl -so /var/lib/unbound/root.hints https://www.internic.net/domain/named.root

sudo service unbound restart

The Unbound resolver is now up and running, and will now listen on localhost port 5678. You can change to another IP/port combination in the configuration file.

To make sure that the root.hints file is kept updated (changes rarely and infrequently so around 6 months is quite safe), we can create a cron job that will take care of that for us. Let’s use a separate script for customization sake. Paste the content below in a text editor, like nano, and give it the .sh extension:


test $(date +%m) -eq 2 || test $(date +%m) -eq 7 || exit
curl -so /var/lib/unbound/root.hints https://www.internic.net/domain/named.root
service unbound restart

You can save that file to your home folder, or any other path of your choosing. Don’t forget to give the .sh file permissions to execute:

sudo chmod a+x /home/user/example.sh

Finally, let’s schedule a task using cron:

sudo crontab -e

Add this line in the end of the prompt/file and save it:

0 4 1 * * sh /home/user/example.sh

These steps will schedule an update of your root.hints at 4 AM every 1st of February and July, and restart the Unbound service to apply the changes.

To make sure your device(s) is(are) using your Unbound instance, make the TXT record query below.

On Unix:

dig +short TXT whoami.ipv4.akahelp.net

On Windows:

nslookup -type=TXT whoami.ipv4.akahelp.net

In the non-authoritative answer, the “ns” record is the unicast IP address of the requesting recursive resolver. You should get your IP if the Unbound instance is local, or your VPS IP if in the cloud. If not, your device is not using your Unbound resolver but some other DNS provider. Check your network/device for DNS leaks.

Optional step: Paired with pi-hole or AdGuardHome, you can add an extra layer between you and the resolver, filtering nefarious domains.

Share:  EMail · Reddit · Twitter · Telegram · Whatsapp · Threema

Back to previous page