For some time now I've had a setup with OpenVPN that provided connectivity back to my house and allowed me to optionally send my internet traffic through the VPN tunnel and my house. Wireguard is an interesting project that provides a simplified peer-to-peer VPN tunnel capability that I've been interested in trying out. Pi-Hole is a project that provides "network wide ad-blocking" by providing a caching DNS server and blocklists.
There's a few different ways to configure clients to use pi-hole once you stand one up. I opted to point specific clients in my house – my iPhone, laptops, etc – to use the pi-hole caching DNS server. For the upstream DNS I use CloudFlare's 1.1.1.1 DNS services. I haven't yet configured DNS over https with the pi-hole, but probably will at a later date. I decided to manually configure client wifi configurations because my wife wasn't a big fan of just how much ad-blocking the Pi-hole does. Over time I've added whitelist entries that suit me and tuned the lists substantially. I've got a fair number of lists added in addition to the default:
I've got a little Intel NUC running at the house with a version of Alpine Linux
installed as the OS. So I opted for the docker install of pi-hole. With
docker-compose
that's simple enough:
version: "3"
# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "6767:6767/udp"
- "80:80/tcp"
- "443:443/tcp"
environment:
TZ: 'America/Chicago'
WEBPASSWORD: '<a good password>'
DNS1: '1.1.1.1'
DNS2: '1.0.0.1'
# Volumes store your data between container upgrades
volumes:
- './etc-pihole/:/etc/pihole/'
- './etc-dnsmasq.d/:/etc/dnsmasq.d/'
dns:
- 127.0.0.1
- 1.1.1.1
# Recommended but not required (DHCP needs NET_ADMIN)
# https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
cap_add:
- NET_ADMIN
restart: unless-stopped
With a docker-compose up
the pi-hole is up and running. For my clients when
I'm on my home wifi network, I override the DNS servers provided by DHCP
manually to point to my internal server running pi-hole. In addition to the
pi-hole website, the pi-hole subreddit proved valuable with identifying
additional blocklists and useful regexes as well.
When I'm remote I'd also like to benefit from the pi-hole blocking which requires a running VPN, For this I installed wireguard on my laptops and iphone. A MacOS wireguard client is available for that platform. I also have the wireguard "server" installed on the same NUC as the pi-hole. My wifi network router passes the appropriate NATted port I chose for wireguard back to the NUC to handle.
Installing wireguard on the NUC requires a little more effort than then clients.
There are several tutorials but I found this one to be the most useful. Alpine
didn't have a wireguard APK so I built it from source which does mean every time
I get a kernel update on Alpine I have to rebuild it. Also, I needed to make
sure I enabled ip forwarding. With that I generated the necessary keys for all
hosts on my NUC. I distributed the relevant private keys/configurations to my
iphone and laptops following the wireguard docs. I also needed to have
wg-quick.sh
set up some firewall rules and a small subnet, so that's shown in
the configuration..
The wireguard /etc/wireguard/wg0.conf
on my NUC looks like this:
[Interface]
Address = 10.23.5.1/24
ListenPort = 1500
PrivateKey = <NUCprivkey>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o wlan0 -j MASQUERADE
# macbook
[Peer]
PublicKey = <macpubkey>
AllowedIPs = 10.23.5.2/32
# Mobile
[Peer]
PublicKey = <iphonepubkey>
AllowedIPs = 10.23.5.3/32
with a wg-quick up wg0
I have an at the ready wireguard setup. On the client
side, the laptop looks like this:
[Interface]
PrivateKey = <macprivkey>
Address = 10.23.5.2/24
DNS = 192.168.86.103
[Peer]
PublicKey = <nucpubkey>
Endpoint = <myhousepublicDNS>:1500
AllowedIPs = 0.0.0.0/0
The Endpoint
above points to the public DNS name I have for my home network
and NATtd UDP port. The DNS
entry routes DNS to the pi-hole and the
AllowedIPs
makes it so the default route passes through the wireguard VPN. It
is also possible to do a split-tunneling configuration where only DNS and local
network traffic is passed to the VPN. The iptables
rules in the NUC's config
for PostUp
and PostDown
are stood up and torn down by the wg-quick
script.
Alpine Linux doesn't use systemd. The simplified init system has a facility
to start local scripts on boot by placing them in /etc/local.d
like so:
huskerdu:/etc/local.d# cat wg-quick.start
/usr/bin/wg-quick up wg0
huskerdu:/etc/local.d# cat wg-quick.stop
/usr/bin/wg-quick down wg0
With that, the pi-hole also starts on boot due to the docker-compose
configuration. So while I am remote I can still get the benefits of pi-hole and
malware blocklists. I've found that routing my default gateway through my home
doesn't add any significant performance issues in most cases. In fact the pi-hole
has a side benefit of improving some web page loads because it eliminates any
attempt to load blocked ad content. I simply turn on wireguard on my laptop and
iphone with the configuration files I built installed on each. One of the nice
things about wireguard is that it acts in a stateless manner and follows me from
wifi networks to LTE and back without issue. I don't have to stop and restart
when I change networks so it's just running and I'm VPNed and getting the
pi-hole benefit nearly all the time.
I do have to watch for wifi neworks at airports and the like that require a splash page to login as they initially require their own DNS to pull up that page. It's a simple matter of turning off the wireguard connection temporarily, connecting to wifi, and firing back up after authorizing through the splash page to resolve that.