When we started building HostAnywhere, the protocol question came up early. Many mesh networking products built in the last few years use WireGuard. A few — most notably ZeroTier — use a custom protocol. Both choices have real trade-offs.
We picked WireGuard. This post is about why, and — equally important — what we gave up.
What WireGuard is, in one paragraph
WireGuard is a minimal, modern VPN protocol that runs over UDP. It uses Curve25519 for key exchange, ChaCha20-Poly1305 for authenticated encryption, and BLAKE2s for hashing. The Linux implementation is small compared with older VPN stacks, and WireGuard was merged into the mainline Linux kernel in 5.6. It also has mature cross-platform implementations across macOS, Windows, iOS, and Android.
It is intentionally opinionated and small. WireGuard gives you encrypted point-to-point tunnels. It does not solve key distribution, NAT traversal, identity, device inventory, access policy, DNS, or user management. Everything around the tunnel is the responsibility of the product built on top.
How HostAnywhere runs WireGuard
HostAnywhere runs WireGuard in userspace on all five platforms — Windows, macOS, Linux, iOS, and Android. The userspace data plane gives us:
- A single Go codebase across all five platforms instead of five platform-specific implementations.
- No kernel module dependency — works on older Linux distros and restricted environments, and works on platforms where a kernel WireGuard module isn't available to applications at all.
- Consistent debugging and observability — the same code path means the same logs, the same edge cases, and the same NAT-traversal behavior everywhere we ship.
- Easier deployment — no DKMS on Linux, no kernel-mode driver beyond the wintun TUN driver on Windows, no platform-specific data planes to maintain.
On Windows, macOS, iOS, and Android, userspace is effectively the only practical option for an application — those OSes don't expose a kernel WireGuard module the way Linux does. On Linux, kernel WireGuard exists (merged in 5.6) and some products use it directly. We picked userspace on Linux too, to keep a single code path across the entire fleet.
The case for WireGuard
The case is mostly about leverage:
- Mature cryptography with a small, well-reviewed protocol surface.
- Broad implementation maturity — kernel-resident on Linux, mature userspace implementations on macOS, Windows, iOS, and Android.
- Strong ecosystem adoption across VPN products, mesh networks, cloud environments, and security tools.
- Good performance on direct paths without making cryptography the bottleneck for most users.
- Public protocol and broad implementation support, instead of a private wire format controlled by one vendor.
- More engineering time for the product layer: coordination, policy, posture, gateways, storage, and backups.
The leverage matters because it means we spend our engineering time on the layer above WireGuard — the mesh coordination, the policy engine, the integrations, the storage server, the phone backups — not on rolling our own crypto.
The case for a custom protocol
It's a real case. ZeroTier has run a custom protocol since 2015. Their team has reasons:
- Layer-2 capability. WireGuard is strictly Layer 3 — IP packets. ZeroTier can carry Ethernet frames, which matters for broadcast/multicast (Bonjour, IPv6 link-local, AppleTalk-era protocols), some legacy IoT, and "make this mesh look like a flat LAN" use cases.
- Custom features. ZeroTier's flow rules are a domain-specific language for traffic policies that can rate-limit, tag, redirect, and inspect packets on the fly. WireGuard doesn't have a comparable layer.
- Tight coupling between protocol and product. ZeroTier can change wire-format details when their product needs them. WireGuard's stability is a constraint.
- Bridging into physical Ethernet segments. Useful in industrial / OT environments where you need a virtual switch port that behaves like a real one.
These are real capabilities. If your use case depends on Layer-2 bridging, ZeroTier is likely a better fit than a pure WireGuard-based Layer-3 mesh.
What we gave up by picking WireGuard
Honest list:
- No Layer-2 mesh. HostAnywhere is Layer 3 only. If you need broadcast/multicast across the mesh, or you're running legacy protocols that don't speak IP routing, we don't cover that case.
- No flow-rules DSL. Our access control is a UI-driven rule list with allow/deny and posture conditions. You can express the common cases (allow tag A to reach device B on port C when posture is X), but you can't write arbitrary packet-inspection logic the way ZeroTier flow rules let you.
- No Layer-2 bridging into physical Ethernet segments. HostAnywhere can route IP subnets through gateways — that's what our VPN Gateway does. But it does not make a remote device behave like it's plugged into the same Ethernet switch. Industrial / OT users who need a true virtual Ethernet port will pick something else.
- No custom protocol features at the data-plane level. Anything we ship has to live above WireGuard's stable wire format. Most product features don't care about this. A few — like dynamic per-packet rate limiting or in-band traffic classification — would be easier with protocol-level hooks.
Each of those is a real trade-off. For each one, there's some real user out there for whom it's the deciding constraint. We made the choice knowing those users would pick differently.
Why we made the trade
Three reasons.
One: the leverage compounds. Every engineer-hour we don't spend building a data plane is an engineer-hour we spend on the layer above. The phone backup architecture, the Storage Server replication, the CrowdStrike integration, the Internet Gateway failover — those features exist because we're not also maintaining a custom crypto stack.
Two: WireGuard's ecosystem keeps growing. Kernel inclusion is rare in the networking world. Once a protocol is in the mainline Linux kernel, it becomes available across a huge range of future Linux distributions, appliances, servers, and embedded systems. Mature cross-platform implementations elsewhere mean we are not designing a new cryptographic data plane for every OS.
Three: smaller attack surface, less reputational risk. A small, audited implementation and well-reviewed protocol surface is a smaller "trust us, we got the crypto right" ask than rolling our own. For a product positioned around security, having WireGuard's track record under the hood means we're not asking customers to also evaluate our novel cryptographic choices.
What about the convenience features?
A common follow-up: "But Tailscale has MagicDNS, Tailscale SSH, and Taildrop. WireGuard didn't give them those — they built them on top. Why don't you have them?"
Fair question. Those features are not data-plane concerns. They're conveniences in the user-facing product, built on top of whatever mesh you have. They take engineering time to build. We haven't built them yet. They're on our roadmap; none of them require a custom protocol.
The reason we focused elsewhere first is product shape. Our bet is that most users who care about a mesh also care about exposing services, posture-gating access, and phone backups. So we built those things first. MagicDNS-equivalents and SSH-key-replacement are convenience layers we'll add — but they're not what changed our minds about WireGuard. Choosing WireGuard did not prevent us from building those features; it only means they belong above the tunnel, not inside the tunnel.
A note for builders
If you're building a mesh product today and weighing the protocol choice, the questions we'd ask:
- Will any of your users need Layer 2? If yes, WireGuard alone probably isn't enough — you may need a Layer-2 overlay, a bridging layer, or a protocol designed for Ethernet semantics. If no, default to WireGuard.
- Are you going to be the one maintaining the platform integrations on Windows / macOS / iOS / Android? If yes, you'll appreciate using something the OSes already support.
- Do you have a specific data-plane feature you can't build above the wire format? If yes, custom. If no, you'll find a way to do it above WireGuard.
- How much engineer-time can you afford to put into the data plane? If "a few people indefinitely," custom is feasible. If "we want to ship product features instead," WireGuard.
WireGuard isn't the answer for every mesh product. It was the right answer for the product we're trying to build.
A few practical notes from the road
If you're already deciding between WireGuard-based products, two things worth knowing:
- Implementations are not all equal. Different WireGuard-based products make different implementation choices — kernel module vs. userspace, single-threaded vs. multi-threaded data planes, custom NAT-traversal logic vs. STUN. ZeroTier doesn't use WireGuard at all. So "WireGuard-based" still leaves room for different operational behavior, NAT-traversal tactics, and observed throughput. Benchmark your own workload before assuming "WireGuard means the same performance everywhere."
- The protocol is stable; the products are not. WireGuard's wire format is essentially frozen. The product layer above it — coordination, key rotation, observability, policy — is where actual differences between products live, and where they evolve. When you're evaluating, focus there, not on "do they use WireGuard."
See the HostAnywhere docs for technical details on mesh networking, VPN Gateway routing, and access control — or follow @HostAnywhere on LinkedIn for more engineering posts.