How to extend your Pi-Hole Ad protection beyond your own LAN
Explore how to extend Pi-Hole ad protection beyond home, leverage WireGuard VPN for mobile device management, & set up Docker-based network security.
The Problem
As my kids have grown, I’ve found that I no longer require the parental controls offered by Circle. In fact, Circle has increasingly become a bottleneck in my environment. However, I still want to provide the benefits of privacy, ad blocking, and generalized filtering that my Pi-Hole offers. Previously, with Circle, all mobile phones were routed back through a VPN tunnel to our home’s main LAN to enforce parental controls. This worked seamlessly, whether we were using LTE, Wi-Fi networks outside of our home, or anything in between. I now needed to recreate this solution that I was receiving from the Circle device.
My search for a suitable solution led me into the complex world of Mobile Device Management (MDM) and Virtual Private Networks (VPNs). Unfortunately, I couldn’t find a cost-effective MDM solution for families, particularly since we use iPhones, which require an Apple Certificate to manage (this involves annual costs). Therefore, a VPN seemed like my only viable option.
Functionally, I wanted a very simple solution that would work like this:
Regardless of the user’s location, they would benefit from PiHole’s protection, including ad-blocking, malware prevention, and phishing protection.
WireGuard VPN
After much research, I discovered WireGuard VPN, a free, open-source solution that conveniently comes in a Docker container. Since my entire infrastructure is Docker-based, this seemed like the perfect fit.
Digging deeper into WireGuard, I stumbled upon another project called WireGuard Easy. This provided the lightweight CLI VPN with a user-friendly interface for adding clients and tracking usage.
By employing a working WireGuard solution, I could install the client on all mobile endpoints. These would connect back to my server instance on my Docker container, with WireGuard directing all endpoints to use the PiHole on my local LAN for comprehensive adware/malware protection.
A critical aspect that made this process smooth was iOS’s On Demand VPN functionality. I could set up each WireGuard Client to activate or deactivate protection based on whether the device was connected to our home’s internal SSIDs. As soon as a device left our Wi-Fi network, the VPN functionality would kick in. Conversely, upon returning home, the VPN would deactivate, since protection was already locally defined via the DHCP scope.
DHCP and Docker Subnetting
I did encounter a few challenges when configuring the networking for the WireGuard and PiHole containers. I’ll skip detailing the trial and error phase and go straight to my final configuration.
Interestingly, this design does not route ALL traffic through the internal VPN, but only the DNS requests. This offers the desired domain blocking protection for all devices without forcing a throughput bottleneck through WireGuard.
When I moved the PiHole and WireGuard containers to a 172.0.56.x network, I faced a minor hiccup. As my PiHole also serves DHCP addresses to my network, I needed to introduce a DHCP helper to the 192.168.10.x network to forward requests.
The Solution
Here is the Docker-Compose entry for the DHCPHelper. With one line (IP:), you point the container back to your PiHole instance.
dhcphelper:
restart: unless-stopped
container_name: dhcphelper
network_mode: "host"
image: homeall/dhcphelper:latest
environment:
IP: '172.0.56.10'
TZ: America/New_York
cap_add:
- NET_ADMIN
Here is the Docker-Compose entry for my PiHole:
pihole:
container_name: pihole
image: pihole/pihole:latest
environment:
- TZ=America/New_York
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
volumes:
- './etc-pihole:/etc/pihole'
- './etc-dnsmasq.d:/etc/dnsmasq.d'
- /etc/localtime:/etc/localtime:ro
cap_add:
- NET_ADMIN
restart: always
depends_on:
- dhcphelper
networks:
backend:
ipv4_address: '172.0.56.10'
and here is the Docker-Compose entry for the WireGuard Easy container:
wg-easy:
environment:
- WG_HOST=wireguard.fordst.com
- WG_DEFAULT_DNS=172.0.56.10
- WG_DEFAULT_ADDRESS=10.0.0.x
- WG_ALLOWED_IPS=10.0.0.0/24, 172.0.56.10/32
image: weejewel/wg-easy
container_name: wg-easy
volumes:
- ./wireguard:/etc/wireguard
ports:
- 51820:51820/udp
- 51821:51821/tcp
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
depends_on:
- pihole
networks:
backend:
ipv4_address: '172.0.56.20'
The backend network is defined here:
networks:
backend:
ipam:
config:
- subnet: 172.0.56.0/24
In conclusion, the solution I’ve outlined above has served my requirements well. It enables privacy, ad-blocking, and malware protection for my family’s iPhones, whether we’re at home or on the go. It leverages the capabilities of WireGuard VPN, WireGuard Easy, and PiHole in a Docker-based environment, with additional refinement through iOS’s On-Demand VPN functionality.
This solution is currently serving my family and I hope this guide helps those of you searching for a similar solution.
Happy Surfing!
CARLO