2760 words
14 minutes
Implementing Zero Trust Network Access with Cloudflare

Implementing Zero Trust Network Access with Cloudflare#

Cloudflare Zero Trust provides a comprehensive suite of tools to implement modern security architecture that eliminates implicit trust and continuously validates every transaction. This guide covers implementing Zero Trust Network Access (ZTNA) using Cloudflare’s Access, Tunnel, Gateway, and WARP products.

Table of Contents#

Introduction to Zero Trust#

Zero Trust is a security model that requires all users, whether inside or outside the organization’s network, to be authenticated, authorized, and continuously validated before being granted access to applications and data.

Core Principles#

  1. Never trust, always verify - No implicit trust based on network location
  2. Least privilege access - Users get minimal required permissions
  3. Assume breach - Design security as if the network is already compromised
  4. Verify explicitly - Authenticate and authorize based on all available data points
  5. Inspect and log all traffic - Complete visibility into network activity

Cloudflare Zero Trust Components#

  • Cloudflare Access - Identity-aware proxy for applications
  • Cloudflare Tunnel - Secure connection to internal resources
  • Cloudflare Gateway - Secure web gateway and DNS filtering
  • WARP - VPN replacement for device connectivity
  • Browser Isolation - Remote browser execution
  • Data Loss Prevention - Protect sensitive data

Architecture Overview#

┌──────────────────────────────────────────────────────────┐
│ Internet / Public Network │
└────────────────┬─────────────────────────────────────────┘
┌─────────▼─────────┐
│ Cloudflare Edge │
│ (150+ POPs) │
└─────────┬─────────┘
┌────────────┼────────────┐
│ │ │
┌───▼───┐ ┌────▼────┐ ┌────▼────┐
│Access │ │Gateway │ │ WARP │
│Proxy │ │Filtering│ │ Client │
└───┬───┘ └────┬────┘ └────┬────┘
│ │ │
┌───▼───────────▼─────────────▼───┐
│ Cloudflare Tunnel │
│ (Outbound-only Connection) │
└─────────────┬───────────────────┘
┌─────────▼─────────┐
│ Private Network │
│ Applications │
└───────────────────┘

Setting Up Cloudflare Access#

1. Initial Configuration#

Terminal window
# Install cloudflared
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
# Authenticate
cloudflared tunnel login
# This will open a browser to authenticate with your Cloudflare account

2. Create Access Application#

// Using Cloudflare API to create Access application
const createAccessApp = async () => {
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Internal Dashboard',
domain: 'dashboard.internal.company.com',
type: 'self_hosted',
session_duration: '24h',
auto_redirect_to_identity: false,
allowed_idps: ['google', 'azure'],
custom_pages: {
forbidden: 'https://company.com/access-denied',
},
cors_headers: {
allowed_methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowed_origins: ['https://app.company.com'],
allow_credentials: true,
},
}),
}
);
return response.json();
};

3. Configure Access Policies#

// Create access policy with multiple rules
const createAccessPolicy = async (appId) => {
const policy = {
name: 'Engineering Team Access',
precedence: 1,
decision: 'allow',
include: [
{
email_domain: {
domain: 'company.com'
}
},
{
group: {
id: 'engineering-group-id'
}
}
],
exclude: [
{
email: {
email: 'contractor@external.com'
}
}
],
require: [
{
geo: {
country_code: ['US', 'CA', 'GB']
}
},
{
device_posture: {
integration_uid: 'device-trust-check'
}
}
],
isolation_required: false,
purpose_justification_required: true,
purpose_justification_prompt: 'Please provide reason for access',
approval_required: true,
approval_groups: [
{
email_list: ['manager@company.com', 'security@company.com']
}
]
};
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps/${appId}/policies`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(policy),
}
);
return response.json();
};

4. Identity Provider Integration#

// Configure SAML identity provider
const configureSAML = async () => {
const samlConfig = {
name: 'Company SAML',
type: 'saml',
config: {
issuer_url: 'https://idp.company.com',
sso_target_url: 'https://idp.company.com/sso/saml',
idp_public_cert: `-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
...
-----END CERTIFICATE-----`,
attributes: [
'email',
'name',
'groups'
],
email_attribute_name: 'EmailAddress',
sign_request: true,
redirect_url: 'https://team.cloudflareaccess.com/cdn-cgi/access/callback'
}
};
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/identity_providers`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(samlConfig),
}
);
return response.json();
};
// Configure OAuth 2.0 provider
const configureOAuth = async () => {
const oauthConfig = {
name: 'Google Workspace',
type: 'google',
config: {
client_id: process.env.GOOGLE_CLIENT_ID,
client_secret: process.env.GOOGLE_CLIENT_SECRET,
apps_domain: 'company.com'
}
};
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/identity_providers`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(oauthConfig),
}
);
return response.json();
};

Cloudflare Tunnel Configuration#

1. Create and Configure Tunnel#

Terminal window
# Create a new tunnel
cloudflared tunnel create production-tunnel
# This creates:
# - ~/.cloudflared/<TUNNEL_ID>.json (credentials file)
# - Tunnel UUID
# List tunnels
cloudflared tunnel list

2. Tunnel Configuration File#

~/.cloudflared/config.yml:

tunnel: YOUR_TUNNEL_ID
credentials-file: /home/user/.cloudflared/YOUR_TUNNEL_ID.json
# Ingress rules - routing traffic to your services
ingress:
# Public hostname routing to internal service
- hostname: app.company.com
service: http://localhost:3000
originRequest:
noTLSVerify: false
originServerName: app.internal.local
connectTimeout: 30s
tcpKeepAlive: 30s
keepAliveConnections: 100
keepAliveTimeout: 90s
httpHostHeader: app.internal.local
# API endpoint with different configuration
- hostname: api.company.com
service: http://localhost:8080
originRequest:
noTLSVerify: true
disableChunkedEncoding: true
bastionMode: false
proxyAddress: 127.0.0.1
proxyPort: 8080
proxyType: socks
# WebSocket support
- hostname: ws.company.com
service: ws://localhost:8081
originRequest:
noTLSVerify: true
# TCP service (SSH, RDP, etc.)
- hostname: ssh.company.com
service: tcp://localhost:22
# Load balancing across multiple origins
- hostname: balanced.company.com
service: http://localhost:3001
originRequest:
noTLSVerify: false
loadBalancer:
- http://server1:3001
- http://server2:3001
- http://server3:3001
# Catch-all rule (must be last)
- service: http_status:404

3. Run Tunnel as a Service#

Terminal window
# Install as systemd service (Linux)
sudo cloudflared service install
# Start the service
sudo systemctl start cloudflared
sudo systemctl enable cloudflared
# Check status
sudo systemctl status cloudflared
# View logs
sudo journalctl -u cloudflared -f

4. High Availability Setup#

config-replica-1.yml
tunnel: YOUR_TUNNEL_ID
credentials-file: /path/to/credentials.json
protocol: quic
ingress:
- hostname: app.company.com
service: http://localhost:3000
originRequest:
noTLSVerify: false
- service: http_status:404
# Run multiple instances for HA
# Instance 1
cloudflared tunnel --config config-replica-1.yml run
# Instance 2 (on different server)
cloudflared tunnel --config config-replica-2.yml run

Gateway and DNS Filtering#

1. Configure Gateway Policies#

// Create DNS filtering policy
const createGatewayPolicy = async () => {
const policy = {
name: 'Block Malicious Domains',
description: 'Blocks known malicious domains and categories',
action: 'block',
enabled: true,
precedence: 1,
filters: [
'dns'
],
traffic: {
dns: {
domains: [
'malicious-site.com',
'*.phishing-domain.net'
],
categories: [
'malware',
'phishing',
'crypto_mining'
]
}
},
rule: {
operator: 'or',
conditions: [
{
type: 'domain',
operator: 'in',
value: ['malware', 'phishing']
},
{
type: 'dns_category',
operator: 'in',
value: [117, 118, 131] // Category IDs
}
]
},
schedule: {
time_zone: 'America/New_York',
monday: { start: '00:00', end: '24:00' },
tuesday: { start: '00:00', end: '24:00' },
wednesday: { start: '00:00', end: '24:00' },
thursday: { start: '00:00', end: '24:00' },
friday: { start: '00:00', end: '24:00' },
saturday: { start: '00:00', end: '24:00' },
sunday: { start: '00:00', end: '24:00' }
}
};
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/gateway/rules`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(policy),
}
);
return response.json();
};

2. HTTP Inspection Policies#

// Configure HTTP inspection rules
const createHTTPPolicy = async () => {
const policy = {
name: 'Data Loss Prevention',
action: 'block',
enabled: true,
filters: ['http'],
precedence: 2,
traffic: {
http: {
methods: ['POST', 'PUT'],
mime_types: ['application/json', 'text/plain']
}
},
rule: {
operator: 'and',
conditions: [
{
type: 'http_method',
operator: 'in',
value: ['POST', 'PUT']
},
{
type: 'payload_content',
operator: 'matches',
value: '\\b(?:\\d{3}-\\d{2}-\\d{4}|\\d{9})\\b' // SSN pattern
}
]
},
dlp_profile: {
entries: [
{
name: 'Credit Card Numbers',
pattern: '\\b(?:\\d{4}[\\s-]?){3}\\d{4}\\b',
enabled: true
},
{
name: 'Social Security Numbers',
pattern: '\\b\\d{3}-\\d{2}-\\d{4}\\b',
enabled: true
}
]
},
notification_settings: {
enabled: true,
message: 'Sensitive data transmission blocked',
support_url: 'https://company.com/security-policy'
}
};
return await createGatewayRule(policy);
};

3. Custom Block Pages#

<!-- Custom block page template -->
<!DOCTYPE html>
<html>
<head>
<title>Access Blocked</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
text-align: center;
padding: 40px;
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
backdrop-filter: blur(10px);
}
h1 { font-size: 48px; margin-bottom: 20px; }
p { font-size: 18px; margin-bottom: 30px; }
.details {
background: rgba(0, 0, 0, 0.2);
padding: 20px;
border-radius: 5px;
margin-top: 20px;
}
.code { font-family: monospace; color: #ffd700; }
</style>
</head>
<body>
<div class="container">
<h1>🛡️ Access Blocked</h1>
<p>This website has been blocked by your organization's security policy.</p>
<div class="details">
<p><strong>Category:</strong> <span class="code">{{CATEGORY}}</span></p>
<p><strong>Policy:</strong> <span class="code">{{POLICY_NAME}}</span></p>
<p><strong>Request ID:</strong> <span class="code">{{REQUEST_ID}}</span></p>
<p><strong>Timestamp:</strong> <span class="code">{{TIMESTAMP}}</span></p>
</div>
<p>If you believe this is a mistake, please contact IT support.</p>
</div>
</body>
</html>

WARP Client Deployment#

1. MDM Deployment Configuration#

<!-- Windows MDM Configuration -->
<MDMConfiguration>
<WARPClient>
<Organization>YOUR_ORGANIZATION</Organization>
<AuthToken>YOUR_AUTH_TOKEN</AuthToken>
<ServiceMode>warp</ServiceMode>
<AutoConnect>true</AutoConnect>
<SwitchLocked>true</SwitchLocked>
<ExcludedRoutes>
<Route>192.168.0.0/16</Route>
<Route>10.0.0.0/8</Route>
</ExcludedRoutes>
<IncludedRoutes>
<Route>172.16.0.0/12</Route>
</IncludedRoutes>
<FallbackDomains>
<Domain>internal.company.com</Domain>
<Domain>corp.company.local</Domain>
</FallbackDomains>
<DNSServerOverride>
<Primary>162.159.36.1</Primary>
<Secondary>162.159.46.1</Secondary>
</DNSServerOverride>
</WARPClient>
</MDMConfiguration>

2. Deployment Script#

Terminal window
# PowerShell deployment script for Windows
param(
[string]$OrganizationName = "company",
[string]$AuthToken = "YOUR_AUTH_TOKEN"
)
# Download WARP client
$warpUrl = "https://www.cloudflare.com/Cloudflare_WARP_Release-x64.msi"
$installerPath = "$env:TEMP\cloudflare-warp.msi"
Invoke-WebRequest -Uri $warpUrl -OutFile $installerPath
# Install WARP silently
$arguments = @(
"/i"
"`"$installerPath`""
"/quiet"
"/norestart"
"ORGANIZATION=`"$OrganizationName`""
"AUTH_CLIENT_ID=`"$AuthToken`""
"ENABLE=`"true`""
"GATEWAY_UNIQUE_ID=`"$OrganizationName`""
"SERVICE_MODE=`"warp`""
"SUPPORT_URL=`"https://support.company.com`""
)
Start-Process msiexec.exe -ArgumentList $arguments -Wait -NoNewWindow
# Configure WARP settings
$warpConfig = @{
auto_connect = $true
switch_locked = $true
service_mode = "warp"
organization = $OrganizationName
exclude = @(
"*.local"
"192.168.*"
"10.*"
)
fallback_domains = @(
"internal.company.com"
"corp.local"
)
}
$warpConfig | ConvertTo-Json | Set-Content -Path "C:\ProgramData\Cloudflare\warp-config.json"
# Start WARP service
Start-Service "CloudflareWARP"
Set-Service "CloudflareWARP" -StartupType Automatic
Write-Host "WARP client installed and configured successfully"

3. macOS Deployment#

#!/bin/bash
# macOS deployment script
# Download WARP client
curl -o /tmp/Cloudflare_WARP.pkg https://www.cloudflare.com/Cloudflare_WARP.pkg
# Install WARP
sudo installer -pkg /tmp/Cloudflare_WARP.pkg -target /
# Configure WARP
cat > /Library/Managed\ Preferences/com.cloudflare.warp.plist << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>organization</key>
<string>company</string>
<key>auto_connect</key>
<true/>
<key>switch_locked</key>
<true/>
<key>service_mode</key>
<string>warp</string>
<key>gateway_unique_id</key>
<string>company</string>
<key>exclude_routes</key>
<array>
<string>192.168.0.0/16</string>
<string>10.0.0.0/8</string>
</array>
<key>fallback_domains</key>
<array>
<string>internal.company.com</string>
<string>corp.local</string>
</array>
</dict>
</plist>
EOF
# Start WARP
sudo launchctl load /Library/LaunchDaemons/com.cloudflare.warp.plist

Device Posture Checks#

1. Configure Device Trust#

// Create device posture rule
const createDevicePosture = async () => {
const postureRule = {
name: 'Corporate Device Check',
type: 'serial_number',
schedule: '0 */4 * * *', // Check every 4 hours
expiration: '30d',
description: 'Verify device is corporate-managed',
match: [
{
platform: 'windows',
serial_numbers: [
'ABC123456',
'DEF789012'
]
},
{
platform: 'mac',
serial_numbers: [
'C02ABC1234'
]
}
],
input: {
operating_system: {
windows: {
version: '10.0.19041',
operator: '>='
},
mac: {
version: '11.0',
operator: '>='
}
},
firewall: {
enabled: true
},
disk_encryption: {
enabled: true,
encrypted_locations: ['C:\\', '/']
},
antivirus: {
installed: true,
running: true,
definitions_up_to_date: true
}
}
};
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/devices/posture`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(postureRule),
}
);
return response.json();
};

2. Advanced Posture Checks#

// Compliance check implementation
const complianceCheck = {
name: 'Security Compliance',
type: 'file',
schedule: '0 0 * * *', // Daily
checks: [
{
name: 'Certificate Present',
platform: 'windows',
path: 'C:\\ProgramData\\Company\\cert.pem',
exists: true,
sha256: 'abc123def456...'
},
{
name: 'Security Agent Running',
platform: 'all',
process: 'SecurityAgent',
running: true
},
{
name: 'Registry Key Check',
platform: 'windows',
registry: {
path: 'HKLM\\Software\\Company\\Security',
key: 'ComplianceLevel',
value: 'High'
}
},
{
name: 'Script Output Check',
platform: 'mac',
script: {
path: '/usr/local/bin/compliance-check.sh',
expected_output: 'COMPLIANT',
timeout: 30
}
}
]
};

Service Auth and API Security#

1. Service Token Implementation#

// Create service token for automation
const createServiceToken = async () => {
const token = {
name: 'CI/CD Pipeline',
duration: '365d',
policies: [
{
effect: 'allow',
resources: ['com.cloudflare.api.account.*'],
permission_groups: [
{
id: 'read_only_permissions'
}
]
}
]
};
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/service_tokens`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(token),
}
);
const result = await response.json();
// Returns client_id and client_secret
return result;
};
// Use service token for authentication
const authenticateService = async (clientId, clientSecret) => {
const response = await fetch('https://api.internal.company.com/data', {
headers: {
'CF-Access-Client-Id': clientId,
'CF-Access-Client-Secret': clientSecret,
}
});
return response.json();
};

2. mTLS Configuration#

// Configure mutual TLS
const configureMTLS = async () => {
const mtlsConfig = {
name: 'API mTLS',
hostname: 'api.company.com',
certificate_authorities: [
{
name: 'Company Root CA',
certificate: `-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
...
-----END CERTIFICATE-----`
}
],
client_certificate_forwarding: {
enabled: true,
header_name: 'X-Client-Cert'
},
validation: {
require_client_certificate: true,
check_revocation: true
}
};
return await createMTLSRule(mtlsConfig);
};

Monitoring and Analytics#

1. Access Logs Integration#

// Stream Access logs to SIEM
const configureLogPush = async () => {
const logPushConfig = {
name: 'Access Logs to SIEM',
destination_conf: 's3://security-logs/cloudflare/access/',
dataset: 'access_logs',
frequency: 'every_5_minutes',
enabled: true,
logpull_options: 'fields=RayID,EdgeStartTimestamp,ClientIP,ClientCountry,ClientDeviceType,EdgePathingSrc,EdgePathingOp,EdgePathingStatus,OriginResponseStatus,ClientRequestHost,ClientRequestMethod,ClientRequestPath,ClientRequestProtocol,ClientRequestUserAgent,EdgeResponseBytes,EdgeResponseStatus,EdgeServerIP,SecurityLevel',
ownership_challenge: 'challenge-token-here',
filter: {
where: {
key: 'ApplicationID',
operator: 'eq',
value: 'app-id-here'
}
}
};
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/logpush/jobs`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(logPushConfig),
}
);
return response.json();
};

2. Real-time Analytics Dashboard#

// Analytics API integration
const getAccessAnalytics = async () => {
const query = `
query GetAccessMetrics($accountId: String!, $datetimeStart: String!, $datetimeEnd: String!) {
viewer {
accounts(filter: {accountTag: $accountId}) {
accessRequests: accessRequestsAdaptiveGroups(
filter: {
datetime_geq: $datetimeStart,
datetime_leq: $datetimeEnd
}
) {
sum {
requests
allowedRequests
deniedRequests
}
dimensions {
datetimeHour
applicationName
action
userEmail
country
}
}
}
}
}
`;
const variables = {
accountId: ACCOUNT_ID,
datetimeStart: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
datetimeEnd: new Date().toISOString()
};
const response = await fetch('https://api.cloudflare.com/client/v4/graphql', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query, variables }),
});
return response.json();
};

3. Alert Configuration#

// Configure security alerts
const createSecurityAlert = async () => {
const alert = {
name: 'Suspicious Access Activity',
description: 'Alert on unusual access patterns',
enabled: true,
alert_type: 'access_anomaly',
filters: {
zones: ['all'],
services: ['access'],
where: {
or: [
{
key: 'failed_login_count',
operator: 'gt',
value: '5'
},
{
key: 'new_location',
operator: 'eq',
value: 'true'
},
{
key: 'impossible_travel',
operator: 'eq',
value: 'true'
}
]
}
},
mechanisms: {
email: {
enabled: true,
addresses: ['security@company.com']
},
webhook: {
enabled: true,
url: 'https://siem.company.com/webhook',
secret: process.env.WEBHOOK_SECRET
},
pagerduty: {
enabled: true,
integration_key: process.env.PAGERDUTY_KEY
}
}
};
return await createAlert(alert);
};

Best Practices and Security Hardening#

1. Least Privilege Access#

// Implement time-based access
const createTemporaryAccess = async () => {
const temporaryPolicy = {
name: 'Contractor Temporary Access',
decision: 'allow',
include: [
{
email: {
email: 'contractor@external.com'
}
}
],
require: [
{
purpose_justification: {
required: true,
prompt: 'Provide ticket number and reason'
}
}
],
session_duration: '4h',
valid_from: new Date().toISOString(),
valid_until: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
approval_required: true,
approval_groups: [
{
email_list: ['manager@company.com']
}
]
};
return await createPolicy(temporaryPolicy);
};

2. Network Segmentation#

# Tunnel configuration for network segmentation
tunnel: production-tunnel
credentials-file: /path/to/credentials.json
ingress:
# Production environment
- hostname: prod-*.company.com
service: http://prod-lb:8080
originRequest:
noTLSVerify: false
access:
required: true
teamName: production-team
# Staging environment
- hostname: staging-*.company.com
service: http://staging-lb:8080
originRequest:
noTLSVerify: true
access:
required: true
teamName: dev-team
# Development environment
- hostname: dev-*.company.com
service: http://dev-lb:8080
originRequest:
noTLSVerify: true
access:
required: false
- service: http_status:404

3. Incident Response Automation#

// Automated incident response
const respondToIncident = async (incident) => {
// 1. Isolate affected user
await revokeUserSessions(incident.userId);
// 2. Block source IP
await createIPBlock(incident.sourceIP);
// 3. Force password reset
await forcePasswordReset(incident.userId);
// 4. Notify security team
await notifySecurityTeam(incident);
// 5. Create forensic snapshot
await captureForensicData(incident);
// 6. Update access policies
await tightenAccessPolicies(incident.affectedResources);
return {
incidentId: incident.id,
actions: [
'sessions_revoked',
'ip_blocked',
'password_reset_forced',
'team_notified',
'forensics_captured',
'policies_updated'
],
timestamp: new Date().toISOString()
};
};
const revokeUserSessions = async (userId) => {
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/users/${userId}/active_sessions`,
{
method: 'DELETE',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
},
}
);
return response.json();
};

Troubleshooting Guide#

1. Common Issues and Solutions#

// Diagnostic script
const runDiagnostics = async () => {
const diagnostics = {
timestamp: new Date().toISOString(),
checks: []
};
// Check tunnel connectivity
try {
const tunnelStatus = await checkTunnelStatus();
diagnostics.checks.push({
name: 'Tunnel Connectivity',
status: tunnelStatus.connected ? 'OK' : 'FAILED',
details: tunnelStatus
});
} catch (error) {
diagnostics.checks.push({
name: 'Tunnel Connectivity',
status: 'ERROR',
error: error.message
});
}
// Check DNS resolution
try {
const dnsCheck = await checkDNSResolution();
diagnostics.checks.push({
name: 'DNS Resolution',
status: dnsCheck.success ? 'OK' : 'FAILED',
details: dnsCheck
});
} catch (error) {
diagnostics.checks.push({
name: 'DNS Resolution',
status: 'ERROR',
error: error.message
});
}
// Check Access policies
try {
const policyCheck = await validatePolicies();
diagnostics.checks.push({
name: 'Access Policies',
status: policyCheck.valid ? 'OK' : 'MISCONFIGURED',
details: policyCheck
});
} catch (error) {
diagnostics.checks.push({
name: 'Access Policies',
status: 'ERROR',
error: error.message
});
}
// Check certificate validity
try {
const certCheck = await checkCertificates();
diagnostics.checks.push({
name: 'Certificate Validity',
status: certCheck.valid ? 'OK' : 'EXPIRED',
details: certCheck
});
} catch (error) {
diagnostics.checks.push({
name: 'Certificate Validity',
status: 'ERROR',
error: error.message
});
}
return diagnostics;
};

2. Debug Logging#

Terminal window
# Enable debug logging for cloudflared
cloudflared tunnel run --loglevel debug --logfile /var/log/cloudflared.log
# Enable WARP debug logs (Windows)
reg add "HKLM\Software\Cloudflare\WARP" /v "LogLevel" /t REG_SZ /d "debug" /f
# Enable WARP debug logs (macOS)
sudo defaults write /Library/Preferences/com.cloudflare.warp LogLevel -string "debug"

3. Performance Optimization#

// Optimize tunnel performance
const optimizeTunnelConfig = {
protocol: 'quic', // Use QUIC for better performance
retries: 5,
grace_period: '30s',
originRequest: {
connectTimeout: '30s',
tlsTimeout: '10s',
tcpKeepAlive: '30s',
noHappyEyeballs: false,
keepAliveConnections: 100,
keepAliveTimeout: '90s',
httpHostHeader: '',
originServerName: '',
caPool: '',
noTLSVerify: false,
disableChunkedEncoding: false,
bastionMode: false,
proxyAddress: '127.0.0.1',
proxyPort: 0,
proxyType: '',
ipRules: []
}
};

Conclusion#

Cloudflare Zero Trust provides a comprehensive platform for implementing modern security architecture:

  • Identity-based access control replacing network perimeter security
  • Secure connectivity without traditional VPNs
  • Comprehensive threat protection at the edge
  • Detailed visibility into all network activity
  • Simplified management through centralized policies

Key Benefits#

  1. Reduced attack surface - No exposed inbound ports
  2. Improved user experience - Fast, seamless access
  3. Cost reduction - Eliminate VPN infrastructure
  4. Enhanced security - Continuous verification
  5. Scalability - Cloud-native architecture

Implementation Checklist#

  • Configure identity providers
  • Set up Cloudflare Tunnel
  • Create Access applications
  • Deploy WARP clients
  • Configure Gateway policies
  • Implement device posture checks
  • Set up monitoring and alerts
  • Test disaster recovery procedures
  • Train users on new access methods
  • Document security policies

Resources#

Implementing Zero Trust Network Access with Cloudflare
https://mranv.pages.dev/posts/cloudflare-zero-trust-network-guide/
Author
Anubhav Gain
Published at
2025-08-10
License
CC BY-NC-SA 4.0