WireGuard is a new VPN software, which is described as
It aims to be faster, simpler, leaner, and more useful than IPSec, while avoiding the massive headache and using state-of-the-art cryptography.
a black hole for Internet advertisements, ie a server blocking advertisements at DNS level.
I have Pi-hole on my home network, but wanted to have it also as DNS server on my phone when I am not home. As I have a bad DSL connection, I can not rely on my home server. So I put Pi-hole on a VPS server I rent: it works, flawlessly.
Nevertheless it was an open DNS resolver, which can be used to amplify DDoS attacks; there is already 2212 unsecured Pi-hole ont the Internet, so I do not want to add another one.
Pi-hole provides documentation to use OpenVPN, even to redirect only DNS requests but it is not efficient on a phone as it is not a stateless connection, so it consumes battery; moreover GSM/Wifi switch is not really handled, you have to reconnect. The solution comes from WireGuard which is stateless, and provides Android & iOS apps. I struggle to configure everything, so here is what I did:
Pi-Hole in Docker container
Pi-holes provides a [convenient Docker]https://hub.docker.com/r/pihole/pihole/) container so it is easy to build a Docker-compose file on top.
Here is an example, as there is already other Docker services serving on ports
443 through jwilder container providing reverse proxy, so I add this container to the same network.
Pi-hole also recommends to have it as default on the machine in order to replace adds by white pages, it helps to keep pages layout, so jwilder's Docker environment variable
DEFAULT_HOST should be set to Pi-hole's
If you do not use jwilder container just delete
networks related options.
version: '3.5' services: pihole: image: pihole/pihole:latest dns: - 127.0.0.1 - 184.108.40.206 ports: - '127.0.0.1:53:53/tcp' - '127.0.0.1:53:53/udp' # Adapt to WireGuard interface - '192.168.2.1:53:53/tcp' - '192.168.2.1:53:53/udp' volumes: # Adapt to folders - ../../data/pi-hole/etc:/etc/pihole/ - ../../data/pi-hole/dnsmasq.d:/etc/dnsmasq.d networks: - network-proxy environment: # Adapt to server IP address ServerIP: X.X.X.X PROXY_LOCATION: pihole # Adapt to domain VIRTUAL_HOST: pihole.YOURDOMAIN.ext VIRTUAL_PORT: 80 extra_hosts: # Resolve to nothing domains (terminate connection) # 'nw2master.bioware.com nwn2.master.gamespy.com:0.0.0.0' # LAN hostnames for other docker containers using jwilder - 'pihole pihole.yourDomain.lan:220.127.116.11' restart: unless-stopped networks: network-proxy: name: "https-proxy"
WireGuard configuration was more difficult. My server is running Debian 9 where Debian systemd documentation can not be used as the version is too old, and I never found out why regular documentation was failing with
So I had to use the old
/etc/network/interfaces file. Replace eth0 with your "main" interface.
auto wg0 iface wg0 inet static address 192.168.200.1 netmask 255.255.255.0 pre-up ip link add $IFACE type wireguard pre-up wg setconf $IFACE /etc/wireguard/$IFACE.conf pre-up iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; post-down iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; post-down ip link del $IFACE
Now we have to configure WireGuard itself in
/etc/wireguard/wg0.conf, where wg0 is WireGuard interface name:
[Interface] ListenPort = 8124 PrivateKey = REPLACE_WITH_YOUR_PRIVATE_KEY [Peer] PublicKey = REPLACE_WITH_CLIENT_PUBLIC_KEY_GENERATED_AFTER AllowedIPs = 0.0.0.0/0
Server keys are generated as per documentation:
wg genkey | tee privatekey | wg pubkey > publickey
Then route should be added:
ip route add 192.168.2.2/32 dev wg0
- Generate public/private key thanks to
Interface->Addressesis client IP address. ex:
Interface->Listen portis the same than
Interface->DNS serversis your server WireGuard IP. ex:
Peer->Public keyis the server's public key
Allowed IPshould be serverIp/24 but I do not know why it forwards only DNS queries to the server. Putting
0.0.0.0/0makes it work, I have to figure out why.
Endpointis server public IP address:port. ex: