Family-Safe Internet Filtering
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.
04The roadmap from here
- Step 2: enrol the child's device as a WireGuard peer with its own key, set to always-on / on-demand so the protection can't simply be switched off.
- Step 3: force all traffic + DNS through home (full-tunnel), so every request: not just web browsing: is filtered by Pi-hole and the family resolver.
- Step 4: verify away-from-home: confirm that on mobile data, ad/tracker/malware and adult-content domains are actually blocked, matching the home experience.
- Step 5: per-device policy: a dedicated Pi-hole group for the kid's device with a stricter blocklist, and optionally time-of-day rules.
05Skills & why it matters
- Defense-in-depth: layering DNS filtering and a transport VPN so protection isn't tied to one location.
- Networking & VPNs: WireGuard server, key-based peers, full-tunnel routing and NAT/port-forwarding.
- DNS security: sinkholing and safe upstream resolvers as a practical control.
- Resilience engineering: solving the dynamic-IP failure mode with automated, self-healing dynamic DNS.
- Privacy by design: the whole solution runs on my own hardware; no child's browsing data goes to a third party.