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
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
- Go to Zero Trust > Access > Applications in the Cloudflare dashboard
- Add an application (self-hosted type)
- Set the application domain (e.g.,
staging.your-domain.com) - 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
- Add the domain in the Cloudflare dashboard
- Update your registrar’s nameservers to the ones Cloudflare provides
- Wait for propagation (usually minutes, sometimes up to 24h)
Proxied vs DNS-Only Records
| Record Setting | What Happens | Use For |
|---|---|---|
| Proxied (orange cloud) | Traffic flows through CF’s network; DDoS protection, caching, Workers active | Web traffic, APIs |
| DNS-only (gray cloud) | CF just resolves the DNS; traffic goes direct to origin | Mail 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
| Mode | Behavior | Use For |
|---|---|---|
| Managed | Cloudflare decides if challenge is needed | Most forms |
| Non-interactive | Never shows a challenge, still verifies | API endpoints, invisible protection |
| Invisible | Like non-interactive but with fallback challenges | High-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.