Wireguard and pi-hole

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:

pi-hole screenshot

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.

 Share!

 
comments powered by Disqus