
In this tutorial, we are going to install and configure WireGuard+Pi-hole with Docker to make our personal VPN, which it’s going to be secure and ads-free.
WireGuard is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many circumstances.
Pi-hole is a Linux network-level advertisement and Internet tracker blocking application which acts as a DNS sinkhole and optionally a DHCP server, intended for use on a private network.
We are going to start editing our docker-compose file:
$ nano docker-compose.yaml
version: '3.8'
services:
wireguard:
image: linuxserver/wireguard
container_name: wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=America/Argentina/Mendoza
- SERVERPORT=51820
- PEERS=2 #this is how many client I want
volumes:
- /path/to/our/wireguard/config:/config
- /path/to/our/wireguard/lib/modules:/lib/modules
- /usr/src:/usr/src
ports:
- 51820:51820/udp
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
dns:
- 172.0.0.10 #this is the internal docker ip of pihole
restart: unless-stopped
networks:
lan:
ipv4_address: 172.0.0.5
pihole:
container_name: pihole
image: pihole/pihole
expose:
- "53"
- "67"
- "80"
- "443"
environment:
TZ: 'America/Argentina/Mendoza'
WEBPASSWORD: '12345678' #we can access pihole web with this pass
volumes:
- /path/to/pihole/etc-pihole/:/etc/pihole/
- /path/to/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/
cap_add:
- NET_ADMIN
restart: unless-stopped
networks:
lan:
ipv4_address: 172.0.0.10
networks:
lan: #name of the network subnet
ipam:
config:
- subnet: 172.0.0.0/24
Now we can start our new containers with:
$ docker-compose up -d
We can check the status of the containers, not only with command “$ docker ps”, we can also use docker-compose (I prefer this command because it’s more readable):
$ docker-compose ps
Firewall
We need to open the firewall for 51820, depending on what OS are you using we are going to use a different command. In this case, I’m using Ubuntu 20.04 LTS and Ubuntu use UFW as firewall:
$ sudo ufw allow 51820
We can check this new rule with:
$ sudo ufw status
We also are going to need to open our edge router/home router. This also depend on what router do you use. I’m using a Mikrotik, so we need to go to IP>Firewall>Add New, and set up the Chain as “forward”, Protocol “TCP”, Destination Port 51820 and the Action “accept”. We also need to open 51820 on UDP, so go to IP>Firewall>Add New, and set up the Chain as “forward”, Protocol “UDP”, Destination Port 51820 and the Action “accept”.

Connecting clients (peers)
Now we need to connect our clients to the WireGuard server. The first step for this is installing WireGuard client. After the installation, we are going to need a peer.conf file or the QR code (for smartphones). We can find the peer.conf file on:
/path/to/our/wireguard/config/peer1/peer1.conf
Because we detail the numbers of peers in the docker-compose file, now we have the same amount of peers folders. We can upload this config file using transfer.sh following this tutorial.
If we want to connect our smartphone via QR code, we are going to check WireGuard logs typing:
$ docker logs wireguard

Looking in the WireGuard’s logs file, we are going to see every QR peers code. In the android app, we are going to select “Add Tunnel” and the “Scanning QR code”. We can also download the peer.conf file and installed, but I think it’s faster with the QR.

Testing
We can quickly check if everything it’s okay doing a dig test connected to the VPN:
$ dig google.com
$ dig ads.google.com

I add “@172.20.0.7” because in that scenario I’m not using pihole as my default DNS, so adding that I can force 172.20.0.7 (my pihole IP) as DNS server.
Now we can check in our browser if pihole it’s working fine:


We can test pihole too:

Done! Personal VPN wherever we are, with secure and ads-free connection.
Update (14 July 2022) :
Adding IP/domain to pi-hole to remove YouTube Ads.
One user on Reddit discovered doing some tcpdumps that if you do a nslookup on one domain that YouTube use for their ads, you can block that IP and stop the ads on your videos.
$ nslookup manifest.googlevideo.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: manifest.googlevideo.com
Address: 142.251.133.46
Name: manifest.googlevideo.com
Address: 2800:3f0:4002:809::200e
If we now do a new nslookup on that IP:
$ nslookup 142.251.133.46
46.133.251.142.in-addr.arpa name = eze10s02-in-f14.1e100.net.
Authoritative answers can be found from:
Now go to your pi-hole dashboard, login, Blacklist and add this domain and IP:

Now you don’t have any ads on YouTube, the only thing I still don’t figure out, it’s how to remove this:

I mean, I know that clicking the “x”, but I don’t want that this empty rectangle shows up.
Update (03 Sep 2022) :
If trying to run docker-compose an error of binding ports like this appears:
ERROR: for pihole Cannot start service pihole: driver failed programming external connectivity on endpoint pihole (306d268570ea188d68cee54de648ef24fdo3294fee3b0a4851c493c2793): Error starting userland proxy: listen udp4 0.0.0.0:53: bind: address already in use
Use lsof to check the binding ports, in this case DNS port 53
$ sudo lsof -i :53
matiasm@home-server:~/docker$ sudo lsof -i :53
[sudo] password for matiasm:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd-r 786 systemd-resolve 13u IPv4 22331 0t0 UDP 127.0.0.53:domain
systemd-r 786 systemd-resolve 14u IPv4 22332 0t0 TCP 127.0.0.53:domain (LISTEN)
Unbind systemd-resolve from port 53:
$ sudo systemctl disable systemd-resolved.service
Removed /etc/systemd/system/multi-user.target.wants/systemd-resolved.service.
Removed /etc/systemd/system/dbus-org.freedesktop.resolve1.service.
$ sudo systemctl stop systemd-resolved
Now edit resolved.conf
$ sudo nano /etc/systemd/resolved.conf
DNS=127.0.0.1
DNSStubListener=no
Pingback: Apps for Android that every SRE should try – the admin notes
Pingback: Networking with Linux: commands, services and more – the admin notes