PiHole + Wireguard Road Warrior Setup

PiHole + Wireguard Road Warrior Setup

I have set up a basic VPN while travelling to prevent tracking and annoying ads on unsecured public WiFi networks. It all runs on a tiny t2.nano, costing less than $5/month.

The box

All this runs on a single t2.nano AWS instance running in the nearest region running Ubuntu 19.04.

Pi-hole (DNS + AdBlocker)

A simply trusty old cURL to bash?‍

curl -sSL https://install.pi-hole.net | bash

WireGuard

Setting this up is relatively easy after you get the hang of the key generation commands.

add-apt-repository ppa:wireguard/wireguard
apt-get update
apt-get install wireguard

cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey

I then muck around inside Vim to create /etc/wireguard/wg0.conf something that contains something like:

Note: Check your outgoing interface. It's probably not ens5 like mine, depending on your distro.

[Interface]
Address = 192.168.13.1
PrivateKey = [aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1vYXZNdFVXREJUTQ==] change me
ListenPort = 51820
PostUp = sysctl net.ipv4.ip_forward=1; iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -s 192.168.13.0/24 -o ens5 -j MASQUERADE; /usr/local/bin/pihole restartdns
PostDown = iptables -t nat -D POSTROUTING -s 192.168.13.0/24 -o ens5 -j MASQUERADE

[Peer]
PublicKey = [aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1vYXZNdFVXREJUTQ==] change me
AllowedIPs = 192.168.13.2/32
...
etc etc

The post-up/stop commands ensure traffic is forwarded from the machine's IP address. You might need to replace ens5 the interface of your default route. Pihole is restarted to ensure it listens on the wg0 interface so clients can use it as the DNS server.

Sample client config file

[Interface]
PrivateKey = aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1vYXZNdFVXREJUTQ==
Address = 192.168.13.2/32
DNS = 192.168.13.1

[Peer]
# the server
PublicKey = aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1vYXZNdFVXREJUTQ== change me
AllowedIPs = 0.0.0.0/0
# The server IP/udp port wg listens on
Endpoint = 13.37.13.37:51820
PersistentKeepalive = 25
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

systemctl status wg-quick@wg0
wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
   Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; vendor preset: enabled)
   Active: active (exited) since Fri 2019-10-18 14:00:55 UTC; 21s ago
     Docs: man:wg-quick(8)
           man:wg(8)
           https://www.wireguard.com/
           https://www.wireguard.com/quickstart/
           https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
           https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8
  Process: 18126 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
 Main PID: 18126 (code=exited, status=0/SUCCESS)

Oct 18 14:00:55 ip-172-31-5-144 systemd[1]: Starting WireGuard via wg-quick(8) for wg0...
Oct 18 14:00:55 ip-172-31-5-144 wg-quick[18126]: [#] ip link add wg0 type wireguard
Oct 18 14:00:55 ip-172-31-5-144 wg-quick[18126]: [#] wg setconf wg0 /dev/fd/63
Oct 18 14:00:55 ip-172-31-5-144 wg-quick[18126]: [#] ip -4 address add 192.168.13.1 dev wg0
Oct 18 14:00:55 ip-172-31-5-144 wg-quick[18126]: [#] ip link set mtu 8921 up dev wg0
Oct 18 14:00:55 ip-172-31-5-144 wg-quick[18126]: [#] ip -4 route add 192.168.13.2/32 dev wg0
Oct 18 14:00:55 ip-172-31-5-144 wg-quick[18126]: [#] sysctl net.ipv4.ip_forward=1; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -s 192.168.13.0/24 -o ens5 -j MASQUERADE; /usr/local/bin/pihole restartdns
Oct 18 14:00:55 ip-172-31-5-144 wg-quick[18126]: net.ipv4.ip_forward = 1
Oct 18 14:00:55 ip-172-31-5-144 systemd[1]: Started WireGuard via wg-quick(8) for wg0.

Everything should be running now, but Pihole needs a change to allow it to listen to DNS requests on the wg0 interface. I don't know how to do this automatically yet.

First, we must set a password for Pihole:

pihole -a -p
  1. Connect to the VPN
  2. visit http://192.168.13.1/admin/settings.php?tab=dns over the VPN
  3. change Interface Listening Behaviour to: Listen on all interfaces, permit all origins
  4. restart pinhole
  5. Note: Do not allow public traffic on port 53 to prevent open DNS resolver abuse. AWS security groups solved this for me.

Done.