Tailscale, FortiGate CVEs, and Remote Access That Doesn’t Suck
🚧 UNDER CONSTRUCTION 🚧 This post is a work in progress.
The Problem#
I need to reach into my home network from anywhere. SSH into nodes, check Grafana dashboards, access services that aren’t exposed through Cloudflare. The traditional answer is a VPN, and I have a FortiGate sitting right there with IPSec and SSL VPN capabilities built in.
I don’t use them.
FortiGate and the CVE Treadmill#
Fortinet firewalls have a CVE problem. Not a small one. A recurring, systemic, “maybe we should talk about this” problem.
In the last few years alone, FortiOS has had multiple critical pre-auth RCE vulnerabilities. CVE-2024-21762 was a pre-authentication out-of-bounds write in the SSL VPN that CISA added to the Known Exploited Vulnerabilities catalog. CVE-2023-27997 was a heap buffer overflow in the SSL VPN, also pre-auth, also actively exploited. CVE-2022-42475 was another SSL VPN heap overflow, also pre-auth, also exploited in the wild before the patch dropped.
That’s three critical pre-auth RCEs in the SSL VPN component alone across three consecutive years. The pattern is clear: if you expose FortiGate’s SSL VPN to the internet, you are running a service with a track record of getting popped before patches are available.
Patching a FortiGate is its own adventure. The firmware upgrade process requires a reboot, which means a maintenance window, which means downtime for every VLAN, every DHCP server, every firewall policy, and every NAT rule that the box handles. For a homelab that’s also the primary router for the household, that’s not a “just patch it Tuesday” situation. And FortiGate firmware upgrades have their own history of breaking things. Configuration incompatibilities between versions, features that change behavior silently, DHCP leases that don’t survive the reboot cleanly.
So the calculus is: expose a VPN service with a known history of critical vulns and commit to a patching treadmill that requires downtime, or find another way in.
Tailscale: Ass-Wipe Mode Remote Access#
Tailscale is the ass-wipe mode answer. It’s a mesh VPN built on WireGuard that handles all the key exchange, NAT traversal, and peer discovery through a SaaS coordination server. You install it, you authenticate, and your devices can talk to each other. No port forwarding. No firewall rules. No exposed services. No CVE treadmill.
It’s private in the sense that the traffic is encrypted end-to-end with WireGuard and the coordination server never sees your data. It’s not private in the sense that Tailscale (the company) runs the control plane, handles key distribution, and knows which devices are in your network. You’re trusting a SaaS provider with your network topology. For a homelab, that tradeoff is fine. For a classified government network, probably not.
The setup is genuinely trivial. The Ansible role installs Tailscale, authenticates with an auth key from AWS Secrets Manager, and the node joins the tailnet. Every host in the lab is reachable from my laptop, my phone, or any other device on the tailnet, regardless of what network I’m on.
The Exit Node#
One of the k8s nodes (nebula-3) runs as a Tailscale exit node. This means I can route all my traffic through the homelab when I’m on an untrusted network. Coffee shop WiFi? Route through the exit node. Hotel network? Exit node. It’s like a traditional VPN but without exposing any service on the FortiGate.
The exit node runs as a pod in the k8s cluster with hostNetwork: true and advertises the home subnet (10.x.x.0/20) so all internal services are reachable. The FortiGate doesn’t know or care. Traffic arrives on the LAN from a local IP, and the firewall treats it like any other local traffic.
Why Not Just Use the FortiGate VPN#
Three reasons:
The CVE history. I manage the FortiGate with Terraform and I like it for what it does (routing, firewall policies, DHCP, NAT). But I don’t trust it as an internet-facing VPN endpoint. The attack surface is too large and the track record is too bad.
Patching requires downtime. The FortiGate is the router for the entire house. Firmware upgrades mean everything goes down. Tailscale updates are per-node, zero-downtime, and usually automatic.
Tailscale is ass-wipe mode. Install, auth, done. No certificates to manage, no split tunnel configs to debug, no NAT traversal to figure out. It just works. I’d rather spend my time on the k8s cluster or the monitoring stack than fighting VPN configuration.
The Tradeoff#
You’re trusting Tailscale’s coordination server. If Tailscale gets compromised, an attacker could potentially inject keys or manipulate your network topology. The actual traffic is still WireGuard-encrypted and they can’t see it, but the control plane is theirs.
For a homelab, this is an acceptable tradeoff. The alternative is exposing a FortiGate SSL VPN with a history of pre-auth RCEs to the internet. I’ll take the SaaS dependency.