Pi-Hole + Openvpn not being used for DNS queries

Expected Behaviour:

Pi-hole should be used for DNS when connected to VPN.

Actual Behaviour:

Pi-hole adminstator interface is accessible through VPN, but Pi-hole is not being used for DNS.

Debug Token:

https://tricorder.pi-hole.net/tzrSRlqc/

My issue is identical with the one in the following post, except that I did not disable logging.

Pi-hole is installed on a VPS, using this guide.
https://docs.pi-hole.net/guides/vpn/openvpn/overview/

The VPN works fine. Pi-hole interface works fine. Pi-hole resolving and blocking works fine when done from the VPS. Pi-hole isn't used at all by clients using the VPN.

Blocking On VPS:

host pi-hole.net 10.8.0.1
Using domain server:
Name: 10.8.0.1
Address: 10.8.0.1#53
Aliases: 
pi-hole.net has address `<public IP redacted>`
pi-hole.net mail is handled by 20 sunfire-relay.mxrouting.net.
pi-hole.net mail is handled by 10 sunfire.mxrouting.net.

I blocked odysee.com to make the following example.

host odysee.com 10.8.0.1
Using domain server:
Name: 10.8.0.1
Address: 10.8.0.1#53
Aliases: 
odysee.com has address 0.0.0.0
odysee.com has IPv6 address ::

OpenVPN server.conf

local XXX.XXX.XXX.XXX
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh.pem
auth SHA512
tls-crypt tc.key
topology subnet
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
ifconfig-pool-persist ipp.txt
push "dhcp-option DNS 10.8.0.1"
#push "dhcp-option DNS 149.112.112.112"
push "block-outside-dns"
keepalive 10 120
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
verb 3
crl-verify crl.pem
explicit-exit-notify

01-pihole.conf

addn-hosts=/etc/pihole/local.list
addn-hosts=/etc/pihole/custom.list
localise-queries
no-resolv
log-queries
log-facility=/var/log/pihole/pihole.log
log-async
cache-size=10000
server=9.9.9.9
server=149.112.112.112
domain-needed
expand-hosts
bogus-priv
local-service

setupVars.conf

PIHOLE_INTERFACE=tun0
QUERY_LOGGING=true
INSTALL_WEB_SERVER=true
INSTALL_WEB_INTERFACE=true
LIGHTTPD_ENABLED=true
CACHE_SIZE=10000
DNS_FQDN_REQUIRED=true
DNS_BOGUS_PRIV=true
DNSMASQ_LISTENING=local
WEBPASSWORD=<redacted>
BLOCKING_ENABLED=true
WEBUIBOXEDLAYOUT=traditional
WEBTHEME=default-dark
DNSSEC=false
REV_SERVER=false
PIHOLE_DNS_1=9.9.9.9
PIHOLE_DNS_2=149.112.112.112

Firewall

This VPS is only used for testing, so I disable the firewall while testing in order to remove as many variables as possible. I should mention I am using UFW to manage the firewall, as the VPS I hope to install Pi-hole on already has other services running on it, and it uses UFW.

iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     udp  --  anywhere             anywhere             udp dpt:openvpn
2    ufw-before-logging-input  all  --  anywhere             anywhere            
3    ufw-before-input  all  --  anywhere             anywhere            
4    ufw-after-input  all  --  anywhere             anywhere            
5    ufw-after-logging-input  all  --  anywhere             anywhere            
6    ufw-reject-input  all  --  anywhere             anywhere            
7    ufw-track-input  all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
2    ACCEPT     all  --  10.8.0.0/24          anywhere            
3    ufw-before-logging-forward  all  --  anywhere             anywhere            
4    ufw-before-forward  all  --  anywhere             anywhere            
5    ufw-after-forward  all  --  anywhere             anywhere            
6    ufw-after-logging-forward  all  --  anywhere             anywhere            
7    ufw-reject-forward  all  --  anywhere             anywhere            
8    ufw-track-forward  all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ufw-before-logging-output  all  --  anywhere             anywhere            
2    ufw-before-output  all  --  anywhere             anywhere            
3    ufw-after-output  all  --  anywhere             anywhere            
4    ufw-after-logging-output  all  --  anywhere             anywhere            
5    ufw-reject-output  all  --  anywhere             anywhere            
6    ufw-track-output  all  --  anywhere             anywhere            

Chain ufw-after-forward (1 references)
num  target     prot opt source               destination         

Chain ufw-after-input (1 references)
num  target     prot opt source               destination         

Chain ufw-after-logging-forward (1 references)
num  target     prot opt source               destination         

Chain ufw-after-logging-input (1 references)
num  target     prot opt source               destination         

Chain ufw-after-logging-output (1 references)
num  target     prot opt source               destination         

Chain ufw-after-output (1 references)
num  target     prot opt source               destination         

Chain ufw-before-forward (1 references)
num  target     prot opt source               destination         

Chain ufw-before-input (1 references)
num  target     prot opt source               destination         

Chain ufw-before-logging-forward (1 references)
num  target     prot opt source               destination         

Chain ufw-before-logging-input (1 references)
num  target     prot opt source               destination         

Chain ufw-before-logging-output (1 references)
num  target     prot opt source               destination         

Chain ufw-before-output (1 references)
num  target     prot opt source               destination         

Chain ufw-reject-forward (1 references)
num  target     prot opt source               destination         

Chain ufw-reject-input (1 references)
num  target     prot opt source               destination         

Chain ufw-reject-output (1 references)
num  target     prot opt source               destination         

Chain ufw-track-forward (1 references)
num  target     prot opt source               destination         

Chain ufw-track-input (1 references)
num  target     prot opt source               destination         

Chain ufw-track-output (1 references)
num  target     prot opt source               destination

Pi-hole settings

Pi-hole DNS setting is „Allow only local requests".
I checked „Pi-hole diagnosis", and there's nothing in there about my requests being blocked.

I don't know what else to do. I've tried restarting from scratch about two dozen times, and have read countless blog and forum posts, leading to no success. Any help would be appreciated. Thank you.

(For your own privacy and safety, you want to be careful about posting sensitive details. I've redacted your public IPs and password hashes from your post.)

Run from an OpenVPN client that is currently connected to your OpenVPN server, what is the output of:

nslookup pi.hole
nslookup flurry.com

Thank you for making the redactions. I looked through for sensitive information, but I must have just overlooked them.

nslookup pi.hole
Server:		127.0.0.53
Address:	127.0.0.53#53

** server can't find pi.hole: NXDOMAIN
nslookup flurry.com
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
Name:	flurry.com
Address: X.X.X.X
Name:	flurry.com
Address: X.X.X.X
Name:	flurry.com
Address: X.X.X.X

Each of the IP addresses returned by „nslookup flurry.com" was different.

(Showing public IPs is generally ok - you just want to be careful about your own public IP addresses.:wink:)

That client is using a stub resolver at 127.0.0.53 on the same device, and that stub resolver in turn was not using Pi-hole as upstream (or else you'd have seen IPs for pi.hole and 0.0.0.0 for flurry.com)

Just to be sure:
Was that client connected to OpenVPN when running those nslookups?

What OS is that client running?
You'd have to investigate which stub resolver that OS is using, and how to configure it to honor your VPNs DNS servers.

Yes, the client was connected through the Linux openvpn CLI, which brings me to the next part, being that I'm running an Linux Mint 21.

I looked into it, and Linux Mint is using systemd-resolved. Based on the information found at the link below I edited resolved.conf, simply adding the DNS line at the bottom (I chose to do this instead of uncommenting and editing the existing DNS line, because it is easier for me to keep track of things in my mind when all my changes are in my own added section.).

/etc/systemd/resolved.conf

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it under the
#  terms of the GNU Lesser General Public License as published by the Free
#  Software Foundation; either version 2.1 of the License, or (at your option)
#  any later version.
#
# Entries in this file show the compile time defaults. Local configuration
# should be created by either modifying this file, or by creating "drop-ins" in
# the resolved.conf.d/ subdirectory. The latter is generally recommended.
# Defaults can be restored by simply deleting this file and all drop-ins.
#
# Use 'systemd-analyze cat-config systemd/resolved.conf' to display the full config.
#
# See resolved.conf(5) for details.

[Resolve]
# Some examples of DNS servers which may be used for DNS= and FallbackDNS=:
# Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com
# Google:     8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google
# Quad9:      9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net
#DNS=
#FallbackDNS=
#Domains=
#DNSSEC=no
#DNSOverTLS=no
#MulticastDNS=no
#LLMNR=no
#Cache=no-negative
#CacheFromLocalhost=no
#DNSStubListener=yes
#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no

#My Changes
DNS=<MY VPS PUBLIC IPV4 ADDRESS>

I should note that my VPS doesn't have an IPV6 address.
The good news is, the VPN is now using my Pi-hole for DNS.
The bad news is that I'm now getting this in the „Pihole diagnosis" section.
„ignoring query from non-local network X.X.X.X (logged only once)"

It seems that Linux Mint went to a fallback DNS after the queries were refused, as the pings I made to different websites still went through, but after a several seconds long delay and after the error message about ignoring the query came up.

It seems that, despite being connected through the VPN, the connection is still not recognized as local.
I had a new debug log made after these changes.
https://tricorder.pi-hole.net/F257SR2J/

In the meantime, I'll keep poking around with a stick.

Okay, I have it working. I just needed to change my bit at the end of the config file.

/etc/systemd/resolved.conf - #My Changes section

#DNS=<MY VPS PUBLIC IPV4 ADDRESS>
DNS=10.8.0.1

I disconnected from my VPN and checked if the internet still worked and DNS still worked. It did. I don't know which DNS server it's using when the VPN is off, though. Everything seems to be working as intended and expected.

This was an interesting learning experience. I only use Linux and BSD, so I'm not familiar with the inner workings of Windows. Windows does not have stub resolvers?

Perhaps I should also add, for people that may face this issue in the future, that after changing /etc/systemd/resolved.conf to restart it with

sudo systemctl restart systemd-resolved

I should also add, for any other UFW users, that my firewall configuration on the VPS is as follows.

ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere                  
53                         ALLOW       Anywhere                  
80/tcp                     ALLOW       Anywhere                  
443                        ALLOW       Anywhere                  
10.8.0.1 53/udp            ALLOW       10.8.0.0/24               
10.8.0.1 53/tcp            ALLOW       10.8.0.0/24               
10.8.0.1 80/tcp            ALLOW       10.8.0.0/24               
53 (v6)                    ALLOW       Anywhere (v6)             
80/tcp (v6)                ALLOW       Anywhere (v6)             
443 (v6)                   ALLOW       Anywhere (v6)

The commands for putting these rules in place can be found here.

If anyone sees a problem in this firewall configuration, please let me know.

I'll add a couple more things.

NGINX Reverse Proxy

Many who will be running Pi-hole on a VPS with other services already running will have some services running on NGINX, and will need a reverse proxy in order for lighttpd to run. The following NGINX entry is working for me so far. I haven't noticed any issues yet. If anyone experiences problems with it, please let me know.

server {
        listen 10.8.0.1;
        #server_name _;

        location / {
                proxy_pass http://127.0.0.1:8080;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Forwarded-Host $http_host;
        }
}

Don't forget in /etc/lighttpd/lighttpd.conf to set

server.port                 = 8080

Pi-hole + Safing's Portmaster

Lastly, for anyone that wants to use Safing's Portmaster together with Pi-hole, the following is working for me.
Add dns://10.8.0.1?&name=WHATEVER_NAME_YOU_WANT&blockedif=zeroip to your DNS Servers list. If you do this, you will not need to do the step involving /etc/systemd/resolved.conf, as Portmaster runs at the kernel level and forces the system to use whatever DNS servers are in its DNS Servers list.

It is important that your Pi-hole DNS is at the top of the list, as this is what Portmaster will default to. If it is not, Portmaster will use whatever is at the top of the list, regardless of how your VPN is configured and what is in your /etc/systemd/resolved.conf file. Thus, your Pi-hole will not be used for DNS when connected to your VPN if your Pi-hole DNS is not at the top of Portmaster's list.

In my experience, disconnecting the VPN caused Portmaster to use the DNS Server that was next in the list, in my case Quad9. Because of this, it will still work even with the VPN disconnected, so long as you have backup DNS servers in Portmaster's DNS Server list.

Hopefully some other people find this useful.

Thank you Bucking_Horn, for helping me solve this.

While that did address your issue, I'd consider that a workaround only.

Your OpenVPN configuration correctly does push "dhcp-option DNS 10.8.0.1", so a client should pick up 10.8.0.1 when connecting to OpenVPN automatically.
Somehow, your systemd-resolved fails to do so.

Manually setting Pi-hole's VPN IPv4 as DNS is a valid option, but I would have expected systemd-resolved to respect DHCP provided DNS resolvers.

That said:
I'd only investgate further if you'd still have issues.
If your workaround works for you, then stick with it. :wink:

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