WireGuard vs Tailscale in 2026: Mesh VPNs, Zero Trust and Real Prices

Nov 10, 2026 · 12 min · Ajay Kumar

Every time I have helped a team replace a bastion host with a WireGuard-based network, the hard part was not the tunnel. WireGuard itself is small, fast and almost boring. What takes the work is everything around it: who hands out keys, how two laptops behind hotel NAT find each other, and who is allowed to reach which port. This post explains how WireGuard works, what mesh VPNs like Tailscale, Headscale, NetBird and ZeroTier add on top, whether any of that deserves the label zero trust networking, and what it costs in November 2026. If you just want a server running tonight, the companion guide on setting up a WireGuard VPN server on Ubuntu 24.04 has the commands.

How does WireGuard actually work?

WireGuard is a layer 3 tunnel that runs over UDP. Its protocol page lists a deliberately fixed set of primitives: Curve25519 for key exchange, ChaCha20 with Poly1305 for authenticated encryption, BLAKE2s for hashing, SipHash24 for hashtable keys and HKDF for key derivation. The handshake is a Noise framework pattern, written out in full as Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s. There is no cipher negotiation. If a primitive is ever broken, the fix is a new protocol version, not a configuration knob that half your fleet forgets to turn.

The whitepaper describes the Linux implementation as less than 4,000 lines of code, excluding the cryptographic primitives. Small enough that auditors actually read all of it, which is rarely true of an OpenVPN or IPsec stack. It landed in mainline Linux in the 5.6 release, and Jason Donenfeld announced WireGuard 1.0.0 the evening Linus shipped it at the end of March 2020. Every kernel since carries it.

Three design choices explain most of WireGuard's behaviour in practice:

  • Cryptokey routing. Each peer is a public key plus a list of AllowedIPs. Outbound, that list works like a routing table: a packet to 10.8.0.2 goes to whichever peer owns 10.8.0.2. Inbound, it works like an access list: a decrypted packet whose source address is not in the sender's AllowedIPs is dropped. Identity and routing are the same table.
  • Silence. A WireGuard endpoint does not answer unauthenticated packets at all. Every handshake message carries a MAC computed from the receiver's public key, so a port scanner sees nothing. Under load the responder can demand a cookie tied to the sender's IP before doing expensive work.
  • Timers instead of state machines. The whitepaper's constants table sets Rekey-After-Time to 120 seconds, Reject-After-Time to 180 seconds, Rekey-Timeout to 5 seconds and Keepalive-Timeout to 10 seconds. Sessions rekey roughly every two minutes, and keys older than three minutes are refused. There is no "connected" state to get stuck in, which is why a laptop can roam from Wi-Fi to tethering and keep its tunnel.

WireGuard has no user accounts, no key distribution and no NAT traversal beyond keepalives. A peer is a key, full stop. For two servers with static IPs that is a feature. For 200 engineers on laptops it is a spreadsheet of public keys waiting to go stale.

What does Tailscale add on top of WireGuard?

A mesh VPN keeps WireGuard as the data plane and adds a control plane. The control plane does four jobs: it ties each node key to a human identity from your SSO provider, distributes peer public keys and addresses to every node, pushes an access policy, and helps nodes find a path to each other through NAT.

The NAT part is where most of the engineering lives. Tailscale's DERP documentation says DERP servers mainly help devices set up direct connections and act as a relay of last resort when NAT or firewalls block a direct path. Because packets are already WireGuard-encrypted and private keys never leave the device, a DERP server forwards ciphertext it cannot read. Tailscale now also supports peer relays, which use a node in your own tailnet as the relay; the same page says Tailscale tries those before falling back to DERP, with lower latency and no cloud egress through a third party.

The result is that the network is flat at layer 3 but filtered by policy at every node. Policy is a JSON file, versioned like any other config. Here is a minimal example of the kind I would start with: engineers get SSH to production only through Tailscale SSH with re-authentication, and nobody gets anything else by default.

// Tailscale policy file (HuJSON), checked into git and applied via GitOps
// Syntax per tailscale.com/kb/1324/grants and kb/1193/tailscale-ssh (Nov 2026)
{
  "groups": {
    "group:sre": ["alice@example.com", "bob@example.com"]
  },
  "tagOwners": {
    "tag:prod": ["group:sre"]   // only SREs can tag a node as prod
  },
  "grants": [
    // network access: SREs may reach prod nodes on TCP 22 only
    { "src": ["group:sre"], "dst": ["tag:prod"], "ip": ["tcp:22"] }
  ],
  "ssh": [
    {
      "action": "check",          // force a fresh SSO login...
      "checkPeriod": "2h",        // ...at most every two hours
      "src": ["group:sre"],
      "dst": ["tag:prod"],
      "users": ["ubuntu"]         // never root by default
    }
  ]
}

Tailscale's own docs now recommend grants over the older acls block for most cases, and the Tailscale SSH page notes that an SSH rule needs a matching network grant to work. The same page carries a warning worth repeating: Tailscale SSH does not touch sshd_config or authorized_keys, so a departing engineer's old SSH key still works over any path that is not Tailscale. Offboarding is still your job.

Tailscale vs Headscale vs NetBird vs ZeroTier: how do they compare?

These four come up in almost every evaluation; licence and hosting model differ more than the feature lists.

Option Data plane Control plane Licence Free tier Paid entry price Latest release (checked 10 Nov 2026)
Tailscale WireGuard Hosted SaaS Client BSD-3; control plane proprietary Personal: up to 6 users, unlimited user devices (pricing) Standard $8 per user per month; Premium $18 v1.104.5
Headscale WireGuard (Tailscale clients) Self-hosted, single tailnet BSD-3-Clause (repo) Free software None, you run it v0.29.7
NetBird WireGuard Hosted or self-hosted Client BSD-3; management, signal, relay AGPLv3 (repo) Up to 5 users, 100 machines (pricing) Team EUR 6 per user per month; Business EUR 12 v0.82.0
ZeroTier Own protocol, emulated layer 2 Ethernet Hosted, self-host on Enterprise MPL-2.0 plus a source-available nonfree/ tree (repo) Personal: 10 devices, 1 network, non-commercial (pricing) Essential $18 per month for 10 devices, $2 per extra device 1.16.2

A few things the table hides. Headscale's README is explicit that it targets a single tailnet for personal use or a small open-source organisation, and that the maintainers do not support running it behind reverse proxies or in containers. It is a good fit for a homelab and a brave fit for a company. NetBird is the option I would look at first if self-hosting is a hard requirement, because the whole stack (management, signal, relay and STUN) is published and there is a one-line quickstart; the AGPL on the server components is fine for internal use but worth a conversation with legal if you plan to embed it in a product. ZeroTier is the odd one out: it is not WireGuard, it emulates an Ethernet switch, and that makes it the one to pick when you need layer 2 behaviour such as broadcast or non-IP protocols. Also note ZeroTier prices per device, not per user, so a fleet of servers with few humans can come out cheaper there.

Four ways to reach private infrastructure, and what each one trusts Bastion host One public SSH server Long-lived SSH keys Flat access once inside Port 22 open to internet Trusts: the network Plain WireGuard Static peer list Keys copied by hand AllowedIPs as the ACL Silent to scanners No users, no SSO Trusts: a key Mesh VPN WireGuard data plane Keys tied to SSO users Policy pushed to nodes NAT traversal, relays Tailscale, NetBird Trusts: user + device key ZTNA proxy No network join at all Proxy per application Checks every request Device posture signals Web apps fit best Trusts: each request Left to right: less implicit trust in the network, more dependence on an identity provider being up. Mesh VPNs and ZTNA proxies are often combined: mesh for SSH and databases, proxy for internal web apps.
A qualitative comparison of access models, drawn from the WireGuard protocol docs, Tailscale's DERP and SSH documentation and NIST SP 800-207. No numbers are plotted.

Is a mesh VPN zero trust? ZTNA vs VPN

NIST's SP 800-207, published in August 2020, is still the reference most security teams cite. Its core idea is moving defences away from static network perimeters and onto users, assets and resources, so that being "on the network" grants nothing by itself. Measured against that, a classic VPN concentrator fails: you authenticate once, land on a subnet, and can reach whatever the subnet can.

A mesh VPN gets much closer. Every connection is authenticated with a per-device key, that key is bound to a user in your identity provider, and the policy is enforced at the destination node rather than at a perimeter. What it does not do by default is evaluate each request. Once a grant allows TCP 5432 from your laptop to a database, the mesh does not know or care what SQL you send. A ZTNA proxy, by contrast, sits in the request path for each application and can recheck identity and device posture on every request, which is why it fits HTTP apps well and raw TCP protocols less well.

My honest summary: mesh VPNs are zero trust at the connection level and conventional at the application level. That is a large improvement over a VPN that drops you on a /16, and it is enough for most infrastructure access. If an auditor wants per-request decisions for internal web tools, put an identity-aware proxy in front of those and keep the mesh for SSH, databases and Kubernetes API access. It is the same layering principle behind workload identity federation: short-lived, identity-bound credentials beat long-lived network trust.

How do you replace a bastion host?

The bastion host is the thing most teams actually want to kill. It is a public SSH server holding the keys to everything, its authorized_keys file is rarely pruned, and port 22 faces the internet. The SSH hardening checklist helps, but the cleaner answer is to stop exposing SSH at all.

There are three common replacements:

  1. A mesh VPN with SSH policy. Install the client on each server, tag the nodes, and close port 22 on the public interface. With Tailscale SSH the server authenticates the connection using the WireGuard node identity and your SSO login, and the check action forces re-authentication on a schedule you choose (the docs allow one minute to 168 hours, default 12).
  2. Your cloud's own session broker. On AWS that is SSM Session Manager, on GCP it is IAP TCP forwarding. No inbound ports, IAM for authorisation, CloudTrail or audit logs for free. The downside is one tool per cloud, which hurts if you run more than one.
  3. Plain WireGuard to a single gateway. One small VM with WireGuard and nothing else listening; the step-by-step guide builds exactly this. It is cheap and fully under your control, but key distribution and revocation are manual, which is fine for five people and miserable for fifty.

For comparison, a managed cloud VPN is not free either. AWS Client VPN charges $0.10 per hour per subnet association and $0.05 per connection-hour in its US East (Ohio) examples. One association running all month is about $73 before a single engineer connects, which is about nine months of Tailscale Standard for one user.

Whichever you pick, the discipline is the same: access policy in git, reviewed like code, applied by CI, with a break-glass path that does not depend on the identity provider. Access should arrive by merged pull request, not a key pasted at 11pm.

Should you self-host the control plane?

Self-hosting is the most common question I get about mesh VPNs, usually from teams who were burned by a SaaS outage or who have a data residency requirement. The data plane is already peer-to-peer and end-to-end encrypted in all of these products, so the control plane never sees your traffic. What it does hold is your network map, your policy, your node keys' public halves and the ability to authorise new nodes. If someone compromises it, they can add a node to your network. That is the real risk, and it applies equally to a SaaS control plane and to the VM you forgot to patch.

So the question is less "do I trust them" and more "can I run this better than they do". Running Headscale or NetBird means owning upgrades, backups, TLS, the relay servers and the identity integration, plus being on call when it breaks. If your team already runs Postgres, Keycloak and a few internal services well, NetBird or Headscale is a reasonable weekend of work and a few hours a month after that. If not, the hosted control plane is cheaper than your time. Tailscale also offers Tailnet Lock, which requires new nodes to be signed by a trusted node you control, so the coordination server cannot add a node on its own; the docs list it for the Personal and Enterprise plans.

One practical warning: if most of your traffic ends up on a distant relay, latency suffers, so check how nodes actually connect (tailscale status shows direct or relayed paths).

FAQ

Is WireGuard more secure than OpenVPN?

WireGuard has a much smaller codebase (under 4,000 lines for the Linux implementation, per its whitepaper), a fixed modern cipher suite and no negotiation, which removes whole classes of misconfiguration. OpenVPN is not insecure, but it is far larger and more configurable. For new deployments WireGuard is the default choice unless you need TCP transport or a specific compliance profile.

Is Tailscale free?

The Personal plan is free for up to 6 users with unlimited user devices, per Tailscale's pricing page in November 2026. Paid plans start at $8 per user per month for Standard and $18 for Premium. The pricing page lists 50 included tagged resources, with more sold as add-ons.

What is the best self-hosted Tailscale alternative?

Headscale if you want to keep using the official Tailscale clients and only need one tailnet for a small group. NetBird if you want a complete open-source stack with its own clients, a web UI and SSO integration, and can accept AGPLv3 on the server components. ZeroTier only self-hosts its controller on the Enterprise tier.

Does a mesh VPN replace a firewall?

No. It replaces the perimeter VPN and often the bastion host, but servers should still run a host firewall, and cloud security groups should still block everything you are not using. Treat the mesh as an authenticated path in, not as a reason to open ports.

If I were starting this quarter with a bastion host and a handful of engineers, I would put a mesh VPN on every server, write the policy file in git with SSH limited to tagged production nodes and a two-hour check period, close port 22 on public interfaces, and keep one plain WireGuard gateway, configured as in the setup guide, as the break-glass path that works even when SSO does not.

Related: SSH Security Best Practices 2026: OpenSSH 10.6, ML-KEM and FIDO2 Keys, Workload Identity Federation Explained (2026): OIDC Instead of Cloud Keys and Kubernetes Security in 2026: First Attack in 18 Minutes, and What Stops It.

Spot an error or something out of date? Email me and I will fix it and log it on the corrections page.

I'm Ajay Kumar — I build and operate PandaStack, an open-source Firecracker microVM cloud for AI agents, and write about the infrastructure and tooling around it.

Need this kind of infrastructure work? See what I do or email hello@ajayk.sh.


Related