Cloudflare Tunnel for Publishing a Web Service Behind CGNAT
Cloudflare Tunnel can publish a web application without an inbound IPv4 port forward. A cloudflared connector near the origin opens outbound connections to Cloudflare, and a public hostname sends matching requests through those connections to the configured local service. CGNAT does not block this model because the connection begins inside the homelab.
Use the tunnel for the right audience
A public hostname can make a site reachable by anyone unless another control is added. That is appropriate for a deliberately public website, not automatically for a router, hypervisor, storage interface, camera system, or private dashboard. Protect private applications with Cloudflare Access or keep them on a private network such as Tailscale.
| Application | Safer starting design |
|---|---|
| Public website or webhook receiver | Public hostname, hardened origin, application authentication where required. |
| Household dashboard | Cloudflare Access policy before the origin, or private Tailscale access. |
| SSH or remote administration | Private access first; follow Cloudflare’s client-side access design if Tunnel is specifically required. |
| Arbitrary public TCP or UDP service | Do not assume an HTTP public hostname is a transparent port forward; verify protocol support and client requirements. |
Prepare the origin before the tunnel
- Patch the operating system, web server, runtime, and application.
- Give the application a stable local address or run
cloudflaredon the same host. - Bind the origin to loopback when the connector is local, or allow the origin port only from the connector’s network identity.
- Remove old WAN port forwards and verify the origin is not separately reachable from untrusted networks.
- Back up the application and record how to disable the tunnel without losing local administration.
Cloudflare protects the path from its edge to the connector, but the application remains responsible for authorization, input handling, updates, data protection, and safe failure behavior.
Create a named tunnel and one public hostname
- Add the intended domain to the appropriate Cloudflare account and confirm control of its DNS zone.
- Create a named tunnel using Cloudflare’s current dashboard or command-line procedure.
- Install
cloudflaredfrom an official source on a maintained connector host. - Map one hostname, such as
app.example.net, to the exact local HTTP or HTTPS origin. - Add a final catch-all rule that returns an error rather than forwarding unexpected hostnames.
- Run the connector as a supervised service and confirm it starts after a reboot.
Put identity in front of private applications
For a non-public application, create a Cloudflare Access application for the hostname before inviting users. Use a maintained identity provider, require multifactor authentication where available, and write an allow policy for named people or groups rather than an entire email domain unless that broad access is intentional. Test both an authorized and unauthorized account.
Enforce Access at Cloudflare’s edge. If the origin must independently verify identity, explicitly configure and document Cloudflare’s supported JWT or service-token validation and make the application reject missing or invalid assertions. Never trust an identity header supplied by an arbitrary local client. Keep an independent local recovery path so an Access, DNS, or internet outage does not permanently block administration.
Restrict network egress and monitor the connector
Cloudflare documents outbound TCP or UDP port 7844 from cloudflared to its tunnel endpoints. Protocol fallback behavior, endpoint ranges, and requirements can change, so use Cloudflare’s current firewall documentation rather than copying a fixed address list from an old guide. Permit the DNS resolution and any package-repository or update traffic the maintained connector actually requires. Apply restrictions only after recording these dependencies; overly narrow rules can make a tunnel fail intermittently. No unsolicited inbound rule is required for the connector.
- Monitor connector status, restarts, authentication failures, and application errors.
- Review public DNS and Access policy whenever hostnames or administrators change.
- Keep more than one connector only when the origin and surrounding infrastructure can actually tolerate a failure.
- Test from outside the homelab and confirm the old public IP and unrelated hostnames do not reach the origin.
- When retiring the service, remove its hostname, route, Access application, connector credentials, and origin listener.
dispelled