My home server sat behind a static IP for years. Port forwarding, DDNS, the whole routine — it worked. Then my ISP migrated me to CGNAT (Carrier-Grade NAT), and every port-forwarding tutorial I had bookmarked became instantly useless.
CGNAT is the ISP-level NAT that puts you behind the same public IP as hundreds of other customers. You don't have a dedicated public address. You can't open ports. UPnP doesn't help. The traditional playbook — forward port 443 on your router, point a domain at it — collapses completely.
If you need to reach a service behind CGNAT, here are the real options and what each one costs you.
The SSH Tunnel Escape
The simplest escape route is a reverse SSH tunnel. You provision a cheap VPS with a public IP, then from your CGNAT'd machine:
ssh -R 8080:localhost:3000 user@your-vps
Now your-vps:8080 forwards to port 3000 on your home machine. It's raw, it works, and it requires exactly one dependency: an SSH server you control.
The trade-off surfaces fast. That single tunnel is a single point of failure. When the connection drops — and it will — you need autossh or a systemd restart loop to bring it back. Every service you expose needs its own -R flag. If you have fifteen services with different ports, you have fifteen tunnel flags or a jump box. Latency doubles because traffic goes server → VPS → home instead of server → home. And you're managing a VPS just to be a relay — the CGNAT'd box never actually reaches the open internet on its own terms.
Cloudflare Tunnel (cloudflared)
Cloudflare Tunnel replaces the SSH relay with Cloudflare's edge network. You install cloudflared on your CGNAT'd machine, authenticate it to your domain, and routes appear:
cloudflared tunnel create my-tunnel
cloudflared tunnel route dns my-tunnel service.example.com
cloudflared tunnel run
The setup is smoother than raw SSH. Cloudflare handles the keepalive, the DNS, and the TLS termination. You get DDoS protection and analytics for free.
The cost is architectural. Every byte of traffic flows through Cloudflare's infrastructure — you are routing your service through a third-party CDN whether you need it or not. Cloudflare can inspect, terminate, or reshape that traffic. If your service uses non-HTTP protocols (gRPC without HTTPS, raw TCP, UDP-based workloads), you hit Cloudflare's protocol restrictions. And the tunnel is tied to a Cloudflare account and domain — not something you can move between providers.
Overlay Networks (Tailscale, ZeroTier, Nebula)
Overlay networks solve the problem differently. Instead of a single tunnel to one relay, they create a virtual network interface that connects all your machines, CGNAT or not, as if they share a LAN.
Tailscale is the most polished option here. You install tailscale up on every machine, and they find each other through a coordination server plus NAT traversal:
tailscale up --advertise-routes=192.168.1.0/24
WireGuard underneath, automatic key rotation, MagicDNS for naming. Machines behind CGNAT connect directly to each other when hole punching succeeds, falling back to DERPs (Tailscale's relay servers) when it doesn't.
ZeroTier offers similar semantics with a different architecture — a software-defined switch rather than a WireGuard mesh. Nebula gives you more control over the certificate authority and lighthouse nodes if you want to self-host the coordination.
The overlay approach gives you a flat network. Your home server, your cloud VPS, your laptop — they all get an address in the overlay and can talk on any port. You don't think about CGNAT anymore once the overlay is up.
The friction is that an overlay network is a whole additional network layer. You're running a mesh protocol, a coordination service, key management. For reaching one service from one client, it's a lot of machinery. And if your use case involves exposing a service to users who aren't on the overlay, you still need a gateway or a funnel — the overlay is great for machine-to-machine within your fleet, less so for general public access.
Pilot Protocol: Overlay With a Different Starting Point
Pilot Protocol starts from the same observation as Tailscale and ZeroTier — CGNAT means you cannot rely on a publicly routable address — but makes a different set of design decisions.
Where Tailscale builds on WireGuard and a central coordination server, Pilot implements its own encrypted UDP tunnel layer (X25519 key exchange, AES-GCM) in Go with zero external dependencies. NAT traversal works the same way — STUN-style hole punching with a beacon relay fallback — but the network model is peer-to-peer all the way down. There is no coordination server. Every node gets a permanent virtual address that survives restarts, IP changes, and cloud migrations. Discovery happens through a rendezvous registry, not a central management plane.
For reaching a service behind CGNAT, the flow looks like this:
curl -fsSL https://pilotprotocol.network/install.sh | sh
pilotctl daemon start
pilotctl send-message <peer> --data '{"service":"http","port":3000}'
The CGNAT'd machine and the remote client each run the daemon, handshake, and traffic flows over the encrypted tunnel. No SSH flags, no VPS bill, no cloudflare config — just a running daemon on each end.
The trade-off is maturity and ecosystem. Tailscale has years of polish, a management console, ACLs, and enterprise integrations. Pilot is newer, open source (AGPL-3.0), and designed specifically for AI agent workloads — it ships with an app store of agent-native tools (discover → install → call), a typed IPC model, and 435 service agents on the overlay. If your use case is connecting two AI agents across a CGNAT boundary, Pilot's tooling fits naturally. If you're connecting two humans' laptops, Tailscale is probably the smoother path.
Which One Should You Pick?
This depends entirely on what you're trying to reach.
- One-off service, quick fix: SSH reverse tunnel with autossh. Ugly but fast.
- Web service, single domain: Cloudflare Tunnel. Clean setup if you're okay routing through their edge.
- Fleet of machines, team access: Tailscale or ZeroTier. The overlay model solves CGNAT transparently.
- Two AI agents that need to find each other on different ISPs: Pilot Protocol. It's built for agent-to-agent networking and the app store gives you tooling on top.
CGNAT is not going away — IPv4 exhaustion means more ISPs adopt it every year. The question isn't whether you'll need one of these escape routes, but which failure mode you prefer to manage. Pick the one whose trade-offs match your actual use case, not the one that looks simplest on a blog post diagram.
Top comments (0)