Skip to content

Optional: Dual operation: LAN & VPN at the same time

Up until now, this wiki has been about a server set up on a cloud host, available on the public Internet. This section is aimed at a server setup in a private network like on a Raspberry Pi.

So if blocking works using eth0 but stops working for tun0, as described here, you may want to run this command pihole -a -i all, which should get the behaviour you want by opening dnsmasq up to listen on all ports. This is not recommended for cloud servers as they should not be listening on eth0.

If you want to set up your Pi-hole + OpenVPN such that you can use from both internal ((W)LAN) and external (VPN) networks, you have to apply some small changes. As additional benefit, you will be able to reach all devices in the internal network (e.g. computers, networking-aware printers, etc.) through the VPN.

This setup assumes that your local network is in the range (i.e. device addresses are in the range of - If this is not the case for you, you have to adjust the settings, accordingly, e.g.

  • devices in - -> route
  • devices in - -> route

Edit your /etc/openvpn/server.conf:

push "route"
push "dhcp-option DNS"

As you can see, we change the address of the DNS server to the local IP address of our Pi-hole (which is in this example).

Afterwards, we change the interface of Pi-hole to eth0 (your local network adapter instead of the VPN adapter tun0). This can conveniently be done by using pihole -r + Reconfigure.

After a restart of the OpenVPN server, all clients should be able to see all devices within your (at home) local network. This is an example running on a distant server, which is connected through the VPN and can successfully communicate with all internal devices:

me@client ~ $ ifconfig
eth0      Link encap:Ethernet  HWaddr e0:xx:xx:xx:xx:xx  
          inet addr:134.x.x.x  Bcast:134.x.x.x  Mask:255.x.x.x
          inet6 addr: X:X:X:X::X/64 Scope:Link
          RX packets:3623911 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2803670 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1921375471 (1.9 GB)  TX bytes:1227835028 (1.2 GB)

lo        Link encap:Local Loopback  
          inet addr:  Mask:
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:553426 errors:0 dropped:0 overruns:0 frame:0
          TX packets:553426 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:113417383 (113.4 MB)  TX bytes:113417383 (113.4 MB)

tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:  P-t-P:  Mask:
          RX packets:274676 errors:0 dropped:0 overruns:0 frame:0
          TX packets:331178 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:43745313 (43.7 MB)  TX bytes:43956250 (43.9 MB)

me@client ~ $ ping
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=18.9 ms
64 bytes from icmp_seq=2 ttl=64 time=18.9 ms
64 bytes from icmp_seq=3 ttl=64 time=18.9 ms
64 bytes from icmp_seq=4 ttl=64 time=18.7 ms
64 bytes from icmp_seq=5 ttl=64 time=18.7 ms
64 bytes from icmp_seq=6 ttl=64 time=19.0 ms
--- ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5007ms
rtt min/avg/max/mdev = 18.740/18.894/19.017/0.189 ms

Important last step

The undocumented pihole -a -i all command is simply what runs when you choose Listen on all interfaces, permit all origins (make sure your Pi-hole is firewalled), which if you've read this far in the tutorial, you should understand that we don't want you to knowingly or unknowing set up an open resolver. screenshot