In my setup, Unbound 1.26.1 was sending its queries to the root servers with the RD (Recursion Desired) flag set to 0. The root servers were returning REFUSED to those non-recursive queries. Unbound would then try multiple root servers, classify the responses as THROWAWAY, eventually reach 33 attempts, and return SERVFAIL.
I confirmed this by testing the root server directly with dig. A non-recursive query (RD=0) returned REFUSED, while the same query with recursion requested (RD=1) returned NOERROR with the root NS records.
I then downloaded a fresh copy of the Unbound 1.26.1 source, rather than modifying the source I had already experimented with. In iterator.c, around line 3098, I changed:
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
to:
iq->chase_flags | BIT_RD,
This forces the RD flag on when Unbound sends the query.
I compiled the modified source and installed it. Because the custom-compiled Unbound binary did not support systemd’s notification mechanism, I also had to change the Unbound systemd service from:
Type=notify
to:
Type=simple
After that change, the Unbound service started normally.
After restarting Unbound, the same test:
dig @127.0.0.1 -p 5335 iana.org
changed from:
status: SERVFAIL
to:
status: NOERROR
with an A record returned for iana.org.
I then tested normal Pi-hole DNS traffic. The Pi-hole log showed the request being forwarded to Unbound and successfully receiving the CNAME and A/AAAA records:
2026-09-27 19:17:21.067 forwarded accounts.youtube.com to 127.0.0.1#5335
2026-09-27 19:17:21.088 reply accounts.youtube.com is <CNAME>
2026-09-27 19:17:21.088 reply www3.l.google.com is 74.125.136.139
2026-09-27 19:17:21.088 reply www3.l.google.com is 74.125.136.138
2026-09-27 19:17:21.088 reply www3.l.google.com is 74.125.136.100
2026-09-27 19:17:21.088 reply www3.l.google.com is 74.125.136.101
2026-09-27 19:17:21.088 reply www3.l.google.com is 74.125.136.102
2026-09-27 19:17:21.088 reply www3.l.google.com is 74.125.136.113
It also returned the IPv6 addresses:
2026-09-27 19:17:21.091 reply www3.l.google.com is 2607:f8b0:4002:c00::8b
2026-09-27 19:17:21.091 reply www3.l.google.com is 2607:f8b0:4002:c00::66
2026-09-27 19:17:21.091 reply www3.l.google.com is 2607:f8b0:4002:c00::65
2026-09-27 19:17:21.091 reply www3.l.google.com is 2607:f8b0:4002:c00::64
And Pi-hole subsequently queried:
2026-09-27 19:17:21.095 query[HTTPS] www3.l.google.com from 10.10.1.16
So normal DNS resolution is now working through Pi-hole → Unbound.
I also tested the setup with NordVPN/Wireguard, and Mullvad, so the issue wasn’t limited to one particular VPN provider.
In my case, forcing RD=1 on the outbound Unbound query fixed the problem. The additional systemd service change from notify to simple was necessary to run the custom-compiled Unbound binary.
::