back to projects

Family-Safe Internet Filtering

Defense-in-depth for a child's device · filtered at home, protected everywhere
Pi-hole WireGuard Cloudflare for Families Dynamic DNS Under construction
The goal Make sure my kid's device has safe, filtered internet wherever it is, with the same protection on home Wi-Fi as out on mobile data. At home, a Pi-hole plus family-safe DNS blocks ads, trackers, malware and adult content for the whole network. Away from home, an always-on WireGuard VPN carries the device back home so it inherits exactly the same filtering, leaving no gap the moment they leave the house.

01Why I'm building it

Content filters that only live on the home router stop working the instant a device leaves the Wi-Fi. On mobile data a phone or tablet is wide open. I wanted one consistent layer of protection that travels with the device, without relying on a paid third-party app that can be uninstalled or bypassed. The whole thing runs on my own infrastructure, so I control the policy and nothing about my kid's browsing is handed to an external service.

02How it works: two layers

At home: filter the whole network

Every device on the home network resolves DNS through a Pi-hole, which sinkholes ad, tracker and known-malware domains. Pi-hole's upstream is set to Cloudflare's family resolver (1.1.1.3), which additionally blocks malware and adult content at the DNS level. Together that's a solid, low-maintenance safety net for anything on the LAN.

Away from home: bring the device back to that network

The trick for "away" is simple in concept: put the device on the home network no matter where it physically is. An always-on WireGuard tunnel routes all of the device's traffic back home, where it exits through the same Pi-hole + family-DNS filtering. To the internet the device looks like it's sitting on the home LAN; to my kid it just works; and the protection is identical to being at home.

03Step 1: getting the VPN back to home working

Everything above depends on one foundation: a device out in the world being able to reliably reach home. If the tunnel home isn't rock-solid, the away-from-home filtering simply doesn't happen. So step 1 was building and hardening that path.

The VPN server

A WireGuard server runs in a container on my home lab, listening on its own UDP port. WireGuard is the right tool here: it is modern, fast and key-based. Each device is its own peer with its own keypair, so nothing connects without an explicitly authorised key. The child's device becomes one locked-down peer.

The problem that actually broke it: a moving address

A device away from home has to dial the server by address, but my home internet (Starlink) hands out a dynamic public IP that changes without warning. When it changed, the VPN's hostname was still pointing at the old IP, so the device was dialling an address that was no longer my house. The tunnel silently failed and never completed a handshake. That's the classic failure mode for self-hosted remote access, and exactly what I had to solve to make this dependable.

The fix: a self-healing address

I built a dynamic-DNS updater: a small script on the server checks the home's real public IP every few minutes and, whenever it changes, automatically updates the VPN hostname's DNS record to match. It runs on a scheduled timer, reads its API credentials from a protected secrets file (never hard-coded), and keeps the record DNS-only so WireGuard's UDP traffic isn't interfered with. The result is a stable name that always resolves to home even as the ISP shuffles our IP, so the tunnel comes back on its own instead of breaking every time.

Outcome of step 1 A dependable, self-healing route home: an authorised device can reach the WireGuard server from anywhere, the connection survives dynamic-IP changes, and it's all key-based and locked down. That's the platform the rest of the project is built on.

04The roadmap from here

05Skills & why it matters

back to projects