picture of a laptop keyboard

Pihole and wireguard VPN

2024-02-17
Mark Hughes

BT don't make it easy to use PiHole to block ads at home

I’ve tried setting up PiHole on my home network in the past, a few times, but I’ve had to abandon the mission each time because I have a BT Smart Hub 2, which doesn’t allow me to use custom DNS, which means having to use the Pi as a DHCP server, and I’ve found that the performance of that can be a bit ropey, which would be fine, but my wife gets angry with me for breaking the internet on her phone and stuff so I’ve have to put it back. But I didn’t want to give up, I wanted to have ads blocked in my house and so I decided to do it again, but this time without drawing the ire of my better half. I thought about buying a router with a modem to replace the Smart Hub, which would have been the simplest way around it, but while I’m experimenting I don’t want to spend a lot of money on an expensive one, so I found a cheap old TP-Link router on Facebook Marketplace and I’ve connected it to the Smart Hub, setting it up as a separate network, which has the benefit that my wife can stay connected to the old one and not notice, well, except for the cool spaceship looking thing now sitting where the Smart Hub was.

With the TP Link router connected via ethernet to one of the Smart Hub’s LAN ports, there were a few steps I had to do to set it up. In the BT hub, I had port forwarding rules already configured to forward different types of traffic on my domain to my Pi. These need changing to the new router. It was simply a case of changing the target from the pi to the TP-Link

Set it to Wireless Router mode

Make sure that both the 2.4G and 5G bands are turned on Connect the Pi to it via WiFi, by editing /etc/network/interfaces.d/50-cloud-init with the username and password for the new router Give the Pi a static local IP In the DHCP menu, set the DNS servers to the IP address of the Pi Set up port forwarding rules to direct traffic to the Pi. I had other services running on my Pi already which conflicted with ports used by the router, such as 80 for the admin interface, so I also had to change the router's local management port in order to keep things working.

At this point, I’m able to connect my devices to the TP-Link router instead of the Smart Hub and get internet, yay. Next is to get pihole running on the Pi I chose to have Pihole running in a docker container, since I’m already using my pi for other services running in containers. I used this docker-compose file https://github.com/pi-hole/docker-pi-hole changing the ports to avoid conflicts. And run the command docker-compose up -d Test this is working by opening localhost:90 in your browser (assuming you’ve mapped it to port 90 like I have)

In the admin interface add a couple of blocklists, I’ve picked a few from https://avoidthehack.com/best-pihole-blocklists

In Settings > DNS, choose your upstream DNS servers, I just have OpenDNS, and make sure you have Interface Settings set to “Allow only local requests”

That should get Pihole up and running, serving your network traffic and blocking ads, on the dashboard you should slowly start to see queries coming through and details of domains being blocked.

This is all good, but I wasn’t happy with just having ads blocked on my home network, I wanted to block them on my phone when I’m out and about. For this I need to run a VPN server on the Pi and connect my phone as a client. There are a few VPN tools I could use but I went for wireguard, as it’s one of the more efficient and performant options available.

Install the Wireguard server components

The following steps are followed to set up the wireguard service

sudo apt-get install wireguard wireguard-tools

Create a wireguard folder

mkdir /etc/wireguard
cd /etc/wireguard

Generate a key-pair

wg genkey | tee server.key | wg pubkey > server.pub

Create a config file /etc/wireguard/wg0.conf

[Interface]
Address = 10.100.0.1/24, fd08:4711::1/64
ListenPort = 47111

Copy the private key to the config file as well

echo "PrivateKey = $(cat server.key)" >> /etc/wireguard/wg0.conf

Make sure that the router has the wireguard port forwarded to the Pi (in this case, 47111) Enable wireguard as a service that always runs in the background

sudo systemctl enable wg-quick@wg0.service
sudo systemctl daemon-reload
sudo systemctl start wg-quick@wg0

With wireguard running now, the last thing to do is add your client(s) This process is similar to adding the configuration for your server Generate a key pair for your client

sudo -i
cd /etc/wireguard
umask 077
name="client_name"
wg genkey | tee "${name}.key" | wg pubkey > "${name}.pub"

Generate a pre-shared key

wg genpsk > "${name}.psk"

Add the a configuration for the client in wg0.conf

echo "[Peer]" >> /etc/wireguard/wg0.conf
echo "PublicKey = $(cat "${name}.pub")" >> /etc/wireguard/wg0.conf
echo "PresharedKey = $(cat "${name}.psk")" >> /etc/wireguard/wg0.conf
echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> /etc/wireguard/wg0.conf

Reload the server config

wg syncconf wg0 <(wg-quick strip wg0)

Create a dedicated config file for your client

[Interface]
Address = 10.100.0.2/32, fd08:4711::2/128
DNS = 10.100.0.1
PrivateKey = $(cat "${name}.key")
[Peer]
AllowedIPs = 10.100.0.1/32, fd08:4711::1/128
Endpoint = [your public IP or domain]:47111
PersistentKeepalive = 25
PublicKey = $(cat server.pub)
PresharedKey = $(cat "${name}.psk")

Create a qr code that can be used by a mobile device to scan the config

sudo qrencode -t ansiutf8 < "/etc/wireguard/${name}.conf"

Use the wireguard app to import the config, and connect

Now we have my phone on mobile data (or any other wifi network) connected to the VPN, with internet access and ads being blocked. The way I test it is by going to https://fuzzthepiguy.tech/adtest/ and seeing if ads load. If they don’t, it’s all working as expected.

before after