Using WireGuard so kids' devices stay protected on any network
After setting up AdGuard Home and Unbound on my home server, DNS filtering was working perfectly for every device on the home network. But children's devices don't stay on the home network. They go to school, to friends' houses, connect to public Wi-Fi, and use mobile data. In all of those situations, the home DNS filtering was being bypassed entirely.
The solution was WireGuard VPN, configured so that children's devices always route their DNS queries back through the home server, regardless of which network they're on.
Why WireGuard
I've used OpenVPN in the past and it works, but WireGuard is a different league:
- Fast. Built into the Linux kernel, minimal overhead. You don't notice it's running.
- Simple. The entire codebase is around 4,000 lines of code. OpenVPN is over 100,000.
- Battery friendly. It only sends packets when there's traffic. No keepalive polling draining the battery.
- Reliable. Handles network changes gracefully. Switch from Wi-Fi to mobile data and the tunnel reconnects silently.
The N100's hardware AES-NI support means encryption overhead is essentially zero. WireGuard throughput on this box easily saturates the home broadband connection.
DNS-only vs full tunnel
This is the key design decision. There are two approaches:
Full tunnel routes all traffic through the VPN. Every web request, every app connection, everything goes home first and then out to the internet. This gives you full control but means all traffic takes a round trip through your home broadband, which adds latency and uses upload bandwidth.
DNS-only routing sends only DNS queries through the VPN. The actual browsing traffic goes directly to the internet via whatever network the device is on. But because DNS is resolved at home, AdGuard Home's filtering still applies everywhere.
I went with DNS-only routing for the children's devices. The filtering is the point, not inspecting traffic. This keeps browsing fast while still blocking ads, trackers and inappropriate content on every network.
Server setup
Install WireGuard
sudo apt install wireguard
Generate server keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
Server configuration
/etc/wireguard/wg0.conf:
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <server_private_key>
# NAT for VPN clients
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Child's iPad
[Peer]
PublicKey = <client_public_key>
AllowedIPs = 10.10.0.2/32
Enable IP forwarding:
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Start and enable the service:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
Port forwarding
You'll need to forward UDP port 51820 on your router to the server's local IP. This is the only port WireGuard needs.
Client configuration
For each child's device, generate a key pair:
wg genkey | tee client_private.key | wg pubkey > client_public.key
The client configuration is where the DNS-only routing magic happens:
[Interface]
PrivateKey = <client_private_key>
Address = 10.10.0.2/24
DNS = 10.10.0.1
[Peer]
PublicKey = <server_public_key>
Endpoint = your-home-ip:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25
The critical line is AllowedIPs = 10.10.0.0/24. This tells WireGuard to only route traffic destined for the VPN subnet through the tunnel. Since DNS = 10.10.0.1 points to the server's VPN address, DNS queries go through the tunnel and hit AdGuard Home. Everything else goes direct.
If you wanted a full tunnel instead, you'd set AllowedIPs = 0.0.0.0/0 which routes everything through the VPN.
Getting it onto the devices
The easiest way is to generate a QR code:
sudo apt install qrcode
qrencode -t ansiutf8 < client.conf
Open the WireGuard app on iOS or Android, tap "Add tunnel", scan the QR code, done. The whole process takes about 30 seconds per device.
AdGuard Home integration
For this to work properly, AdGuard Home needs to listen on the WireGuard interface too. In AdGuard Home's settings, make sure it's bound to 0.0.0.0 (all interfaces) or specifically includes 10.10.0.1.
You can also configure AdGuard Home with per-client settings. I have the children's VPN IPs set up with stricter filtering rules (safe search enforced, adult content blocked) while my own devices have a lighter touch.
On-demand VPN on iOS
On iPhones and iPads, WireGuard supports "on-demand" activation. In the WireGuard app, you can configure the tunnel to activate automatically on any Wi-Fi network, on mobile data, or both. I have it set to activate on all networks except the home Wi-Fi (where filtering already applies via the router's DNS settings).
This means the filtering is genuinely always on. The kids don't need to remember to connect, and they can't easily disconnect it without the configuration being re-pushed.
The result
Whether a device is at home, on school Wi-Fi, at a friend's house, or using mobile data, DNS queries go through the home filtering system. Ads are blocked, trackers are blocked, and inappropriate content is filtered. All without installing any software beyond the WireGuard app, and with no noticeable impact on browsing speed.
The whole stack (N100 server, Debian, AdGuard Home, Unbound, WireGuard) has been running for months now without intervention. It's the kind of infrastructure that just fades into the background and works, which is exactly the point.
This is the final article in my home server series. Previously: building the N100 server and AdGuard Home with Unbound for private DNS.