RouteHardenHire us
← Back to blog
Self-Hosted Privacy··8 min read

OpenWrt privacy router without breakage theater

How to build an OpenWrt privacy router with WireGuard, policy-based routing, explicit DNS handling, and fewer leak-prone shortcuts.

A privacy router should be boring first.

That is the right design principle for OpenWrt and for self-hosted networking in general. The goal is not to assemble the maximum number of privacy features into one screenshot. The goal is a router that leaks less, breaks less, and can still be understood when the ISP flakes out at 2 a.m.

If the setup is too clever to reason about under failure, it is not a good privacy router. It is a hobby artifact.

Pick the routing model before you touch DNS

Most fragile OpenWrt builds start in the wrong order. People enable encrypted DNS, flip on a VPN client, add a few policy rules, then only later ask what traffic model the router is supposed to implement.

Start with the routing model instead:

  1. route everything over one VPN
  2. split-tunnel only some clients or destinations
  3. run a VPN server and a VPN client at the same time

Those are different jobs.

OpenWrt's PBR overview is useful here because it reminds you what policy-based routing is actually for: split tunneling, WAN forwarding with a VPN default route, and mixed server/client VPN roles.

If you skip this decision, DNS and firewall settings become cleanup work for a topology you never named clearly.

That ordering matters because DNS, firewall zones, and policy rules all inherit the routing model whether you intended that or not. If the core path idea is fuzzy, the supporting settings only look coherent by accident.

PBR is the real foundation

OpenWrt's PBR tooling is the part of the stack that turns "I want some traffic to go elsewhere" into a coherent router behavior.

The important practical distinction in the docs is:

  • the pbr app is great when your decisions are based on interfaces, subnets, IP addresses, or ports
  • it is not a magic domain-routing engine

That matters because people often try to solve domain-based policy at the router when the router is actually better at path-based policy.

The deeper pbr with netifd guide is even more important. It recommends separate routing tables per upstream interface and keeping default routes enabled for each upstream. That is the kind of boring structure that prevents surprising leaks later.

It also explicitly says it includes both IPv4 and IPv6 rules to prevent traffic leaks. That is exactly the right mindset. IPv6 is not appendix material.

In practice, there are two different maturity levels here:

  • the pbr app is enough when you have straightforward path decisions
  • table-first thinking matters when the router is turning into real routing infrastructure

Both are valid. The mistake is pretending the second case can still be reasoned about purely as a checkbox exercise.

One quick heuristic helps here: if you are still thinking in terms of "a couple of clients should use the VPN," the app-level pbr workflow is often enough. If you are thinking in terms of multiple upstreams, different default routes, and how failover should behave when one path dies, you are already doing routing engineering whether or not the LuCI page looks friendly.

WireGuard full tunnel without hand-waving

The official all traffic through WireGuard page is good because it shows the lines people actually need to care about:

  • list allowed_ips '0.0.0.0/0'
  • option route_allowed_ips '1'
  • LAN forwarding toward the WireGuard zone
  • masquerading on that zone
  • DNS that is reachable through the tunnel path

A compact peer excerpt looks like:

config wireguard_wg0_int
    option public_key 'REDACTED'
    list allowed_ips '0.0.0.0/0'
    option route_allowed_ips '1'
    option endpoint_port '51820'
    option persistent_keepalive '15'
    option endpoint_host 'vpn.example.com'

The companion firewall idea is just as important:

config forwarding
    option src 'lan'
    option dest 'wg0_zone'

What I like about the official guide is that it quietly teaches the correct lesson: a full-tunnel router is not "VPN box plus vibes." It is routing, forwarding, and DNS behaving consistently together.

It also teaches a subtler lesson: keep the DNS server reachable on the path you are building. A full tunnel with a resolver that only works on the wrong side of the tunnel is how people create outages and then blame WireGuard for a resolver-placement error.

DNS should be local, explicit, and testable

OpenWrt's DoH with dnsmasq and https-dns-proxy guide is worth reading not just for setup, but for the validation mindset.

It calls out DNS leak testing and DNSSEC testing explicitly. That is good operator behavior.

The design rule I would keep is:

  • clients ask the router
  • the router decides where DNS goes
  • encrypted upstream DNS, if enabled, should be a router-side design choice, not accidental overlap with every client doing its own thing

Even a minimal router-side direction like:

config dnsmasq
    list server '10.0.0.1'

is better than an implicit mystery path you forgot to document.

The official docs also note that custom Android Private DNS combined with router-side encrypted DNS can create confusing results. That is a perfect example of why checkbox stacking is not architecture. If both client and router try to own DNS policy in incompatible ways, the user experience gets weird and the leak story gets harder to verify.

This is where /blog/pihole-doh-home-network and router DNS design naturally intersect.

It is also why I prefer explicit router DNS over mysterious smart layers. The router is often the only place you can make one rule for the household and verify it centrally.

That verification step deserves real time. After each meaningful change, test:

  • what the router itself resolves through
  • what a LAN client resolves through
  • whether DNS still works when the VPN reconnects
  • whether DNS still behaves the way you expect after reboot

If you do not test those states, you are mostly trusting that the previous page load reflected the permanent truth.

IPv6 is part of the main design

The pbr_netifd documentation is one of the rare router guides that treats IPv6 with the seriousness it deserves. Keep that energy.

If you are building a privacy router, the dangerous state is not "IPv6 exists." The dangerous state is "the VPN and routing story were built as if only IPv4 matters."

That means you need to ask:

  • does the upstream support IPv6?
  • do the policy rules cover IPv6 intentionally?
  • what leaks if the IPv6 story is partial?

This overlaps directly with /blog/ipv6-leak-prevention, because the router is often where the leak either gets prevented cleanly or made harder to notice.

Failure behavior matters just as much. Ask yourself: if the VPN client drops, does traffic fail closed, reroute over WAN, or enter some half-working state that depends on whichever route updated last? A privacy router without a clear failure story is just a leak with better marketing.

This is where a lot of attractive OpenWrt screenshots fall apart. They show the happy path beautifully and say almost nothing about the broken path. But home routers spend their lives in the broken path: ISP resets, upstream DNS weirdness, peer endpoints flapping, clients roaming between networks. If the design only makes sense while everything is healthy, it is not really a design yet.

What I would do for a normal household

For a normal household or homelab, I would keep it simpler than most forum screenshots:

  1. one WireGuard client uplink
  2. one clear routing model, either full tunnel or a small number of split-tunneled clients
  3. router-side DNS that is explicit and tested
  4. IPv6 handled intentionally, not ignored
  5. PBR only where it truly buys something

The WireGuard extras and client setup docs are helpful, but the right mindset is more important than memorizing all the UCI knobs. Every extra branch in the topology should justify itself.

For a normal household, I would not start with per-app exceptions, layered encrypted-DNS gimmicks, and three VPN paths. I would start with one clear uplink decision, verify DNS, verify IPv6, and only then add selective routing for the one or two clients that genuinely need it.

That last part matters because households tend to accumulate weird clients: a TV box, a game console, a work laptop, a phone with its own private-DNS settings. The more routing branches you add before the baseline is stable, the harder it becomes to tell whether a problem belongs to the client, the router, the VPN path, or the DNS path.

A compact checklist beats a giant wizard

Use this mental checklist:

- separate routing tables per upstream
- keep default routes enabled per interface
- account for IPv6 explicitly
- test DNS and default-route behavior after every change

That is not glamorous. It is the sort of checklist that keeps a router understandable months later.

And if you are using the pbr app, remember the current docs even include Tailscale-specific notes and warn that Tailscale exit-node behavior may not reflect neatly in LuCI. That is another quiet reminder that the UI is not the network model. The model still matters even when the app makes it convenient.

The RouteHarden opinion

The best OpenWrt privacy router is the one you can still reason about after an outage.

That means:

  • routing model first
  • DNS as part of the main design
  • IPv6 included from the beginning
  • PBR used deliberately, not decoratively

OpenWrt is powerful enough to let you build a clean, low-leak router. It is also flexible enough to let you build a pile of half-understood features that mostly works until it does not.

Choose the first path.

Privacy routers should reduce surprises. They should not become one.