Infrastructure / Networking

How Cloudflare Tunnel works

Serving whenkat.com from a home network — no open ports, no port forwarding, no static IP.


The problem with home internet

Home internet connections have three properties that make self-hosting difficult:

The traditional workaround is port forwarding: punch a hole in your router so traffic on port 443 reaches your server. This works, but it exposes your home IP, requires a dynamic DNS solution, and leaves you managing TLS certificates manually.

Cloudflare Tunnel eliminates all of this. No port forwarding. No exposed home IP. No dynamic DNS. Cloudflare handles TLS.

How the tunnel works

The key insight: the connection is outbound. Your server calls out to Cloudflare — Cloudflare never calls in. Your router sees this as normal outbound HTTPS traffic and lets it through. No rules to configure.

cloudflared is a small daemon that runs inside the cluster. On startup it opens a persistent connection to Cloudflare's edge using QUIC (or HTTPS as fallback). Cloudflare's edge then forwards incoming requests for whenkat.com down that tunnel to cloudflared, which proxies them to the local service.

Browser whenkat.com HTTPS Cloudflare Edge DDoS protection TLS termination WAF tunnel outbound only KUBERNETES CLUSTER cloudflared ×2 replicas NGF HTTPRoute → blog svc home router — no open ports required
  1. 01Browser sends HTTPS request for whenkat.com. DNS resolves to Cloudflare's edge via the CNAME <tunnel-id>.cfargotunnel.com.
  2. 02Cloudflare terminates TLS, applies DDoS protection and WAF rules, then looks up which tunnel is registered for whenkat.com.
  3. 03The request is forwarded down the persistent tunnel connection to the cloudflared pod inside the cluster. This connection was opened outbound by cloudflared at startup — your router never sees inbound traffic.
  4. 04cloudflared proxies the request to http://blog.blog.svc.cluster.local:80 as configured in the tunnel ingress rules.
  5. 05The blog pod serves the pre-built static HTML/CSS/JS. Response travels back the same path.

What runs in the cluster

The tunnel is provisioned entirely with OpenTofu. Three resources:

ResourceWhat it does
cloudflare_zero_trust_tunnel_cloudflared Creates the tunnel in Cloudflare. Generates a secret token the cloudflared daemon uses to authenticate.
cloudflare_zero_trust_tunnel_cloudflared_config Defines ingress rules — which hostnames route to which internal services.
cloudflare_record Creates the CNAME records for whenkat.com and www.whenkat.com pointing at <tunnel-id>.cfargotunnel.com.

The token is stored in a Kubernetes secret in the cloudflared namespace and mounted as TUNNEL_TOKEN into the deployment:

kubectl create secret generic cloudflared-token \
  --from-literal=token=$(cat secrets/cloudflared-token.txt) \
  -n cloudflared

The cloudflared Deployment runs 2 replicas for availability. Each pod opens its own connection to Cloudflare's edge — if one pod restarts, traffic continues through the other.


Why this is more secure than port forwarding

Your home IP is never exposed. DNS for whenkat.com resolves to Cloudflare's IPs, not yours. Even if someone enumerates your DNS records, they see Cloudflare.
No attack surface on your router. Port 443 is not open. There is no service listening for inbound connections at the network boundary. The only traffic crossing your router is outbound HTTPS from cloudflared to Cloudflare's edge.

Cloudflare's edge absorbs volumetric DDoS attacks before they reach your network. Your home connection never sees the traffic spike.