The Pi-hole documentation provides an excellent guide to install Wireguard VPN to allow use of Pi-hole outside of a local network and an equally excellent guide to install Unbound as a recursive DNS server. However, one issue I ran into when implementing Wireguard with a previously working Unbound implementation according to the guides was that Unbound stopped responding to DNS requests.
To solve the issue, try adding a line access-control: [local network subnet] allow into the file /etc/unbound/unbound.conf.d/pi-hole.conf and restarting unbound with sudo /etc/init.d/unbound restart . For example, if your local network hosting Pi-hole is 192.168.1.0/24, add access-control: 192.168.1.0/24 allow.
You can edit the documentation files to add anything that was missed or could be updated, if you are so inclined. The documentation will be seen by far more users than just a note here on Discourse.
Blockhead, you just saved me a lot of headaches! I could not for the life of me figure out why enabling the masquerade rules seemed to break unbound, and this fixed the issue immediately. I hope your PR for the changes to the docs gets merged soon!
(I'm only reading this now, upon nickclyde's reply:)
This should not be required at all.
If you followed our guide, unbound can be expected to only ever receive DNS requests from Pi-hole via 127.0.0.1.
If your unbound would have to accept additional IP ranges, you may be routing DNS requests from your Wireguard network directly to unbound instead of Pi-hole.
You should verify your PostUp/PostDown rules.
And on another thought:
You wouldn't run unbound and/or Pi-hole as a Docker container, would you?
Thanks. This was a while ago and
alas, I'm not at all at the level of your understanding. I'll tell you what I remember and hopefully that will help you sort it out.
I was running Pi-hole on a Win11 hyper-V VM and wanted Wireguard. I recall the Wireguard guide leaving some things out, like not having ufw rules for example. So, I tried to find things that worked. Then, I ran into the nonrouting problem and somehow solved it, possibly with the idea being discussed.
The good news is that I put every change I made to the Wireguard documentation (at the time) to make my system work into the pull request. So if there's something wonky in what I did, it should be there to see. Happy to learn how it could be improved.
When following our guide, there is no direct communication between a client and unbound:
Any client - regardless whether connection via Wireguard or directly - should be talking to Pi-hole for DNS, and Pi-hole will then filter allowed DNS requests only to be forwarded to unbound on 127.0.0.1:5335.
Where did you install unbound then?
Our guide provides instructions on how to run unboundon the same machine as Pi-hole.
By shunning Pi-hole into a VM, you would effectively run Pi-hole and unbound on different machines, even if that machine is only virtual (unless you would install unbound on the very same VM as Pi-hole).
In such a scenario, instead of allowing 127.0.0.1, configuring unbound to accept DNS requests from your Pi-hole's IP address would be required to closely match the original configuration.
However, that requirement would be completely independent of Wireguard.
To objectively assess your solution approach, I think it would be required to also know how you have installed and configured both Pi-hole and unbound.
Weird, I'm pretty sure I'm following a pretty buck standard setup - I just flashed Raspberry Pi OS on my Raspberry Pi 4, installed pihole, installed unbound following the guide in the docs exactly, then set up wireguard following the guide in the docs exactly. It worked perfectly, until I tried the guide to make internal network devices accessible via the VPN. As soon as I added the nftables masquerade rules to my wireguard conf and restarted wireguard, DNS resolution just broke. Adding the access-control line to my unbound conf fixed it!
If they all run on the same VM, then 127.0.0.1 should be sufficient.
So there's a difference to my working installation, as I've used the iptables rules.
If you did configure Pi-hole correctly, and did verify that Pi-hole and unbound would work together before bringing Wireguard to the field, then that could suggest that your nftables rules would intercept DNS requests originating from 127.0.0.1.
Could both of you share a debug token, and also your PostUp/Postdown rules?
For the latter, e.g.:
Your debug log shows you've pointed Pi-hole correctly to 127.0.0.1#5335 as upstream, and there are no stray custom dnsmasq configurations that could potentially interfere.
However, it shows that your FTL.log contains quite a few recent warnings when contacting unbound, like:
2024-09-09 09:25:43.055 EDT [474762/F391681] WARNING: Connection error (127.0.0.1#5335): failed to send TCP(read_write) packet (Connection prematurely closed by remote server)
I'm not yet sure whether that's significant for our analysis, but let's keep those in mind to return to later eventually.
Meanwhile, the obvious difference between your PostUp lines and those from our guide is that yours omits the escaping (\) before the semicolon (;) if that appears within brackets, e.g. yours reads "...policy accept;}..." where the guide has "...policy accept\;}...".
To preclude that those are not just formatting or copy&paste artifacts, could you please share your current nftables ruleset:
sudo nft list ruleset
As you are using ufw, this is probably going to be rather copious, so instead of pasting the contents here, you may also try to upload it to our servers and share its token:
Note, this debug log was generated after I added the access-control line to my unbound conf, and DNS resolution via the VPN is working. I'm happy to generate another log without that line, if it's helpful.
My PostUp and PostDown rules were just copy/pasted from the guide in the docs:
As with Blockhead, your debug log shows you've pointed your Pi-hole v5 correctly to 127.0.0.1#5335 as upstream, and there are no stray custom dnsmasq configurations that could potentially interfere.
Unrelated to the issue, your router distributes `1.1.1.1` as DNS server:
*** [ DIAGNOSING ]: Discovering active DHCP servers (takes 10 seconds)
Scanning all your interfaces for DHCP servers
* Received 305 bytes from eth0:192.168.1.1
Offered IP address: 192.168.1.109
DHCP options:
Message type: DHCPOFFER (2)
router: 192.168.1.1
dns-server: 1.1.1.1
DHCP clients won't use Pi-hole, unless you've manually pointed a client to use Pi-hole, which your debug log suggests you have done for at least some clients.
Blockheads' nft ruleset correctly lists the wireguard tables, so the differences were likely from pasting only.
nickclyde , are you using ufw as well?
Could you also share your nft ruleset?
In the meantime, I've installed Pi-hole and unbound on RPi OS 12/bookworm on a spare Zero, and had no issues when adding the recommended nftables rules.
The resulting ruleset is much smaller than @Blockhead's (click for details)
Next, I tried to apply Blockhead's ruleset to my configuration.
However, nft complained about quite a few unexpected keywords, mostly because a type wasn't declared.
I've turned those lines into comments (more):
210:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
211:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
212:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 0 bytes 0 accept
213:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 0 bytes 0 accept
214:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 0 bytes 0 accept
215:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 0 bytes 0 accept
216:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
217:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
218:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type ip6 hoplimit 1 counter packets 0 bytes 0 accept
219:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type ip6 hoplimit 1 counter packets 0 bytes 0 accept
220:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type ip6 hoplimit 1 counter packets 0 bytes 0 accept
221:# meta l4proto ipv6-icmp icmpv6 type counter packets 0 bytes 0 accept
222:# meta l4proto ipv6-icmp icmpv6 type counter packets 0 bytes 0 accept
223:# meta l4proto ipv6-icmp icmpv6 type counter packets 0 bytes 0 accept
224:# meta l4proto ipv6-icmp icmpv6 type counter packets 0 bytes 0 accept
245:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
246:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
247:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 0 bytes 0 accept
248:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 0 bytes 0 accept
249:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 0 bytes 0 accept
250:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type counter packets 7 bytes 612 accept
251:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
252:# meta l4proto ipv6-icmp icmpv6 type ip6 hoplimit 255 counter packets 0 bytes 0 accept
253:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type ip6 hoplimit 1 counter packets 0 bytes 0 accept
254:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type ip6 hoplimit 1 counter packets 0 bytes 0 accept
255:# meta l4proto ipv6-icmp ip6 saddr fe80::/10 icmpv6 type ip6 hoplimit 1 counter packets 0 bytes 0 accept
Applying the resulting ruleset didn't negatively impact DNS resolution:
I was able to dig @192.168.0.53 heise.de as well as dig @10.100.0.1 heise.de and dig -p 5335 @127.0.1.1 pi-hole.net successfully on the Zero.
Thus, I cannot recreate your observation of failing DNS when appyling nftables rules.
I commented out the access-control line and the error occurred.
Here's a pihole -d token with the comment: EG27vSLl
Oddly, the debug log looks like pihole is able to resolve addresses on the VM, but if I try to use a browser on a computer on the network, I get no resolution. Also, if I dig @ the local address on the VM, I get a network timeout:
$ dig @192.168.1.150 cnn.com
;; communications error to 192.168.1.150#53: timed out
;; communications error to 192.168.1.150#53: timed out
;; communications error to 192.168.1.150#53: timed out
; <<>> DiG 9.18.28-0ubuntu0.22.04.1-Ubuntu <<>> @192.168.1.150 cnn.com
; (1 server found)
;; global options: +cmd
;; no servers could be reached
Alternatively, if I re-enable the access-control, everything is happy with the local VM digging:
Yeah, I had to disable network-wide Pihole due to complaints from the wife about broken sites So I'm just using the Pihole on my laptop and phone via Wireguard.
I am not using ufw - the Rpi is behind NAT, so I'm fine with no firewall.
That could indeed happen if unbound would be receiving requests with a source IP that doesn't match its configured interface.
In turn, that would suggest that ntftables would source-NAT requests from the loopback interface.
The remedy would then be to apply srcnat masquerading to just those inbound and outbound interfaces that involve wireguard (which was always the case with iptables).
Of course, wireguard's interface would be the inbound one, and judging by your debug logs, your outbound interface would be eth0 for both nickclyde and @Blockhead.
Please try the following (while at home, connected directly to your home network):
a. bring down your Wireguard interface:
sudo wg-quick down wg0
b. change your Wireguard's PostUp rules:
sudo nano /etc/wireguard.conf
by replacing your PostUp with the folllowing rules:
In particular, verify that %i has been correctly replaced by your wireguard's interface name.
e. run a few test lookups to your different IP ranges:
-- to your local unbound
dig -p 5335 @127.0.0.1 pi-hole.net
-- to your Pi-hole's home network IP address
dig @<pi.ho.le.ip> pi-hole.net
-- to your Pi-hole's wireguard IP address
dig @<wg.pi.ho.le> pi-hole.net
If that doesn't work straight away, please consider a reboot, and report back whether that would allow Pi-hole/unbound/Wireguard to work for you without expanding unbound's access-control.
That works, both with and without the access-control for all three digs. Can you take on making the edit to the pull-request, if warranted? (It might take me a while to relearn how to do it, and I suspect all my credentials expired.)