Guide

How to Reach a Home Server Behind CGNAT

You forwarded the port. You checked the firewall. From inside the house it works; from outside it times out. Here is why that happens, how to confirm it, and every option that actually fixes it — including the free ones that are a better fit than paying us.

First, confirm it is really CGNAT

Rule it in before you spend a weekend on it, because the symptoms overlap with a plain misconfiguration. Open your router's status page and find the WAN address — what your router believes it holds on the ISP's side. Then, from any machine on that network, ask the internet what address it sees you coming from.

$ curl -4 https://ifconfig.me
203.0.113.44

If those two addresses match, you are not behind CGNAT and your problem is somewhere else — a router firewall rule, a forwarding entry pointed at a stale DHCP lease, or a host firewall on the server itself. If they differ, your traffic is being translated a second time somewhere upstream, and that upstream box is not yours.

The WAN address usually gives it away on sight. Anything in 100.64.0.0/10 is shared address space, reserved by RFC 6598 for exactly this purpose. Some ISPs use ordinary private ranges instead — 10.0.0.0/8 is common — less obvious, same meaning: you hold an address that cannot be routed on the public internet.

Why this breaks inbound connections specifically

NAT is not a firewall, though it behaves like one from outside. It is a translation table whose entries are created by outbound packets. When your laptop opens a connection, your router picks a spare port on its public address, writes down "traffic arriving here belongs to 192.168.1.20 port 54321", and rewrites the packet on the way out. Replies hit that port, the router finds the entry and delivers them. The mapping exists because you created it by sending something first.

An unsolicited inbound packet has no such entry: it arrives with a destination port nobody asked about, the router finds nothing in its table, and drops it. Port forwarding hand-writes a permanent entry — "anything on port 443 goes to 192.168.1.20, always, asked for or not."

The problem under CGNAT is that there are two translation layers and you only control one. Your router's public-looking address is not public. It is an address on your ISP's internal network, and the box performing the second translation sits in their datacentre, shared by hundreds or thousands of subscribers on one pool of real addresses. There is no interface for you to write a forwarding entry into it, and there could not sensibly be one: port 443 on the shared public address can only ever belong to a single subscriber, and it is not going to be you.

So the rule you wrote on your own router is correct and does nothing. It solves the inner NAT; the outer one still has nowhere to send the packet, and drops it before it reaches your equipment. That explains the exact shape of the symptom: fine from inside, dead from outside, and no amount of reconfiguring your own hardware changes it.

What actually works

Five approaches, roughly in order of how much they cost you. Try them in this order — the first two are free and most people stop there.

1. Ask your ISP for a public address

Genuinely the first thing to try, and it is skipped constantly. Many ISPs will move an account off CGNAT on request — sometimes free, sometimes for a small fee, sometimes only on a business plan. Some will put the modem in bridge mode, handing your router the public address directly. Ask for "a public IPv4 address, not CGNAT": front-line support often does not recognise "static IP" as the same request and will quote you a business circuit. If they say yes, you are done and everything below is unnecessary.

2. Use IPv6, if you have real IPv6

CGNAT exists because IPv4 addresses ran out. IPv6 did not run out, so most ISPs that deploy CGNAT hand out genuine, globally routable IPv6 alongside it — often a /56 or /64 to your router, with every device getting a real address. There is no translation layer, so inbound works natively once you open the firewall.

The catch is entirely on the client side: whoever reaches your server must have IPv6 themselves. For something you use personally from a modern mobile network, usually fine. For a public service, a vendor's webhook sender, or a game server with players on mixed connections, not — a meaningful share of the internet still cannot open an IPv6 connection, and you will not be able to tell which visitors silently failed.

Check first: curl -6 https://ifconfig.me from the server. If that returns an address and it matches what your router shows, you have real IPv6 and it costs nothing to use.

3. A reverse tunnel to a hosted endpoint

ngrok, Cloudflare Tunnel and Tailscale Funnel all work the same way at the mechanical level, and it is the same trick that gets around CGNAT: your machine makes an outbound connection to a server that does have a public address, and holds it open. Because your machine initiated it, both NAT layers have a mapping for it. Traffic for you arrives at the provider, travels back down that already-open connection, and reaches your server. CGNAT never has to accept an unsolicited packet, so it never has to drop one.

These are excellent tools and for many readers one of them is the correct answer. What you get is a hostname on somebody else's domain, terminating on their infrastructure, usually shaped around HTTP. What you do not get is an address of your own.

4. Rent a VPS and build the tunnel yourself

A small virtual server costs a few dollars a month and comes with a real public address. Put WireGuard on it, connect your home machine, and forward the ports you need across the tunnel with iptables or nftables. This works for arbitrary TCP and UDP, not just HTTP, and the address is stable for as long as you keep the server.

It is the honest DIY answer and a completely reasonable thing to do. The cost is not the five dollars — you now operate a second machine: kernel updates, a firewall you wrote, keys to rotate, and a load-bearing NAT configuration whose details you will have forgotten in six months when it breaks. If you enjoy that, it is the cheapest real address you will find.

5. Lease an address that is routed to your machine

The last option inverts the tunnel. Instead of forwarding a few ports from a server you rent, a network that owns address space assigns you one of its addresses and announces it by BGP, then routes everything destined for it down a tunnel to your hardware. Your machine still dials out, so CGNAT is still bypassed by the same mechanism as option 3 — but what arrives at the other end is a whole address rather than a hostname or a port mapping.

This is what TunnelNet does, and it is the last section of this page.

Choosing between them, honestly

Use Cloudflare Tunnel if you serve HTTP

If you are exposing a web app and a hostname like app.yourdomain.com is what people will type, Cloudflare Tunnel is free, well-engineered, and brings TLS, caching and DDoS absorption you would otherwise build yourself. It is a better answer than buying an address from us. Its limits appear when the protocol is not HTTP, or something must reference you by address rather than name. Longer comparison.

Use Tailscale if the audience is you

If the machines reaching your server are machines you also control — your laptop, your phone, a box at a friend's house — a private mesh is the right shape and a public address is the wrong one. Tailscale is free at that scale and exposes nothing to the internet at all, a posture a public address cannot match. Where Funnel stops being enough.

Use ngrok for development

Testing an OAuth callback or a Stripe webhook against code on your laptop is exactly what ngrok is for, and nothing is faster. It stops being right when the thing becomes permanent: the URL is not yours and the session is not forever. What to move to.

You need an address when a name will not do

Three situations recur. A vendor or corporate firewall will whitelist an IP and not a hostname. The protocol is not HTTP — a game server, a DNS server, a bare TCP service — and HTTP-shaped tunnels either cannot carry it or charge for the privilege. Or the address itself is the point: permanent, attributable to you, and surviving a change of house or ISP. Full options comparison.

Why an address behaves differently from a tunnel

The distinction is worth being precise about, because it is the whole reason the last option exists.

A hosted tunnel gives you a name resolving to the provider's infrastructure. Connections terminate there and are relayed to you — often desirable, since you inherit their TLS termination and abuse filtering. But the address on the far end of any connection to you belongs to them and is shared with every other user. You cannot hand it to a vendor to whitelist, you cannot set reverse DNS on it, and if their reputation moves, yours moves with it.

A routed address is yours for as long as you lease it. It is announced from a specific autonomous system, it appears in the global routing table, and packets sent to it are carried to your machine unchanged. It behaves like an address on a rack in a datacentre, because at the routing layer that is exactly what it is — the only unusual part is the last hop being a tunnel to your living room rather than a cable to a switch.

Where TunnelNet fits

We lease one public IPv4 address from our own 23.187.152.0/24, announced by BGP from AS396500, and route it to a machine you already own — a home server, a laptop, a Windows box, WSL, a Mac, or a phone. It is $10/month for one address, and an IPv6 /56 comes with it. You install a small agent with a token from your dashboard, it brings up a WireGuard tunnel outbound, and the address is live. We announce from two US cities, Chicago and Newark, on anycast — the internet reaches you through whichever is closer, and if one goes down traffic moves to the other automatically, though recovery takes minutes rather than seconds because the WireGuard rekey dominates. SSH is open by default and everything else is closed until you open it, enforced at our edge rather than on your machine.

Things it is not, so you do not find out later: it is not a VPN and not anonymity — the address is permanently attributable to you, which is the point of it and the opposite of what a proxy sells. The base plan carries inbound traffic only; your outbound still leaves via your ISP unless you take the $20 plan. Outbound port 25 is blocked, so you cannot run a mail server on it today. And we do not publish an availability figure, because we have not been running long enough to have measured one honestly.

If your answer above was Cloudflare Tunnel or Tailscale, use those — they are free and they are better at what they do. If you got to the bottom of the list and you need an actual address, the current plans and prices are here.