DNS Security is the practice of protecting DNS infrastructure from cyberattacks in order to keep it performing quickly and reliably. Most of the DNS queries in the internet are unencrypted. It means that your network administrator or ISP provider can see exactly what websites you visit every day. Usually, only one DNS resolver is used so the provider knows all domains that you visit. Security & Privacy might be at risk. Do you trust your ISP or DNS provider?
We are going block malicious websites & ads by predefined blocklists and also cache DNS entries for faster lookups in the future.
In order to accomplish our goals, we use:
- Pihole is a DNS sinkhole that protects your devices from unwanted content without installing any client-side software. It block malicious websites and ads.
- Unbound is a validating, recursive, and caching DNS resolver.
test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 Average
pihole 2 ms 3 ms 2 ms 3 ms 2 ms 2 ms 3 ms 2 ms 2 ms 2 ms 2.30
quad9 12 ms 12 ms 11 ms 12 ms 11 ms 10 ms 11 ms 11 ms 11 ms 11 ms 11.20
google 11 ms 11 ms 11 ms 13 ms 11 ms 12 ms 11 ms 11 ms 11 ms 11 ms 11.30
cloudflare 22 ms 22 ms 22 ms 22 ms 22 ms 22 ms 20 ms 30 ms 34 ms 20 ms 23.60
Leave a ⭐ if you find this project helpful!
docker -v
docker-compose -v
git clone https://github.com/tomajask/pihole-unbound-dns-stack.git
cd pihole-unbound-dns-stack
cp .env.example .env
echo "WEBPASSWORD=`openssl rand -base64 32`" >> .env
chmod 600 .env
mkdir -p ./pihole
touch ./pihole/pihole.log
mkdir -p ./unbound
cp unbound-config-examples/a-records.example.conf ./unbound/a-records.conf
cp unbound-config-examples/srv-records.example.conf ./unbound/srv-records.conf
cp unbound-config-examples/unbound.example.conf ./unbound/unbound.conf
There are 2 options for Unbound:
- Recursive mode - Unbound will act as a Recursive DNS server, the DNS traffic will not be encrypted
touch ./unbound/forward-records.conf
- Fowarding mode - Unbound will act as a forwarding DNS server, it will use DNS over TLS when querying upstream DNS servers
cp unbound-config-examples/forward-records.example.conf ./unbound/forward-records.conf
If you are not sure which one to use, see discussions: here, here, here
sudo lsof -i -P -n | grep ':53 (LISTEN)'
If the result is empty then it's ready to go. If not, then most probably it's systemd-resolve
's DNSStubListener running.
To disable the DNSStubListener
& Cache
, run:
sudo sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf
sudo sed -r -i.orig 's/#?Cache=yes/Cache=no/g' /etc/systemd/resolved.conf
Restart systemd-resolve
:
sudo systemctl restart systemd-resolved
sudo systemctl status systemd-resolved
Check whether port 53
is freed now:
sudo lsof -i -P -n | grep ':53 (LISTEN)'
docker-compose up -d
You should be able to access now the Pihole Admin panel on <ip_address_of_the_server>/admin
(e.g. http://192.168.1.20/admin).
The default list of blocked domain provided by Pihole is quite small. If you'd like to add more domains, then visit https://firebog.net/ & https://phishing.army/ and add them in the Pihole Admin panel: Panel -> Group Management -> Adlists -> Add a new addlist
.
By default, as upstream DNS resolvers for Unbound are used Cloudflare's and Quad 9's server. They can be adjusted in forward-records.conf
config file.
If you need to setup some local DNS entries, you can add them in Pihole or Unbound:
- Pihole:
Panel -> Local DNS -> DNS Records
orPanel -> Local DNS -> CNAME Records
- Unbound: add new entries to
a-records.conf
config file.
By default, Unbound is configured to use DNS over TLS for upstream DNS resolvers. See forward-records.conf
config file.
In order to check whether DoT (DNS over TLS) is enabled, you can visit https://1.1.1.1/help.
If you are curious how performant your Pihole with Unbound is you can test it with dnsperftest.
To run the test following instructions or:
- install prerequisites
sudo apt install bc dnsutils -y
- clone the repo
git clone --depth=1 https://github.com/cleanbrowsing/dnsperftest/
cd dnsperftest
- insert your Pihole's instance IP address for tests
sed -i '/^PROVIDERS="/a 192.168.1.20#pihole' dnstest.sh
- run the test a few times to allow cache to build itself
./dnstest.sh
./dnstest.sh
./dnstest.sh | sort -k 22 -n
Ideally, pihole
should result on average in a very low latency
In order to see how logs should look like, you can visit https://unboundtest.com and test a domain.
To achieve the same log level in this stack you need to adjust the verbosity
level for unbound:
sed -i 's/verbosity: \d/verbosity: 2/g' ./unbound/unbound.conf
Resolve a domain (replace the IP of the Pihole, adjust the port if needed):
dig github.com @192.168.1.20 -p 53
See: https://www.reddit.com/r/pihole/comments/d9j1z6/unbound_as_recursive_dns_server_slow_performance/