Cloudflare Zero Trust — Step-by-Step Configuration Runbook
Hands-on companion to the Implementation & Best-Practice Onboarding Guide. Where the guide explains why and in what order, this runbook gives the exact navigation paths, field-by-field settings, commands, and config snippets to type or click. Section letters map to the guide's numbered sections.
| Dashboards | Zero Trust: https://one.dash.cloudflare.com · Account: https://dash.cloudflare.com |
| Team domain | https://<team-name>.cloudflareaccess.com (used in every IdP callback URL) |
| Last reviewed | 2026-06-08 |
How to read this runbook
- Path:
A → B → Cmeans click through those dashboard menus in order. - Field tables list every setting on a screen, its recommended value, and notes. Replace
<placeholders>with your values. - ⭐ = recommended best-practice value · ⚠️ = common mistake.
- Menu labels evolve; if a label moved, use the nearest equivalent (paths under Settings, Integrations, Access controls, Traffic policies).
A. Account creation & organization setup (Guide §2)
A.1 Activate Zero Trust
- Sign in at
https://dash.cloudflare.com→ left nav Zero Trust (or go tohttps://one.dash.cloudflare.com). - Choose a plan → enter a team name when prompted → add a payment method (required even on Free).
A.2 Set the team name
Path: Settings → Custom Pages / Settings → Team name and domain
| Field | Value | Notes |
|---|---|---|
| Team name | <your-company-short-name> |
⭐ Stable, recognizable; becomes https://<team-name>.cloudflareaccess.com. ⚠️ Renaming later breaks every IdP callback URL + MDM config |
A.3 Organization defaults to set on day one
| Setting | Path | Recommended |
|---|---|---|
| Account MFA | dash.cloudflare.com → My Profile → Authentication |
⭐ Enable for all admins before anything else |
| Admin roles | dash.cloudflare.com → Manage Account → Members |
⭐ ≥2 Super Admins (break-glass); least-privilege for others |
| Custom login/block pages | Settings → Custom Pages |
Brand them — reduces helpdesk tickets |
| Logpush (Access + Gateway) | Settings → Logs → Logpush (or Logs → Logpush) |
⭐ Wire to SIEM/R2/S3 now, not later |
Validate: https://<team-name>.cloudflareaccess.com shows your org login page; Settings → General shows the correct plan + team name.
B. Identity provider (IdP) integration (Guide §3)
All OIDC-based IdPs use the same Cloudflare callback (redirect) URL:
https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/callback
Google also needs the Authorized JavaScript origin: https://<your-team-name>.cloudflareaccess.com
B.1 Microsoft Entra ID (Azure AD) — full walkthrough
Step 1 — Register the app (Entra admin center https://entra.microsoft.com)
Applications → Enterprise applications → New application → Create your own application.- Name it (e.g.
Cloudflare Access) → select Register an application to integrate with Microsoft Entra ID (App you're developing) → Create. ⚠️ Do not pick a gallery app. - Under Redirect URI, platform = Web, value =
https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/callback - Register.
- Go to
Applications → App registrations → All applications →your app. Copy Application (client) ID and Directory (tenant) ID. - Client credentials → Add a certificate or secret → New client secret → name it, set an expiry → copy the Value immediately (shown once). ⚠️ When it expires, all logins fail — calendar the renewal.
Step 2 — API permissions
App registrations → All applications → your app → API permissions → Add a permission → Microsoft Graph → Delegated permissions, enable these 7:
| Permission | Purpose |
|---|---|
email |
User email |
offline_access |
Refresh tokens |
openid |
OIDC sign-in |
profile |
Basic profile |
User.Read |
Read the signed-in user |
Directory.Read.All |
Read directory |
GroupMember.Read.All |
⭐ Read group membership (required for group policies) |
Then Add permissions → Grant admin consent.
Step 3 — Add to Cloudflare
Zero Trust → Integrations → Identity providers → Add new identity provider → Azure AD:
| Field | Value |
|---|---|
| Application (client) ID | from Step 1.5 |
| Client secret | from Step 1.6 |
| Directory (tenant) ID | from Step 1.5 |
| ⭐ Support Groups | On — lets Cloudflare read Entra group membership |
| Proof Key for Code Exchange (PKCE) | On |
| Enable SCIM | ⭐ On for auto user/group sync + session revocation |
| Email claim | e.g. preferred_username if UPN ≠ email |
Save → Test (confirms email + groups in the identity payload).
API alternative:
POST https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/identity_providerswith{"name":"Entra ID","type":"azureAD","config":{"client_id":"…","client_secret":"…","directory_id":"…","support_groups":true}}(token needs Access: Organizations, Identity Providers, and Groups — Write).
B.2 Okta (OIDC) — full walkthrough
- In Okta, create an OIDC → Web app integration. Set Sign-in redirect URIs =
https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/callback - In the app's General tab, copy the Client ID and Client secret.
- In Cloudflare
Zero Trust → Integrations → Identity providers → Add new → Okta:
| Field | Value |
|---|---|
| App ID | Okta Client ID |
| Client secret | Okta Client secret |
| Okta account URL | your Okta domain, e.g. https://my-company.okta.com |
| Authorization Server ID | from Okta (if using a custom auth server) |
| Okta API token (optional) | ⭐ Required if you have >100 Okta groups (read-only token prevents group lookup failures) |
Save → Test.
B.3 Google Workspace (OIDC) — full walkthrough
- In Google Cloud Console → APIs & Services → Credentials → Create OAuth client ID → Web application.
- Authorized JavaScript origins:
https://<your-team-name>.cloudflareaccess.com - Authorized redirect URIs:
https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/callback - Create → copy the OAuth Client ID and Client secret.
- In Cloudflare
Identity providers → Add new → Google Workspace: enter Client ID + Secret; provide the admin email / domain-wide settings so Cloudflare can read Groups. - Save → Test.
B.4 Global / independent MFA
Path: Zero Trust → Access controls → Access settings
| Setting | Recommended |
|---|---|
| Allow MFA methods | Select your approved methods |
| Authentication duration | e.g. 24h (shorter for sensitive) |
| Use identity provider MFA | ⭐ On — honors IdP amr claim, avoids double-prompt |
| Apply global MFA settings by default | ⭐ On |
Validate every IdP: the Test button returns the expected email + groups; disabling a test user in the IdP revokes access within the SCIM sync window.
C. Device enrollment — Cloudflare One Client (WARP) (Guide §4)
C.1 Device enrollment permissions (the gate — do this first)
Path: Settings → WARP Client → Device enrollment permissions → Manage → Add a rule
| Field | Value | Notes |
|---|---|---|
| Rule name | Corporate employees |
|
| Rule action | Allow | (use Service Auth for token-based fleet/server enrollment) |
| Selector | Emails ending in | |
| Value | @yourco.com |
|
| Authentication / Login methods | select your IdP(s) | ⚠️ No matching rule → users see "you are not allowed to enroll" |
For silent MDM fleet enrollment, create a Service Auth rule and a service token (
Access → Service Auth → Service Tokens). ⚠️ Service tokens require a Service Auth rule — an Allow rule will not work for them.
C.2 Device profile settings
Path: Settings → WARP Client → Device settings → (edit Default profile or Add a profile)
| Setting | ⭐ Recommended (managed) | Notes |
|---|---|---|
| Service mode | Gateway with WARP | Full L3/L7 + DNS filtering (standard enterprise) |
| Switch lock | On (managed) | Prevents users disabling WARP |
| Auto connect | 1–5 min |
Re-enables after brief disconnect (e.g. captive portal). Value 0 = stays off until user reconnects |
| Captive portal detection | On | Lets users reach hotel/airport login pages |
| Allowed device protocols | per policy | e.g. allow/deny WARP over specific protocols |
| Mode switch / admin override | Locked (managed) |
Create separate profiles for Servers, BYOD, Contractors and match them by posture/identity selectors.
C.3 Split Tunnels
Path: within a device profile → Split Tunnels
| Scenario | Mode | What to configure |
|---|---|---|
| Managed laptops | Exclude (default) | Everything tunnels except listed exceptions. Default list already excludes 100.64.0.0/10 (CGNAT used by Cloudflare One). ⭐ Add back any local RFC-1918/CGNAT ranges you actually use |
| BYOD / personal | Include | ⭐ Only listed corporate IPs/domains tunnel — personal traffic stays private. Add your app domains + private CIDRs |
⚠️ Over-broad Include entries (or excluding local subnets you rely on) can black-hole LAN/Wi-Fi traffic when switching networks — test Ethernet↔Wi-Fi.
C.4 Distribute the Cloudflare root CA (required for HTTPS filtering / DLP / AI prompt inspection)
Path: Settings → Resources (download the Cloudflare certificate) → push to OS/browser trust stores via MDM before enabling TLS decryption (§F.3). ⚠️ Decryption before the CA is trusted breaks HTTPS fleet-wide.
C.5 MDM deployment (silent, pre-authenticated)
Push the client with parameters. Windows uses mdm.xml; macOS uses com.cloudflare.warp.plist. ⚠️ Local device settings take precedence over dashboard settings.
Common parameters
| Parameter | Type | ⭐ Value / purpose |
|---|---|---|
organization |
string | Your team name (required for managed enrollment) |
auth_client_id |
string | Service-token client ID, e.g. 88bf3b6d….access |
auth_client_secret |
string | Service-token secret. ⚠️ Token needs Service Auth enrollment permission, not Allow |
service_mode |
string | warp (Gateway with WARP) |
onboarding |
boolean | false → suppress welcome screens (silent install) |
auto_connect |
integer | 1 (connect immediately; 0 = allow off indefinitely). ⚠️ Replaces deprecated enabled — you must remove enabled if you use this |
switch_locked |
boolean | true on managed devices |
display_name |
string | Org nickname in the client GUI (required inside a configs array) |
support_url |
string | Helpdesk link shown in client |
unique_client_id |
string | Stable device identifier for posture/serial mapping |
enable_post_quantum |
boolean | true to enable PQ tunnel crypto |
enable_netbt |
boolean | false (default; only enable for legacy NetBIOS apps) |
environment |
string | normal or fedramp_high |
organization_configs / configs[] |
dict/array | Multi-org / config switching (newer clients) |
macOS .plist example (service-token enrollment, silent):
<dict>
<key>organization</key> <string>your-team-name</string>
<key>auth_client_id</key> <string>88bf3b6d86161464f6509f7219099e57.access</string>
<key>auth_client_secret</key> <string>bdd31cbc4dec990953e39163fbbb194c93313ca9f0a6e420346af9d326b1d2a5</string>
<key>service_mode</key> <string>warp</string>
<key>onboarding</key> <false/>
<key>auto_connect</key> <integer>1</integer>
<key>switch_locked</key> <true/>
<key>support_url</key> <string>https://help.yourco.com</string>
</dict>
The equivalent Windows mdm.xml uses the same keys in <RegistrationData> XML.
C.6 Device posture checks
Path: Settings → WARP Client → Device posture (or Reusable components → Posture checks → Add)
| Category | Examples | Usable in |
|---|---|---|
| Client checks (Cloudflare One Client) | OS version, Disk encryption, Firewall, Client certificate, File/Registry/Application present, Serial number list, Domain joined | Access and Gateway |
| Service-to-service (3rd-party) | CrowdStrike, SentinelOne, Microsoft Intune, Tanium | Access (⚠️ Tanium not supported in Gateway) |
| Access integrations | (various) | Access only |
⭐ For OS-version checks use the latest qualified stable (e.g. macOS ≥ 15.1), not the absolute newest, so a same-day OS release doesn't lock users out.
Validate: device shows Connected with the right profile; appears under My Team → Devices; a posture check (e.g. disk encryption) reports correctly.
D. Connect private apps/networks — Cloudflare Tunnel & Connector (Guide §5.1)
D.1 Cloudflare Tunnel via dashboard (remotely-managed — recommended)
Path: Networks → Tunnels → Create a tunnel → Cloudflared → name it → Save → copy the install command for your OS. Then map Public Hostname or Private Network routes in the dashboard.
One-line connector install (token from the dashboard):
# macOS
brew install cloudflared && sudo cloudflared service install <YOUR_TUNNEL_TOKEN>
# Linux (Debian/RPM package already installed)
sudo cloudflared service install <YOUR_TUNNEL_TOKEN>
D.2 Cloudflare Tunnel via CLI (locally-managed)
cloudflared tunnel login # authenticate + pick a zone
cloudflared tunnel create <NAME> # creates tunnel + credentials JSON
cloudflared tunnel list # note the tunnel UUID
~/.cloudflared/config.yml:
tunnel: <TUNNEL-UUID>
credentials-file: /root/.cloudflared/<TUNNEL-UUID>.json
ingress:
- hostname: wiki.yourco.com
service: http://localhost:3000
- hostname: ssh.yourco.com
service: ssh://localhost:22
- service: http_status:404 # required catch-all
cloudflared tunnel route dns <NAME> wiki.yourco.com # create the DNS record
cloudflared tunnel ingress validate # validate config
cloudflared tunnel run <NAME> # test in foreground
sudo cloudflared service install # run as a service (production)
⭐ Run two cloudflared replicas (different hosts) per tunnel for high availability.
D.3 WARP Connector (site-to-site / mesh on a Linux host)
sudo warp-cli connector new <TOKEN> && sudo warp-cli connect
warp-cli status # expect "Status update: Connected"
E. ZTNA — Access applications & policies (Guide §5)
E.1 Add a self-hosted application
Path: Access → Applications → Add an application → Self-hosted
| Field | Value / recommendation |
|---|---|
| Application name | Internal Wiki |
| Session Duration | ⭐ 24h standard; 15m–No duration for crown-jewel apps |
| Application domain | wiki.yourco.com (must resolve to a tunnel/zone) |
| Identity providers | select the IdP(s) allowed for this app |
| Instant Auth | On if a single IdP (skips the chooser) |
| App Launcher visibility | On (shows in the user portal) |
| Accept all available identity providers | Off if you scope per-app |
E.2 Build an Access policy
Path: within the app → Policies → Add a policy
| Field | Value |
|---|---|
| Policy name | ⭐ Allow — Full-time employees (use a reused naming convention) |
| Action | Allow / Block / Bypass / Service Auth |
| Session duration | inherit or override |
Rules — combine Include / Require / Exclude (Exclude overrides all):
| Rule group | Selector | Operator | Value |
|---|---|---|---|
| Include | IdP Groups | in | Engineering |
| Require | Device Posture | in | Disk encryption, Firewall on |
| Require | Authentication Method | in | mfa |
| Exclude | Emails (List) | in | List: Offboarding |
⭐ Add a second, lowest-priority policy Block — Everyone (Action = Block, Include = Everyone) as a default-deny net. ⚠️ Policies evaluate top-down; keep Block/Exclude policies above broad Allows.
Selector cheat-sheet (most-used):
| Selector | Use it for |
|---|---|
| Emails / Emails ending in | Specific users / domain |
| IdP Groups | ⭐ Group-based access (needs group claims) |
| Device Posture | Require compliant devices |
| Gateway | Require traffic came through Gateway (client/RBI/WAN site) |
| Country / IP ranges | Geo / network restrictions |
| Authentication Method / MFA | Require strong auth |
| mTLS Certificate | Service Auth (machine-to-machine) |
| Cloudflare Account Member | Restrict to your account members |
E.3 Reusable building blocks (do this, not per-app rules)
| Component | Path | Use |
|---|---|---|
| Access Groups | Access controls → Policies → Groups → Add a group |
⭐ Named, reusable rule block (e.g. Secure employees = group + 3 posture checks). Reference across many apps |
| Lists | Reusable components → Lists |
Emails, device serial numbers, IPs — update via UI or API (HR/MDM integration) |
| Posture checks | Reusable components → Posture checks |
Define once, use in Access and Gateway |
E.4 RBI fallback for unmanaged devices
Keep the normal Allow (compliant employees) and add a Gateway HTTP policy with action Isolate matching the same app hostname, so non-compliant devices get a remote-browser session instead of a hard block.
Validate: a permitted user reaches the app post-login; a non-member is blocked; Access → Logs (Logpush) show allow/block with identity + posture.
F. Secure Web Gateway (Gateway) (Guide §6)
Build policies bottom-up the stack: DNS → Network → HTTP.
F.1 DNS policies (start here)
Path: Gateway → Firewall Policies → DNS → Add a policy
| Field | Value |
|---|---|
| Policy name | Block security threats |
| Selector | Security Categories |
| Operator | in |
| Value | ⭐ Malware, Phishing, Command & Control, Cryptomining, DGA Domains, DNS Tunneling, New Domains |
| Action | Block |
Add a second DNS policy for Content Categories (Adult, Gambling, etc.) per your AUP.
DNS Locations (sites without the client): Gateway → DNS Locations → Add a location → point the network's resolver at the assigned IPv4/IPv6, DoH (https://<id>.cloudflare-gateway.com/dns-query), or DoT endpoints shown.
F.2 Network (L4) policies
Path: Gateway → Firewall Policies → Network → Add a policy
| Example | Selector / Operator / Value | Action |
|---|---|---|
| Block outbound SMTP from clients | Destination Port in 25 |
Block |
| Restrict RDP egress | Destination Port in 3389 + Identity not in IT |
Block |
F.3 TLS decryption + HTTP policies
- Enable decryption:
Settings → Network → Firewall → TLS decryption→ On. ⚠️ Requires the Cloudflare root CA on devices (§C.4). - Create Do Not Inspect exceptions FIRST (
Gateway → Firewall Policies → HTTP → Add a policy, Action = Do Not Inspect):
| Exception | Selector / Value |
|---|---|
| Cert-pinned apps | Application in Do Not Inspect (Cloudflare-maintained app type) |
| Microsoft 365 | ⭐ Toggle the one-click Microsoft 365 traffic integration (auto-bypasses M365) |
| Banking / native apps | Application or Domain in your pinned-cert list |
- HTTP filtering policy example:
| Field | Value |
|---|---|
| Policy name | Block risky uploads |
| Selector | Application in <risky app> · or Content Category · or File Type |
| Action | Block / Isolate / Allow / Do Not Scan |
- Application granular controls (within an HTTP policy): allow an app but block specific actions — e.g. ChatGPT → block File upload, Google Drive → block Download to non-corporate tenant. This is also the hook for AI controls (§H).
Validate: browse a blocked category → Cloudflare block page; Gateway → Logs show HTTPS entries with decrypted detail (proves CA + decryption).
G. Data Loss Prevention (DLP) (Guide §7 — Enterprise)
G.1 Pick / build a profile
Path: DLP → DLP Profiles
- Predefined: open e.g. Credentials and Secrets, Financial Information, PII → toggle individual entries on/off.
- Custom:
Create profile→ add detection entries (predefined detectors, custom regex, dictionaries, EDM datasets, Microsoft Purview labels).
G.2 Tune sensitivity (per entry / profile)
| Setting | Where | ⭐ Recommendation |
|---|---|---|
| Confidence threshold | per detection entry | Low / Medium / High (raised by proximity keywords, e.g. "SSN" near a 9-digit number) |
| Minimum match count | per profile/entry | e.g. 10 → fires only at 11+ matches (cuts noise) |
| AI context analysis | DLP → Settings |
On (pretrained model adjusts confidence; HTTP/HTTPS only) |
| OCR | DLP → Settings |
On to scan text in images (.jpg/.png, 4 KB–1 MB) |
PII Record profile is special: it only fires when ≥3 unique entries appear in close proximity — a built-in false-positive control.
G.3 Enforce via a Gateway HTTP policy (⭐ two-policy pattern)
Path: Gateway → Firewall Policies → HTTP → Add a policy, use the DLP Profile selector.
| # | Selector / Value | Action | Purpose |
|---|---|---|---|
| 1 | DLP Profile in Financial Info (Low confidence) |
Allow (+ log) | ⭐ Visibility / baseline |
| 2 | DLP Profile in Financial Info (High confidence) + Destination Domain in dropbox.com, wetransfer.com + User Group in Finance |
Block | Enforcement, scoped |
⭐ Run monitor (Allow+log) for 1–2 weeks, then enable the Block. ⚠️ Always scope by destination/app/group — a broad Credentials profile on all traffic floods false positives. ⚠️ No TLS decryption → DLP can't see HTTPS bodies.
Validate: upload a benign test pattern (fake SSN / test card number) to a monitored destination → detection appears in Gateway → Logs / DLP with the matched profile + confidence.
H. AI safety controls (Guide §8)
H.1 Discover shadow AI
Path: Gateway → Analytics → Shadow IT Discovery → review Generative AI app category → mark apps Approved / Unapproved.
H.2 Govern AI app usage (allow + restrict, don't block)
Path: Gateway → Firewall Policies → HTTP → Add a policy
| Field | Value |
|---|---|
| Selector | Application in ChatGPT, Google Gemini, Claude, Perplexity |
| Application granular controls | ⭐ Block File upload / restrict actions (keeps the app usable) |
| DLP Profile | add AI Prompt: PII / AI Prompt: AI Security |
| Action | Allow (with granular block) or Block on DLP match |
H.3 AI Prompt Protection (DLP for prompts)
Path: DLP → Detection entries → AI prompt topics → enable Content topics (PII, Source Code, Credentials & Secrets, Financial Information, Customer Data) and Intent topics (jailbreak, malicious-code, PII-extraction). Or select a predefined AI Prompt profile, then reference it in the H.2 HTTP policy. ⭐ Start in monitor mode.
H.4 DLP for AI Gateway (programmatic/API AI — no decryption needed)
Path: AI → AI Gateway → your gateway → Features → DLP → Set up → attach DLP profiles. Scans request + response text to AI providers without Gateway HTTP filtering or TLS decryption.
H.5 AI Security for Apps (WAF — for AI you expose)
Path: your zone → Security → Settings / WAF → Detections → AI Security for Apps → enable prompt injection + unsafe topic detections, then write a WAF custom rule acting on the detection fields. Complements DLP (model-layer attacks vs. data detection).
H.6 MCP server portals (governing AI agents)
Path: Access → AI controls → MCP server portals → add a portal → publish/gate/rename tools behind an Access policy.
I. Cloudflare WAN (Guide §9 — Enterprise)
I.0 Pre-flight: MSS clamping (set on your edge BEFORE bringing tunnels up)
| On-ramp | TCP MSS clamp | Why |
|---|---|---|
| GRE | 1,436 bytes (internal interface) | Room for GRE header |
| IPsec | 1,360 bytes max | Room for ESP/encryption overhead |
Vendor syntax: Cisco ip tcp adjust-mss 1436, Juniper tcp-mss 1436. ⚠️ Symptom of a missed clamp: http:// works but https:// hangs — test with curl http://ifconfig.me vs curl https://ifconfig.me.
I.1 Add an IPsec tunnel
Path: Cloudflare WAN → Configuration → Tunnels → Create → IPsec tunnel
| Field | Value |
|---|---|
| Tunnel name | site-a-primary |
| Customer endpoint | your router's public IP (omit if behind NAT) |
| Cloudflare endpoint | the anycast IP assigned to your account |
| Interface address | the /31 (or /30) Cloudflare provides for the tunnel |
| Pre-shared key (PSK) | generate / paste; store in your secrets manager |
| Health check | On ⭐ (rate Low/Mid/High; target = the tunnel interface) |
| Replay protection | Off unless your device can't disable it (then On) |
Supported IKEv2 parameters (match these on your device):
| Parameter | Value |
|---|---|
| IKE version | IKEv2 only |
| Phase 1 encryption | AES256-GCM-16 |
| Phase 2 encryption | AES256-GCM-16 |
| Phase 1 integrity / PRF | SHA2-256 |
| Phase 2 integrity | SHA2-256 |
| Phase 1 DH group | 20 |
| Phase 2 DH group (PFS) | 20 |
| NAT-T | UDP 500 → 4500 (auto) |
I.2 Add a GRE tunnel (alternative)
Same path → GRE tunnel. Provide Customer endpoint, Cloudflare anycast endpoint, interface address (/31), and enable health checks. GRE is stateless (no encryption) — use IPsec where confidentiality matters.
I.3 Configure routing
Path: Cloudflare WAN → Configuration → Routes
| Approach | How | Use |
|---|---|---|
| Static routes | Add prefix (your site/DC subnet) → next-hop = tunnel → set Priority (lower = preferred) + Weight for ECMP | Simple, stable sites |
| BGP (over GRE/IPsec) | Enable BGP on the tunnel; configure eBGP peer + ASNs + MD5 auth | ⭐ Multi-site / dynamic; auto-adds/removes routes |
⭐ Redundancy: create two tunnels from two separate routers. Cloudflare's end is anycast (one tunnel already reaches every Cloudflare PoP), so resilience is about your premises hardware. ⚠️ Plan IP space — overlapping subnets across sites break Magic routing.
I.4 Add security + send site traffic to Gateway
- Magic Firewall:
Magic Firewall → Add rule(L3/L4 allow/deny on Cloudflare WAN traffic). ⚠️ Network traffic is unfiltered until you add rules. - Route Internet-bound traffic to Gateway so clientless sites get the same DNS/Network/HTTP/DLP policies as client users.
I.5 Health alerts
Path: Notifications → Add → Magic Tunnel Health → choose tunnels (filter by GRE / IPsec / CNI) → set recipients.
Validate: tunnels show Healthy; routes appear in the Magic routing table; curl https://ifconfig.me succeeds (MSS correct); disabling one tunnel fails over to the other; site Internet traffic is filtered by Gateway.
J. Validation & troubleshooting commands
# Cloudflare One Client (WARP) state
warp-cli status # expect: Connected
warp-cli settings # mode, org, split-tunnel
warp-cli account # enrolled org / posture
# Confirm you are egressing via Cloudflare (managed device)
curl https://www.cloudflare.com/cdn-cgi/trace/ # look for warp=on, gateway=on
# DNS over HTTPS location test
curl -H 'accept: application/dns-json' \
'https://<location-id>.cloudflare-gateway.com/dns-query?name=example.com&type=A'
# Cloudflare WAN MSS / tunnel sanity
curl http://ifconfig.me # works
curl https://ifconfig.me # hangs => MSS clamp too high (GRE 1436 / IPsec 1360)
# Cloudflare Tunnel
cloudflared tunnel info <NAME> # connector + connection status
cloudflared tunnel ingress validate # config check
| Symptom | Likely cause | Fix |
|---|---|---|
| "Not allowed to enroll" | No device enrollment permission rule | Add Allow/Service-Auth rule (§C.1) |
| HTTPS broken after decryption | Root CA not trusted | Push CA via MDM, then decrypt (§C.4) |
| Group policy never matches | Missing group claims / no SCIM | Re-run IdP Test; enable Support Groups + SCIM (§B) |
| App allowed that should be blocked | Policy order | Move Block/Exclude above broad Allow (§E.2) |
| DLP selector greyed out | Not Enterprise / role | Verify plan + admin role |
https:// hangs over Cloudflare WAN |
MSS clamp | GRE 1,436 / IPsec 1,360 (§I.0) |
K. Quick settings reference (one screen)
| Thing | Exact value |
|---|---|
| Zero Trust dashboard | https://one.dash.cloudflare.com |
| Team domain | https://<team-name>.cloudflareaccess.com |
| OIDC callback URL | https://<team-name>.cloudflareaccess.com/cdn-cgi/access/callback |
| Google JS origin | https://<team-name>.cloudflareaccess.com |
| Entra Graph delegated perms | email, offline_access, openid, profile, User.Read, Directory.Read.All, GroupMember.Read.All |
| Okta read-only API token | Required if >100 groups |
| WARP mode (enterprise) | Gateway with WARP |
| Split tunnel — managed / BYOD | Exclude / Include |
| Default excluded CGNAT | 100.64.0.0/10 |
| Service-token enrollment perm | Service Auth (not Allow) |
| MDM silent install keys | onboarding=false, auto_connect=1, switch_locked=true |
| OCR image size | .jpg/.png, 4 KB–1 MB |
| PII Record threshold | ≥3 unique entries in proximity |
| Cloudflare WAN IPsec ciphers | IKEv2 · AES256-GCM-16 · SHA2-256 · DH group 20 |
| MSS clamp | GRE 1436 / IPsec 1360 |
| IPsec NAT-T | UDP 500 → 4500 |
Prepared 2026-06-08. Field names and exact menu paths reflect current Cloudflare docs (Cloudflare One / Cloudflare WAN) and may shift; verify against your dashboard and confirm Enterprise entitlements (DLP, advanced posture, Cloudflare WAN) before production rollout. Replace all <placeholders> and example secrets with your own values — never reuse the sample tokens shown.