PiHole + Unbound + Wireguard - DNS not working

The issue I am facing:
I have PiHole and Unbound working successfully, but when I use Wireguard under this same configuration, DNS queries do not resolve. Direct IP addresses work and result in successful web page load (such as browsing to 1.1.1.1). Testing performed from both inside and outside my LAN, same results.

Details about my system:
Raspberry Pi 3, current PiHole, Unbound and Wireguard, testing via Wireguard iOS client
Current debug log: XXE41VzO
What I have changed since installing Pi-hole:
I have configured using GitHub - notasausage/pi-hole-unbound-wireguard: Turning your Raspberry Pi into an ad-blocking VPN with built-in DNS resolution using Pi-Hole, Unbound & WireGuard. as the primary guide. I have used ONLY info in this guide modified by me for PiVPN, and I have also tried using IPTABLES suggestions from pi-hole.net's docs online. None of these appear to have made a difference. From my monitoring the log files in unbound, I do not see the domain query from a Wireguard peer until I deactivate the Wireguard client on the querying device. It's as the the DNS query isn't going anywhere.

My problem appears to be very similar to Pi-Hole + Unbound + Wireguard: Home network access but no DNS - Help / Community Help - Pi-hole Userspace, but I am still stuck.

DNS queries work as expected if I use Cloudflare or Quad9 as my specified DNS in Wireguard's configuration files. They do not work if DNS is listed as 192.168.1.200 (PiHole static address) or 10.6.0.1 (Wireguard "server" address, which is the same physical device as the PiHole).

**Edited to include updated debug log token and move to Help forum.

1 Like
sudo echo "DELAY_STARTUP=5" >> /etc/pihole/pihole-FTL.conf

Restart your Pi and DNS should start working fine.
That was the root cause behind DNS issues and also the post you tagged.
The above delays the DNS start allowing the wg interface to start, otherwise, the VPN starts before the DNS service.

Keep in mind that I set all the traffic is via the VPN.

[Peer]
AllowedIPs = 0.0.0.0/0, ::/0

If you followed the official guide, everything else should be covered.

Two more critical details that can mess things up

It took me ages to find this out, if set to true, it expects you do stop the service FIRST before making changes, otherwise, no changes are kept.
Pi-Hole official guide didn't explain that, it just appeared in the guide. The last time I checked, they removed it.

SaveConfig = true

Since that post you tagged, I have virtualized everything with Proxmox (OPNSense, Pi-Hole + Unbound, WireGuard).

WireGuard now has its own Debian11 mini server and I couldn't get it to work coz I forgot 2 critical steps in my Ansible playbook.

  1. I forgot to enable net.ipv4.ip_forward=1
  2. wg0.conf iptables rules had the wrong network interface. It had the default eth0 instead of ens18

This is my Ansible playbook to set WireGuard VPN server and add a single client.

  1. PUBLIC_IP_ADDRESS is my public IP Address. I do not wanna leave this info in my git. No critical info is kep here
  2. qrencode -t ansiutf8 -r "/etc/wireguard/note10plus.conf" it generates a QR code that can be scanned by the Android WireGuard app so need to copy files over, etc.
  3. Set network setting the VM with static IP address
# run with ansible-playbook wireguard.yml -i hosts --extra-vars "PUBLIC_IP_ADDRESS=" --ask-become
# qrencode -t ansiutf8 -r "/etc/wireguard/note10plus.conf"
---
- hosts: home
  become_user: root
  become: yes

# ADD YOUR CLIENT HOSTNAME HERE
  vars:
    client_profile: note10plus
    wireguard_config_path: /etc/wireguard/
    hostname: WG01

  tasks:
  - name: Update the repository cache and install packages
    apt:
     state: latest
     update_cache: yes
     name: 
     - qrencode
     - wireguard
     - wireguard-tools
     - iptables

  - name: Set server wg0.conf config
    copy:
      force: no
      dest: "{{ wireguard_config_path }}/wg0.conf"
      content: |
        [Interface]
        Address = 10.100.0.1/24
        SaveConfig = false
        PostUp = iptables -w -t nat -A POSTROUTING -o ens18 -j MASQUERADE; ip6tables -w -t nat -A POSTROUTING -o ens18 -j MASQUERADE
        PostDown = iptables -w -t nat -D POSTROUTING -o ens18 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o ens18 -j MASQUERADE
        ListenPort = 47111
        PrivateKey = REPLACE_PrivateKey_REPLACE

        [Peer]
        AllowedIPs = 10.100.0.2/32
        PublicKey = REPLACE_PublicKey_REPLACE
        PresharedKey = REPLACE_PresharedKey_REPLACE

  - name: Set client config
    copy:
      force: no
      dest: "{{ wireguard_config_path }}/{{ client_profile }}.conf"
      content: |
        [Interface]
        Address = 10.100.0.2/32
        DNS = 192.168.1.3
        PrivateKey = REPLACE_PrivateKey_REPLACE

        [Peer]
        AllowedIPs = 0.0.0.0/0, ::/0
        Endpoint = {{ PUBLIC_IP_ADDRESS }}:47111
        PresharedKey = REPLACE_PresharedKey_REPLACE
        PublicKey = REPLACE_PublicKey_REPLACE

  - name: Generate certificates and merge into configuration.
    shell: "{{ item.cmd }}"
    args:
      creates: "{{ item.creates | d(omit) }}"
      chdir: "{{ wireguard_config_path }}"
      warn: false
    loop:
    - cmd: wg genpsk > {{ client_profile }}.psk
      creates: "{{ client_profile }}.psk"
    - cmd: wg genkey | tee server.key | wg pubkey > server.pub
      creates: "server.key"
    - cmd: wg genkey | tee {{ client_profile }}.key | wg pubkey > {{ client_profile }}.pub
      creates: "{{ client_profile }}.key"
    - cmd: sed -i -e "s#REPLACE_PresharedKey_REPLACE#$(cat {{ client_profile }}.psk)#" wg0.conf
    - cmd: sed -i -e "s#REPLACE_PrivateKey_REPLACE#$(cat server.key)#" wg0.conf
    - cmd: sed -i -e "s#REPLACE_PublicKey_REPLACE#$(cat {{ client_profile }}.pub)#" wg0.conf
    - cmd: sed -i -e "s#REPLACE_PresharedKey_REPLACE#$(cat {{ client_profile }}.psk)#" {{ client_profile }}.conf
    - cmd: sed -i -e "s#REPLACE_PrivateKey_REPLACE#$(cat {{ client_profile }}.key)#" {{ client_profile }}.conf
    - cmd: sed -i -e "s#REPLACE_PublicKey_REPLACE#$(cat server.pub)#" {{ client_profile }}.conf

  - name: Start and enable WireGuard
    service: 
     name: wg-quick@wg0
     state: started
     enabled: yes

# Delete the current network
# Use 'ip link show' if you messed up to identify the right card

  - name: Set network
    copy:
      force: yes
      dest: /etc/network/interfaces
      content: |
        source /etc/network/interfaces.d/*

        auto lo
        iface lo inet loopback

        #auto ens18
        #iface ens18 inet dhcp
        #iface ens18 inet6 auto
        auto ens18
        iface ens18 inet static
        address 192.168.1.51
        netmask 255.255.255.0
        gateway 192.168.1.2


  - name: Set hostname packet forwarding and locales
    shell: "{{ item }}"
    with_items:
     - sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
     - sed -i 's/#net.ipv6.conf.all.forwarding=1/net.ipv6.conf.all.forwarding=1/' /etc/sysctl.conf
     - sudo update-locale LANG=en_AU.UTF-8
     - sudo dpkg-reconfigure --frontend noninteractive locales
     - echo {{ hostname }} > /etc/hostname
    args:
     warn: false

  - name: Restart server
    command: /sbin/shutdown -r +1
    async: 0
    poll: 0
    ignore_errors: true

To add a new client.
I setup everything yesterday, both playbooks are working 100%
Change as needed.

# run with ansible-playbook wg0_add_client.yml -i hosts --extra-vars "PUBLIC_IP_ADDRESS= CLIENT_HERE=" --ask-become
# qrencode -t ansiutf8 -r "/etc/wireguard/note10plus.conf"
# to remove peer: wg set wg0 peer $(cat /etc/wireguard/note10plus.pub) remove
---
- hosts: home
  become_user: root
  become: yes

# ADD YOUR CLIENT HOSTNAME HERE
  vars:
    client_profile: "{{ CLIENT_HERE }}"
    wireguard_config_path: /etc/wireguard/

  tasks:
  - name: Set client config
    copy:
      force: no
      dest: "{{ wireguard_config_path }}/{{ client_profile }}.conf"
      content: |
        [Interface]
        Address = 10.100.0.3/32
        DNS = 192.168.1.3
        PrivateKey = REPLACE_PrivateKey_REPLACE

        [Peer]
        AllowedIPs = 0.0.0.0/0, ::/0
        Endpoint = {{ PUBLIC_IP_ADDRESS }}:47111
        PresharedKey = REPLACE_PresharedKey_REPLACE
        PublicKey = REPLACE_PublicKey_REPLACE

  - name: Generate certificates and merge into configuration.
    shell: "{{ item.cmd }}"
    args:
      creates: "{{ item.creates | d(omit) }}"
      chdir: "{{ wireguard_config_path }}"
      warn: false
    loop:
    - cmd: wg genpsk > {{ client_profile }}.psk
      creates: "{{ client_profile }}.psk"
    - cmd: wg genkey | tee {{ client_profile }}.key | wg pubkey > {{ client_profile }}.pub
      creates: "{{ client_profile }}.key"
    - cmd: sed -i -e "s#REPLACE_PresharedKey_REPLACE#$(cat {{ client_profile }}.psk)#" {{ client_profile }}.conf
    - cmd: sed -i -e "s#REPLACE_PrivateKey_REPLACE#$(cat {{ client_profile }}.key)#" {{ client_profile }}.conf
    - cmd: sed -i -e "s#REPLACE_PublicKey_REPLACE#$(cat server.pub)#" {{ client_profile }}.conf

  - name: Generate certificates and merge into configuration
    shell: "{{ item }}"
    with_items:
     - echo "\n[Peer]" >> "{{ wireguard_config_path }}/wg0.conf"
     - echo "AllowedIPs = 10.100.0.3/32" >> "{{ wireguard_config_path }}/wg0.conf"
     - echo "PublicKey = $(cat {{ wireguard_config_path }}{{ client_profile }}.pub)" >> "{{ wireguard_config_path }}/wg0.conf"
     - echo "PresharedKey = $(cat {{ wireguard_config_path }}{{ client_profile }}.psk)" >> "{{ wireguard_config_path }}/wg0.conf"

  - name: Start and enable WireGuard
    service: 
     name: wg-quick@wg0
     state: reloaded
     enabled: yes
        

Thanks for the responses.

I already had "DELAY_STARTUP=5" in /etc/pihole/pihole-FTL.conf when I put in my original message. I also tried adding the SaveConfig = False to the wg0.conf file, and rebooted the RPI. The initially reported issue persists. I have verified net.ipv4.ip_forward=1, and this was the case for several days now.

| Whisky
March 13 |

  • | - |

Two more critical details that can mess things up

It took me ages to find this out, if set to true, it expects you do stop the service FIRST before making changes, otherwise, no changes are kept.
Pi-Hole official guide didn't explain that, it just appeared in the guide. The last time I checked, they removed it.

SaveConfig = true

Since that post you tagged, I have virtualized everything with Proxmox (OPNSense, Pi-Hole + Unbound, WireGuard).

WireGuard now has its own Debian11 mini server and I couldn't get it to work coz I forgot 2 critical steps in my Ansible playbook.

  1. I forgot to enable net.ipv4.ip_forward=1
  2. wg0.conf iptables rules had the wrong network interface. It had the default eth0 instead of ens18

This is my Ansible playbook to set WireGuard VPN server and add a single client.

  1. PUBLIC_IP_ADDRESS is my public IP Address. I do not wanna leave this info in my git. No critical info is kep here
  2. qrencode -t ansiutf8 -r "/etc/wireguard/note10plus.conf" it generates a QR code that can be scanned by the Android WireGuard app so need to copy files over, etc.
  3. Set network setting the VM with static IP address
# run with ansible-playbook wireguard.yml -i hosts --extra-vars "PUBLIC_IP_ADDRESS=" --ask-become
# qrencode -t ansiutf8 -r "/etc/wireguard/note10plus.conf"

Have you checked the iptables rule?
I was running Pi-Hole + Unbound + WireGuard from in a Debian 11 image instead of the usual Raspberry OS.
Iptables wasn't installed so the rules wouldn't be applied messing everything else.

Okay I got the following from "iptables -S":

-P INPUT ACCEPT

-P FORWARD ACCEPT

-P OUTPUT ACCEPT

-A FORWARD -d 10.6.0.0/24 -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment wireguard-forward-rule -j ACCEPT

-A FORWARD -s 10.6.0.0/24 -i wg0 -o eth0 -m comment --comment wireguard-forward-rule -j ACCEPT

-A FORWARD -i wg0 -j ACCEPT

-A FORWARD -o wg0 -j ACCEPT

-A FORWARD -i wg0 -j ACCEPT

-A FORWARD -o wg0 -j ACCEPT

-A FORWARD -i wg0 -j ACCEPT

-A FORWARD -o wg0 -j ACCEPT

This is exactly the reason why we removed it .

I found the answer, finally!

https://www.reddit.com/r/WireGuard/comments/cd8ouo/wireguard_not_using_pihole_for_dns/ gave me the idea to edit the /etc/dnsmasq.d/02-pivpn.conf file to add

interface=wg0

I did that, restarted Wireguard via wgquick down wg0 followed by wgquick up wg0, then ran pihole restartdns. No idea if all those steps were necessary.

Now my Wireguard connections are resolving DNS. Also confirmed no "leaks" via dnsleak.com.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.