PRACTITIONER GUIDE
Practitioner GuideUpdated 15 min read

Cloudflare Zero Trust Access: Common VPN Migration Failures and How to Fix Them

60%
of ZTNA migrations leave legacy VPN running in parallel for 6+ months, creating a shadow network bypass
Day 1
is when most security gaps are introduced, during the initial tunnel and policy configuration, not after
Split-brain DNS
the most common root cause of broken application access after WARP deployment, and the most frequently misdiagnosed

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

Cloudflare Zero Trust Access promises to replace your VPN with identity-aware, device-context-enforced access to internal applications, no inbound firewall rules, no split tunneling headaches, no lateral movement risk. In practice, most migrations introduce security gaps that partially negate the security benefits. The gaps are not random. They follow predictable patterns: legacy applications left on TCP-level bypass, tunnel routes that expose entire subnets instead of individual services, identity policies missing device posture, and DNS configurations that leave legacy VPN running as a shadow network. This guide is for the engineers and security teams who have started or are planning a VPN-to-Cloudflare migration and want to close those gaps before they become incidents.

Failure Mode 1: Tunnel Routes That Re-Create the VPN

The most common migration mistake is configuring Cloudflare Tunnel with CIDR routes that cover entire subnets, effectively rebuilding a VPN tunnel in a Zero Trust wrapper. This eliminates the lateral movement benefit of application-level access control.

The wrong pattern: broad subnet routing

cloudflared config with routes like 10.0.0.0/8 or 192.168.0.0/16 gives every WARP-enrolled device access to every host in those ranges, regardless of Cloudflare Access policy. An attacker who compromises any enrolled device has network-level access to your internal network, the same blast radius as a VPN compromise.

The right pattern: per-application routing

Route only the specific hostnames or IP addresses that individual applications need. In Cloudflare Tunnel config: specify individual IPs (10.0.1.50/32) or use hostname-based routing exclusively. For Zero Trust Network Access (ZTNA) to private IPs, use Split Tunnel settings in WARP to exclude only the specific IPs your applications require, not entire subnets.

Audit your current tunnel routes

In Zero Trust Dashboard > Networks > Tunnels, review every active tunnel's routes. Any route with a subnet mask shorter than /28 deserves scrutiny. Use cloudflared tunnel route list to export all routes programmatically and pipe to a script that flags routes wider than a /24. Review against your application inventory, can you replace each subnet route with specific application DNS entries?

Micro-segmentation with Access policies per tunnel

The correct architecture: one cloudflared tunnel per application cluster (or per individual sensitive application), with a Cloudflare Access policy on each tunnel hostname that enforces identity + device posture. A compromised device that passes WARP enrollment can only reach the applications its identity group is authorized for, not adjacent systems on the same network segment.

Failure Mode 2: Split-Brain DNS Breaks Application Access

Split-brain DNS, where internal applications resolve to private IPs internally and different addresses (or NXDOMAIN) externally, breaks Cloudflare Access in predictable ways that are frequently misdiagnosed as Cloudflare bugs.

What breaks and why

Cloudflare Access works by proxying your application hostname through Cloudflare's network. When WARP is enabled in Gateway mode, DNS queries from enrolled devices route through Cloudflare Gateway. If your internal application hostname only resolves on your internal DNS server (not via Cloudflare DNS), WARP-enrolled devices cannot resolve it. The application appears broken and users disable WARP, defeating the migration.

The Local Domain Fallback fix

Zero Trust Dashboard > Settings > WARP Client > Profile Settings > Local Domain Fallback. Add your internal domains (corp.example.com, internal.example.com). These domains will be resolved by your internal DNS server (specified as the fallback resolver) rather than Cloudflare Gateway. This preserves internal DNS resolution while routing all other traffic through Gateway.

Split Horizon with Cloudflare Gateway DNS

Alternatively, add your internal hostnames to Cloudflare's DNS resolver as private network records. Zero Trust Dashboard > Gateway > DNS Locations allows you to create DNS policies that return private IP addresses for internal hostnames when the query comes from enrolled WARP devices. This eliminates the need for a separate internal DNS server for WARP users.

Testing and validation

After configuring Local Domain Fallback or Gateway DNS overrides: run nslookup internal-app.corp.example.com with WARP enabled from an enrolled device and verify it returns the expected private IP. Run cloudflared tunnel route lookup {IP} to verify the resolved IP has a matching tunnel route. Check Zero Trust Dashboard > Analytics > Gateway > DNS for failed resolutions.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

Failure Mode 3: Missing Device Posture Leaves Compromised Devices Authorized

Cloudflare Access enforces identity (who you are) but without device posture checks, it does not enforce device health (what you are using). A valid user credential on a malware-infected, unmanaged personal device passes identity checks and gets full access.

Minimum device posture requirements

Every Access policy protecting sensitive applications should require: (1) WARP client enrolled with your organization (prevents access from non-corporate devices or devices that have had WARP removed). (2) Disk encryption enabled (FileVault for macOS, BitLocker for Windows). (3) OS version minimum (reject devices more than 2 major versions behind). These three checks eliminate the most common compromised-device access scenarios.

Configuring posture in Access policies

Zero Trust Dashboard > Access > Applications > {App} > Policy > Require. Add a posture check rule: device_posture.check.passed = true. First configure the checks in Settings > WARP Client > Device Posture > Add New Check, then reference them in the policy. Posture checks are evaluated at connection time, a device that fails a posture check after initial enrollment will be denied access at the next policy enforcement point.

EDR integration for higher-assurance posture

For sensitive applications: integrate Cloudflare with your EDR provider (CrowdStrike, SentinelOne, Microsoft Intune) to use real-time device health scores rather than static attribute checks. Zero Trust Dashboard > Settings > WARP Client > Device Posture > Third-party checks. With CrowdStrike: require a Zero Trust Assessment (ZTA) score above a threshold (recommended: 70+) for access to critical applications.

Handling BYOD and contractor devices

Contractors and BYOD users who cannot install a corporate-managed WARP client need a different access path. Use Cloudflare Access for browser-rendered SSH or RDP (no client required) combined with short-lived service tokens or Cloudflare Access one-time PINs for these use cases. These sessions are fully logged in Cloudflare's audit log and do not expose internal network segments, only the specific application session.

Failure Mode 4: Legacy VPN Left Running as Shadow Network

The most operationally common failure: migration is declared complete but the legacy VPN is kept running for exceptions, and those exceptions never get resolved. Within 6 months, 30-40% of privileged users are still using the VPN for at least some access.

Why exceptions become permanent

Legacy applications that require Kerberos, NTLM, or SMB access, developer workflows that involve direct database connections, monitoring tools that need ICMP ping across subnets, and any application that was not inventoried before migration all become VPN exceptions. Without a hard deadline and active application migration work, these exceptions accumulate.

Inventorying VPN usage before decommission

Before turning off VPN, instrument it. Pull VPN connection logs and group by: unique user, destination IP/port, and connection frequency. Any destination that appears in VPN logs but not in your Cloudflare Tunnel route inventory is an unmigrated application. Export the full list and assign ownership to application teams with a migration deadline.

Forcing the migration with access policy ordering

Set a VPN decommission date and enforce it with policy. Start by blocking the highest-risk VPN users (privileged accounts, admins, developers with production access) from VPN 30 days before the deadline. Require them to complete Cloudflare Access migration for their specific use cases. Then systematically move the next tier. Never move the VPN decommission date, it creates the expectation that it will move again.

Monitoring for VPN client re-installation

After VPN decommission, monitor for VPN client software re-installation via MDM compliance policies (Intune compliance policy: block devices with VPN client installed) or EDR alerts on VPN client process execution. Some users will find ways to install legacy VPN software on personal devices and route corporate traffic through them, this is an insider threat and compliance risk.

Failure Mode 5: Service Account and Non-Human Access Not Migrated

Zero Trust migrations focus on human users and forget service accounts: CI/CD pipelines, monitoring agents, backup jobs, and API integrations that connect to internal services over the VPN.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Cloudflare Access Policy Best Practices Checklist

A checklist for validating your Access policies before decommissioning the VPN.

Every application has an explicit Access policy (no default-allow)

In Zero Trust Dashboard > Access > Applications, verify every application has at least one Allow policy with explicit identity conditions. Applications with no policy are accessible to any authenticated user in your organization, the equivalent of VPN with no application-level access control.

Sensitive applications require group membership, not just authentication

Access to production databases, administrative interfaces, and financial systems should require membership in a specific identity provider group (Okta group, Azure AD security group, Google group), not just any authenticated user. Authentication proves identity; group membership proves authorization.

All policies enforce device posture for managed devices

Any application accessible from managed devices should require WARP enrollment + disk encryption at minimum. Applications with sensitive data should require EDR posture. Test posture enforcement by temporarily failing a check on a test device and verifying access is denied.

Short session duration for privileged applications

Zero Trust Dashboard > Access > Applications > Settings > Session Duration. Set privileged access (SSH to production, admin interfaces) to 1-4 hours. Standard applications can use 8-24 hours. This limits the window an attacker has with a stolen session token.

Access audit logs shipped to SIEM

Zero Trust Dashboard > Settings > Account > Logpush. Configure Logpush to forward Access audit logs to your SIEM. Critical event types to monitor: policy change, user access denied (unusual spike may indicate compromised credential probing), service token creation, and bypass policy additions.

The bottom line

Cloudflare Zero Trust Access is a genuine security improvement over VPN when configured correctly. The migration failures in this guide, broad tunnel routes, split-brain DNS, missing posture checks, parallel VPN, unmigrated service accounts, each partially or fully negate that improvement. Address them in order: routes first (they expand your blast radius the most), then DNS (it causes the most user pain and drives VPN re-adoption), then posture (it closes the compromised-device gap). Keep the VPN decommission date firm. Every day the legacy VPN runs in parallel is a day the migration is incomplete.

Frequently asked questions

Can Cloudflare Zero Trust replace a site-to-site VPN?

Cloudflare Tunnel (cloudflared) and WARP-to-Tunnel replace remote access VPN use cases. Site-to-site connectivity between data centers or between cloud VPCs is a different pattern, Cloudflare Magic WAN handles that use case. Most organizations migrating from remote access VPN to Cloudflare Access and WARP are replacing the latter, not the former.

What happens to applications that use non-HTTP protocols?

Cloudflare Access supports HTTP/HTTPS applications natively. For SSH, RDP, SMB, and custom TCP/UDP applications, you need Cloudflare Tunnel with the WARP client in Gateway mode. SSH and RDP are supported directly through browser-rendered access. SMB and arbitrary TCP/UDP require private network routing via WARP + cloudflared tunnel with split tunnel configuration.

How do I handle legacy applications that use NTLM or Kerberos authentication?

NTLM and Kerberos do not work through Cloudflare Access by default. Options: (1) Wrap the application behind a Cloudflare Access policy that handles identity, and let the app handle internal NTLM/Kerberos separately. (2) Use Cloudflare Access for Infrastructure with service tokens for machine-to-machine connections that require Kerberos. (3) Some organizations keep a minimal VPN footprint specifically for legacy Kerberos-dependent applications while migrating everything else to ZTNA.

How do I enforce device posture checks without MDM?

Cloudflare WARP device posture checks require either a WARP client registration or integration with an MDM/EDR platform. Without MDM, you can use WARP client-based checks: OS version, disk encryption status (FileVault/BitLocker), firewall enabled, and presence of specific application files. These are configured in Zero Trust Dashboard > Settings > WARP Client > Device Posture. Full posture integration requires Intune, Jamf, CrowdStrike Falcon, SentinelOne, or similar.

What is the most common reason Cloudflare Zero Trust migrations fail?

The most common failure mode is incomplete application discovery before migration. Organizations migrate the 20-30 applications they are aware of, then discover during the cutover that users depend on dozens of additional internal tools -- file shares, legacy intranet apps, internal APIs -- that were not inventoried. These unlisted applications either break (if VPN is decommissioned too early) or create support pressure that stalls the migration indefinitely. Successful migrations start with 60-90 days of VPN traffic analysis to enumerate all internal destinations users actually connect to, building the application inventory from observed network behavior rather than IT asset lists. Only after all applications have ZTNA connectors deployed should VPN access be restricted.

How do I migrate developer workflows that rely on direct database connections over VPN?

Direct database connections (PostgreSQL, MySQL, Redis) are the most common blocker in VPN-to-ZTNA migrations because they use raw TCP, not HTTP, and Cloudflare Access's application-layer proxy does not natively support them. The right approach is Cloudflare Tunnel with WARP in Gateway mode: deploy cloudflared as a sidecar next to each database, configure a private hostname (e.g., postgres-prod.internal.example.com) pointing to the database host, and add a Cloudflare Access policy that requires WARP enrollment plus a specific identity group (your database administrator group in your IdP). Developers connect using standard PostgreSQL clients -- the WARP client handles routing through the tunnel transparently. Enforce short session durations (2-4 hours) for database access policies and require EDR-based device posture checks for any connection to a production database hostname.

Sources & references

  1. Cloudflare Zero Trust documentation
  2. Cloudflare Access: Policies
  3. WARP client documentation
  4. NIST SP 800-207: Zero Trust Architecture

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.