unbounddns
This tutorial is for users of Debian GNU/Linux who want to run their own recursive DNS server using the Unbound project. In this scenario, I am using GL.iNet MT6000 router and a separate AP. The router handles all dhcp/dns for the LAN / private subnet. In the openWRT config on the router's dhcp server, I specify two custom DNS servers in Interfaces / LAN / DHCP Server / Advanced / 6,10.1.1.100,10.1.1.101
. These DNS servers are Debian VMs on two different production servers in the home office space; each of them is running a pihole server. The pihole-FTL takes care of adblocking and DNS sinkhole duties. If left with default settings, it uses your specified third-party DNS servers for upstream requests (Level 3, Cloudflare, etc.). This tutorial is how to replace those third-party DNS servers with Unbound, running locally on each pihole and on port 5335 instead of port 53, which is already used by pihole-FTL.
sudo apt install unbound sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf # I use for lan-side pihole+unbound installations sudo nano /etc/unbound/unbound.conf #I use this for lan- or wan-side non-pihole installations
In that file, enter something like the following, adjusting as necessary for your use-case.
server: # Logging (minimal) use-syslog: yes verbosity: 1 directory: "/etc/unbound" username: unbound # Bind to all interfaces, non-standard port interface: 0.0.0.0 interface: ::0 port: 5335 do-ip4: yes do-ip6: yes prefer-ip6: no do-udp: yes do-tcp: yes # Module configuration module-config: "validator iterator" # Security and DNSSEC harden-glue: yes harden-dnssec-stripped: yes use-caps-for-id: no aggressive-nsec: yes hide-identity: yes hide-version: yes qname-minimisation: yes harden-large-queries: yes # Cache settings cache-max-ttl: 86400 cache-min-ttl: 3600 rrset-cache-size: 256m msg-cache-size: 128m key-cache-size: 64m neg-cache-size: 16m # Performance tweaks num-threads: 8 msg-cache-slabs: 8 rrset-cache-slabs: 8 infra-cache-slabs: 8 key-cache-slabs: 8 outgoing-range: 4096 num-queries-per-thread: 1024 infra-cache-numhosts: 10000 prefetch: yes prefetch-key: yes serve-expired: yes serve-expired-ttl: 3600 so-reuseport: yes edns-buffer-size: 4096 # Block private address ranges (excluding guest subnet) private-address: 172.0.0.0/8 private-address: 169.254.0.0/16 private-address: 10.0.0.0/8 private-address: fd00::/8 private-address: fe80::/10 # Access control for guest subnet access-control: 127.0.0.1/32 allow access-control: ::1 allow access-control: 192.168.1.0/24 allow
If using unbound with a pihole, let /etc/resolv.conf
on the pihole host be populated by your router. It will fill in with something like:
domain domain.com search domain.com nameserver 192.168.1.254
In my case, I prefer traditional rotated logs with rsyslog, so I do the following:
sudo apt install rsyslog sudo nano /etc/rsyslog.d/unbound.conf <if $programname == 'unbound' then /var/log/unbound/unbound.log> <& stop> nano /etc/logrotate.d/unbound
In the log rotate file, enter the following:
/var/log/unbound/unbound.log { daily rotate 7 missingok create 0640 root adm postrotate /usr/lib/rsyslog/rsyslog-rotate endscript }
Additionally, some Debian systems have resolvconf installed, so many install recipes recommend disabling that service so that it does not overwrite the DNS settings we are making here.
systemctl disable --now unbound-resolvconf.service sed -Ei 's/^unbound_conf=/#unbound_conf=/' /etc/resolvconf.conf rm /etc/unbound/unbound.conf.d/resolvconf_resolvers.conf
To make sure logs are working properly:
nano /etc/apparmor.d/local/usr.sbin.unbound </var/log/unbound/unbound.log rw,> sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.unbound sudo service apparmor restart sudo mkdir -p /var/log/unbound sudo touch /var/log/unbound/unbound.log sudo chown unbound /var/log/unbound/unbound.log
Enforce edns settings specified in config (pihole-only installations):
nano /etc/dnsmasq.d/99-edns.conf <edns-packet-max=1232>
The last step is configuring the unbound server in the pihole GUI. Go to DNS > Custom and then add 127.0.0.1#5335
as a server and disable all the rest. Additionally, don't forget to forward requests to the pihole within openWRT. If you do everything in this tutorial: openWRT on GL.Inet MT6000, you can easily add pihole support to both ipv4 and ipv6. Below, please find pics of the pihole custom DNS, and ipv4 and ipv6 settings for pihole in openWRT:
Okay, that concludes the steps for setting up pihole+unbound within an openWRT environment. However, one might also want to leverage unbound for public-facing machines. For those use-cases, I enter the following config in /etc/unbound/unbound.conf
:
server: # Bind to localhost only interface: 127.0.0.1 interface: ::1 port: 53 do-ip4: yes do-ip6: yes prefer-ip6: yes access-control: 127.0.0.0/8 allow access-control: 0.0.0.0/0 refuse access-control: ::0/0 refuse # Optimize for 8 cores num-threads: 4 msg-cache-slabs: 4 rrset-cache-slabs: 4 infra-cache-slabs: 4 key-cache-slabs: 4 # Cache settings for high query volume cache-max-ttl: 86400 cache-min-ttl: 3600 rrset-cache-size: 128m msg-cache-size: 64m key-cache-size: 32m neg-cache-size: 8m # Enable prefetch and expired responses prefetch: yes prefetch-key: yes serve-expired: yes serve-expired-ttl: 3600 # DNSSEC validation for DANE #do-dnssec: yes harden-dnssec-stripped: yes harden-referral-path: yes harden-below-nxdomain: yes harden-algo-downgrade: no # Performance tweaks #so-rcvbuf: 4m #so-sndbuf: 4m edns-buffer-size: 1232 outgoing-range: 4096 num-queries-per-thread: 1024 jostle-timeout: 200 #low-resolver-mem: no # Logging (minimal) verbosity: 1 log-queries: no log-replies: no use-syslog: yes # Security and privacy hide-identity: yes hide-version: yes use-caps-for-id: yes qname-minimisation: yes harden-large-queries: yes harden-glue: yes aggressive-nsec: yes # Protocol settings do-tcp: yes do-udp: yes # Enable full recursion - no longer needed, retained for history # do-not-query-localhost: no # root-hints: "/usr/share/dns/root.hints" # Disable subnetcache module-config: "validator iterator" # Forward to upstream resolvers # forward-zone: # name: "." # forward-addr: 1.1.1.1 # Cloudflare # forward-addr: 8.8.8.8 # Google
After that, I navigate to /etc/resolv.conf
and enter the following:
nameserver ::1 nameserver 127.0.0.1
And, as we already discussed, if you are using unbound without a pihole per se, you would simply adapt the lan-side configuration above and tweak where necessary.
— oemb1905 2025/09/20 18:31