Articles › Security

Reach your home server without opening ports - WireGuard vs Tailscale

Three ways in: port forward + DDNS, plain WireGuard, Tailscale or Headscale. A minimal Ubuntu 24.04 config, the trade-offs, and what still needs hardening behind a VPN.

Intermediate 7 min read October 21, 2026

What you will learn
  • A port exposed to the internet is scanned and attacked within hours, not days
  • WireGuard stays silent to packets without a valid key, so scanners see nothing - but it still needs one UDP port on the router
  • Tailscale gets through NAT with no open port at all, in exchange for a third party in the control plane (Headscale removes it)
  • A public web service should not run from the home box; put a VPS reverse proxy or a tunnel in front

Getting into the machine at home from outside is two half-problems. The “name” half is that your home IP keeps changing; DDNS solves that (companion article). The “access” half is how a packet from outside reaches your box at all without turning it into a target for every bot on the internet. This article is about the second half, comparing three routes: the classic port forward, self-managed WireGuard, and Tailscale.

Every command was tested on Ubuntu 24.04.

Why an open port gets hit immediately

Nobody is targeting your house. Bots simply sweep the whole IPv4 space all day. Palo Alto Networks’ Unit 42 put 320 honeypots on public clouds (2021): 80% were compromised within 24 hours and every one of them within a week. SSH was the most attacked service, and some services were hit within 30 seconds of going live. A home connection is no different: forward port 22 or 3389 and your logs fill up overnight.

Port forward + DDNS therefore “works”, but you own the security of every service you expose: patched on time, no weak passwords, no admin panel you forgot to disable. One slip and the whole house is in.

internetOpen a portanyone can knockscanned in minutesWireGuardone UDP portvalid keys onlyTailscaleno open portNAT traversal, usershome machine
Further right, less exposed: nothing for scanners to find

WireGuard in one paragraph

WireGuard is a kernel-level VPN stripped down to the essentials. Each side has a Curve25519 key pair (think SSH keys) and knows the other side’s public key in advance. It runs over UDP, does a one-round-trip handshake (Noise_IK) and encrypts with ChaCha20-Poly1305. The security detail that matters here: if an incoming packet fails the key check, the server does not answer at all. No banner, no error, no memory allocated. A scanner sees that port as if nothing were listening, unlike SSH or HTTPS, which greet everyone who knocks.

UDP 51820 with WireGuard listening is in a different league from TCP 22 with sshd listening: without the key you don’t even get a reply.

Minimal WireGuard: server + one peer

This route still needs one UDP port forwarded from the router to the home server (and DDNS so the laptop knows the home IP).

On the home server:

sudo apt install wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub

Do the same on the laptop (giving laptop.key / laptop.pub) and exchange only the .pub files. A .key file never leaves the machine that made it.

Server: /etc/wireguard/wg0.conf

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of server.key>

[Peer]
# laptop
PublicKey = <contents of laptop.pub>
AllowedIPs = 10.8.0.2/32

Laptop: wg0.conf

[Interface]
Address = 10.8.0.2/24
PrivateKey = <contents of laptop.key>

[Peer]
PublicKey = <contents of server.pub>
Endpoint = home.example.net:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25

Bring it up on both sides:

sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0   # start at boot
sudo wg                              # last handshake and byte counters

From the laptop, ssh dev@10.8.0.1 getting in means you are done.

The trap: AllowedIPs is not just “who may come in”; it is also the routing table (cryptokey routing). The server uses a /32 per peer; the laptop uses the VPN’s /24. Set 0.0.0.0/0 and all of the laptop’s traffic goes via home, which is not what you want here. PersistentKeepalive = 25 is needed when the laptop sits behind NAT; otherwise the NAT forgets the return path after a quiet spell.

What Tailscale adds

Tailscale uses the same WireGuard in the data plane but takes away two chores: key distribution and NAT.

  • Coordination server acts as a “drop box for public keys”. Every device logs in with an identity (Google, GitHub, Microsoft and so on), generates its keys locally, uploads only the public key and downloads the public keys of the other devices in the network. No swapping .pub files by hand.
  • NAT traversal with STUN/ICE punches a direct path between two devices behind different NATs, with no port opened on the router. If that fails (hard NAT, UDP blocked) traffic goes through a DERP relay, which forwards already-encrypted packets it cannot read.
  • MagicDNS names every device automatically: ssh home-nas instead of an IP.
  • ACLs are a central policy of who may talk to whom on which port, enforced on every device as packets are decrypted.
  • Tailscale SSH (tailscale set --ssh) uses your tailnet identity instead of SSH keys and can force a fresh MFA sign-in with check mode.

On Ubuntu, run Tailscale’s install script, then sudo tailscale up prints a login link. Every device signed in to the same account can talk straight away.

Tailscale’s trade-offs

  • A third party in the control plane. Tailscale cannot read your traffic, but it knows how many devices you have, their names and public IPs, and it decides whose public key is handed to whom. If your identity-provider account is compromised, that person is on every device.
  • An external dependency. Control plane down means new devices cannot join (devices already connected keep talking, since the data plane is peer-to-peer).
  • The free tier has edges. At the time of writing the pricing page lists Personal as free for 6 users with unlimited devices. This has changed before; check the current pricing page.
  • Some advanced features (fine-grained ACL options, audit logs) sit in paid plans; verify against the current docs.

Headscale: your own control plane

Headscale is an open-source reimplementation of Tailscale’s control server. You keep the stock Tailscale clients and point them at your server (tailscale up --login-server https://hs.example.net), getting key distribution, NAT traversal and MagicDNS with no company in the middle.

From the project README: it is deliberately scoped to a single tailnet for self-hosters and small open-source organisations, not large companies. You also need one public server running Headscale (a small VPS is enough) that you maintain yourself. If you keep using Tailscale’s DERP servers, relayed traffic still passes through them when a direct path fails; closing that last gap means running your own DERP too.

Decision table

SituationPickWhy
Home lab, one user, 2-5 devicesTailscale free, or plain WireGuardTailscale is a 5-minute install with no open port; WireGuard if you want zero dependencies and have only 1-2 peers
Small team, several people, several homesTailscale (ACLs + SSH) or HeadscaleCentral identity revokes access instantly when someone leaves; Headscale when policy forbids a third party
One public web service for the general publicVPS + reverse proxy, or a tunnel to the home boxThe thing being attacked is the VPS, not your home network; the home box dials out to the VPS over WireGuard/Tailscale with no inbound port

The home box should never take traffic from strangers directly. If you need a public site, let the thing that gets shot at be a $5 VPS, not the NAS with the family photos.

What still needs hardening behind a VPN

A VPN shrinks who can “knock on the door” from the whole internet to devices holding a key. It does not make the door any stronger.

  • Updates. unattended-upgrades is still required. One device on the network catching malware puts every other device in range.
  • Local firewall. With ufw, allow services only from the VPN interface, e.g. sudo ufw allow in on wg0 to any port 22 (Tailscale’s interface is tailscale0), and don’t expose 22 to the LAN unless you need to.
  • SSH still means keys. Passwords off, root off, as in the SSH hardening article. A VPN is not an excuse to turn passwords back on.
  • Treat keys like passwords. Laptop lost = remove the peer from wg0.conf or delete the device in the admin console, immediately.
  • Unauthenticated LAN services (printers, IoT, admin panels) are visible to every device on the VPN. Keep ACLs or AllowedIPs as narrow as possible.

Sources

FAQ

Can Tailscale read my traffic?

No. Traffic is WireGuard-encrypted end to end and private keys never leave the device. The coordination server sees public keys, IPs and policy; DERP relays forward already-encrypted packets they cannot decrypt.

Does plain WireGuard need a port forward?

Yes, one UDP port (for example 51820) forwarded to the server. But WireGuard never replies to a packet that fails the key check, so a scanner sees the port as closed. If you want no open port at all, use Tailscale.

How many people can use Tailscale for free?

At the time of writing (Oct 2026) the pricing page lists the free Personal plan at 6 users with unlimited devices. This number has changed several times; check the current pricing page before you plan around it.

Commands and settings were tested on sample systems. Try them on a test machine before production.