Networking Essentials

Cloudflare’s networking services connect your Workers and local services to the internet. This covers the developer-relevant parts: Tunnels for exposing services, Access for auth, DNS for domains, and Turnstile for bot protection.

Tunnels

Tunnels let you expose a local service (running on your machine or a private server) to the internet through Cloudflare’s network. No port forwarding, no public IP required.

How Tunnels Work

flowchart LR
    A["Browser"] --> B["CF Edge\n(300+ locations)"]
    B --> C["Tunnel\n(encrypted)"]
    C --> D["cloudflared\n(your server)"]
    D --> E["Local Service\n(localhost:8080)"]

The cloudflared daemon runs on your server and creates an outbound connection to Cloudflare’s edge. Traffic flows: browser -> CF edge -> tunnel -> cloudflared -> local service. Your origin never opens inbound ports.

Quick Setup

# Install cloudflared
brew install cloudflared       # macOS
# or: sudo apt install cloudflared  # Debian/Ubuntu

# Login (one time)
cloudflared tunnel login

# Create a named tunnel
cloudflared tunnel create my-tunnel

# Run it - expose localhost:8080 at my-tunnel.your-domain.com
cloudflared tunnel route dns my-tunnel my-tunnel.your-domain.com
cloudflared tunnel run --url http://localhost:8080 my-tunnel

Quick Tunnel (No Config)

For quick development, cloudflared tunnel --url creates a temporary public URL:

# Instant public URL for local dev server
cloudflared tunnel --url http://localhost:3000
# Prints: https://random-name.trycloudflare.com

This is useful for testing webhooks locally - point the webhook provider at the temporary URL.

Use Cases for Developers

  • Webhook development: receive GitHub/Stripe/etc webhooks on your local machine
  • Staging environments: expose a dev server to testers without deploying
  • Private service access: connect a Worker to an internal API behind a firewall
  • Self-hosted services: expose home servers (media, git, monitoring) securely

Access

Cloudflare Access adds SSO-based authentication in front of any web application. You define who can access a URL, and Cloudflare handles the login flow before traffic reaches your origin.

When to Use Access

  • Protect staging/preview environments with SSO
  • Add auth to internal tools without changing the app
  • Gate access to admin dashboards

Basic Setup

  1. Go to Zero Trust > Access > Applications in the Cloudflare dashboard
  2. Add an application (self-hosted type)
  3. Set the application domain (e.g., staging.your-domain.com)
  4. Create a policy: allow emails ending in @your-company.com

Access supports identity providers (Google, GitHub, Okta, SAML) and one-time PIN via email. For most developer setups, GitHub or Google OAuth is sufficient.

Programmatic Access

Workers can verify Access JWTs to check identity:

// Verify the CF-Access-Jwt-Assertion header
const jwt = request.headers.get("Cf-Access-Jwt-Assertion");
if (!jwt) return new Response("Unauthorized", { status: 401 });

// Validate against your Access policy's public keys
// CF_ACCESS_AUD is your application's audience tag
const isValid = await verifyAccessJwt(jwt, env.CF_ACCESS_AUD);

DNS

Adding a Domain

  1. Add the domain in the Cloudflare dashboard
  2. Update your registrar’s nameservers to the ones Cloudflare provides
  3. Wait for propagation (usually minutes, sometimes up to 24h)

Proxied vs DNS-Only Records

Record SettingWhat HappensUse For
Proxied (orange cloud)Traffic flows through CF’s network; DDoS protection, caching, Workers activeWeb traffic, APIs
DNS-only (gray cloud)CF just resolves the DNS; traffic goes direct to originMail servers, SSH, non-HTTP services

Common Records

Type  Name              Content              Proxy
A     example.com       192.0.2.1            Proxied
AAAA  example.com       2001:db8::1          Proxied
CNAME www               example.com          Proxied
CNAME tunnel            <tunnel-id>.cfargotunnel.com  Proxied
MX    example.com       mail.provider.com    DNS only
TXT   example.com       "v=spf1 ..."         DNS only

DNSSEC

Enable DNSSEC in the dashboard under DNS > Settings. Cloudflare provides a DS record - add it at your registrar. This prevents DNS spoofing.

Turnstile

Turnstile is Cloudflare’s CAPTCHA replacement. It verifies visitors are human without showing puzzles, using browser signals and machine learning.

Client-Side Integration

<!-- Add the Turnstile widget -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form action="/submit" method="POST">
  <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
  <button type="submit">Submit</button>
</form>

The widget generates a cf-turnstile-response token that you verify server-side.

Server-Side Verification

app.post("/submit", async (c) => {
  const formData = await c.req.formData();
  const token = formData.get("cf-turnstile-response");

  // Verify with Cloudflare
  const result = await fetch(
    "https://challenges.cloudflare.com/turnstile/v0/siteverify",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        secret: c.env.TURNSTILE_SECRET,
        response: token,
        remoteip: c.req.header("CF-Connecting-IP"),
      }),
    }
  );

  const outcome = await result.json<{ success: boolean }>();
  if (!outcome.success) {
    return c.json({ error: "verification failed" }, 403);
  }

  // Process the form
  return c.json({ submitted: true });
});

Modes

ModeBehaviorUse For
ManagedCloudflare decides if challenge is neededMost forms
Non-interactiveNever shows a challenge, still verifiesAPI endpoints, invisible protection
InvisibleLike non-interactive but with fallback challengesHigh-security forms

Turnstile is free for unlimited use. Set it up in the Cloudflare dashboard under Turnstile, create a site, and get the site key and secret key.