WARP architecture
This guide explains how the Cloudflare WARP client interacts with a device’s operating system to route traffic in Gateway with WARP mode.
In Gateway with DoH mode, the IP traffic information does not apply. In Secure Web Gateway without DNS filtering mode, the DNS traffic information does not apply.
Overview
The WARP client allows organizations to have granular control over the applications an end user device can access. The client forwards DNS and network traffic from the device to Cloudflare’s global network, where Zero Trust policies are applied in the cloud. On all operating systems, the WARP daemon maintains three connections between the device and Cloudflare:
Connection | Protocol | Purpose |
---|---|---|
Device orchestration | HTTPS | Perform user registration, check device posture, apply WARP profile settings. |
DoH | HTTPS | Send DNS requests to Gateway for DNS policy enforcement. |
Wireguard | UDP | Send IP packets to Gateway for network policy enforcement, HTTP policy enforcement, and private network access. |
Your Split Tunnel configuration determines what traffic is sent down the Wireguard tunnel. Your Local Domain Fallback configuration determines which DNS requests are sent to Gateway via DoH. Traffic to the DoH endpoint and device orchestration API endpoint do not obey Split Tunnel rules, since those connections always operate outside of the Wireguard tunnel.
Next, you will learn how WARP configures your operating system to apply your Local Domain Fallback and Split Tunnel routing rules. Implementation details differ between desktop and mobile clients.
Windows, macOS, and Linux
The desktop client consists of two components: a service/daemon that handles all WARP functionality on your device, and a GUI wrapper that makes it easier for a user to interact with the daemon.
DNS traffic
When you turn on WARP, WARP creates a local DNS proxy on the device and binds it to these IP addresses on port 53 (the port designated for DNS traffic):
- IPv4:
127.0.2.2
and127.0.2.3
- IPv6:
- macOS and Linux:
fd01:db8:1111::2
andfd01:db8:1111::3
- Windows:
::ffff:127.0.2.2
- macOS and Linux:
WARP then configures the operating system to send all DNS requests to these IP addresses. All network interfaces on the device will now use this local DNS proxy for DNS resolution. In other words, all DNS traffic will now be handled by the WARP client.
Based on your Local Domain Fallback configuration, WARP will either forward the request to Gateway for DNS policy enforcement or forward the request to your private DNS resolver.
- Requests to Gateway are sent over our DoH connection (outside of the Wireguard tunnel).
- Requests to your private DNS resolver are sent either inside or outside of the tunnel depending on your Split Tunnel configuration. For more information, refer to How the WARP client handles DNS requests.
You can verify that the operating system is using WARP’s local DNS proxy:
On macOS, open a terminal window and run scutil --dns
. The DNS servers should be set to WARP’s local DNS proxy IPs.
$ scutil --dnsDNS configuration (for scoped queries)resolver #1search domain[0] : <DNS-SEARCH-DOMAIN>nameserver[0] : 127.0.2.2nameserver[1] : 127.0.2.3if_index : 15 (en0)flags : Scoped, Request A recordsreach : 0x00030002 (Reachable,Local Address,Directly Reachable Address)resolver #2nameserver[0] : 127.0.2.2nameserver[1] : 127.0.2.3nameserver[2] : fd01:db8:1111::2nameserver[3] : fd01:db8:1111::3if_index : 23 (utun3)flags : Scoped, Request A records, Request AAAA recordsreach : 0x00030002 (Reachable,Local Address,Directly Reachable Address)
On Windows, open a Powershell window and run ipconfig
. The DNS servers should be set to WARP’s local DNS proxy IPs.
PS C:\> ipconfigWindows IP ConfigurationUnknown adapter CloudflareWARP:Connection-specific DNS Suffix . :Description . . . . . . . . . . . : Cloudflare WARP Interface TunnelPhysical Address. . . . . . . . . :DHCP Enabled. . . . . . . . . . . : NoAutoconfiguration Enabled . . . . : YesIPv6 Address. . . . . . . . . . . : 2606:4700:110:8f79:145:f180:fc4:8106(Preferred)Link-local IPv6 Address . . . . . : fe80::83b:d647:4bed:d388%49(Preferred)IPv4 Address. . . . . . . . . . . : 172.16.0.2(Preferred)Subnet Mask . . . . . . . . . . . : 255.255.255.255Default Gateway . . . . . . . . . :DNS Servers . . . . . . . . . . . : 127.0.2.2127.0.2.3NetBIOS over Tcpip. . . . . . . . : Enabled
On Linux, check the /etc/resolv.conf
file. The DNS servers should be set to WARP’s local DNS proxy IPs.
$ cat /etc/resolv.conf# This file was generated by cloudflare-warp.nameserver 127.0.2.2nameserver 127.0.2.3nameserver fd01:db8:1111::2nameserver fd01:db8:1111::3search <DNS-SEARCH-DOMAIN>options edns0options trust-ad
IP traffic
When you turn on WARP, WARP makes three changes on the device to control if traffic is sent inside or outside of the Wireguard tunnel:
- Creates a virtual network interface.
- Modifies the operating system routing table according to your Split Tunnel rules.
- Modifies the operating system firewall according to your Split Tunnel rules.
Virtual interface
Virtual interfaces allow the operating system to logically subdivide a physical interface, such as a network interface controller (NIC), into separate interfaces for the purposes of routing IP traffic. WARP’s virtual interface is what maintains the Wireguard connection between the device and Cloudflare. Its IP address is hardcoded as 172.16.0.2
.
To view a list of all network interfaces on the operating system:
On macOS, run ifconfig
. When WARP is turned on, you will see a utun
interface with IP address 172.16.0.2
.
$ ifconfig<redacted>utun3: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1280inet 172.16.0.2 --> 172.16.0.2 netmask 0xffffffffinet6 fe80::f6d4:88ff:fe82:6d9e%utun3 prefixlen 64 scopeid 0x17inet6 2606:4700:110:8c7d:7369:7526:a59b:5636 prefixlen 128nd6 options=201<PERFORMNUD,DAD>
On Windows, run ipconfig
. When WARP is turned on, you will see an adapter called CloudflareWARP
with IP address 172.16.0.2
.
PS C:\> ipconfigWindows IP ConfigurationUnknown adapter CloudflareWARP:Connection-specific DNS Suffix . :Description . . . . . . . . . . . : Cloudflare WARP Interface TunnelPhysical Address. . . . . . . . . :DHCP Enabled. . . . . . . . . . . : NoAutoconfiguration Enabled . . . . : YesIPv6 Address. . . . . . . . . . . : 2606:4700:110:8f79:145:f180:fc4:8106(Preferred)Link-local IPv6 Address . . . . . : fe80::83b:d647:4bed:d388%49(Preferred)IPv4 Address. . . . . . . . . . . : 172.16.0.2(Preferred)Subnet Mask . . . . . . . . . . . : 255.255.255.255Default Gateway . . . . . . . . . :DNS Servers . . . . . . . . . . . : 127.0.2.2127.0.2.3NetBIOS over Tcpip. . . . . . . . : Enabled
On Linux, run ifconfig
or ip addr
. When WARP is turned on, you will see a utun
interface with IP address 172.16.0.2
.
$ ip addr<redacted>3: CloudflareWARP: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1280 qdisc mq state UNKNOWN group default qlen 500link/noneinet 172.16.0.2/32 scope global CloudflareWARPvalid_lft forever preferred_lft foreverinet6 2606:4700:110:8a2e:a5f7:a8de:a1f9:919/128 scope globalvalid_lft forever preferred_lft foreverinet6 fe80::117e:276b:8a79:c498/64 scope link stable-privacyvalid_lft forever preferred_lft forever
Routing table
WARP edits the system routing table to control what traffic goes down the Wireguard tunnel to Gateway. The routing table indicates which network interface should handle packets to a particular IP address. By default, all traffic routes through WARP’s virtual interface except for the IPs and domains on your Split Tunnel exclude list (which use the default interface on your device).
You can verify that the routing table matches your Split Tunnel rules:
To view the entire routing table on macOS, run netstat -r
.
You can also search the routing table for a domain or IP address. In this example, we see that traffic to google.com
is sent through utun3
, which is the WARP virtual interface on this device:
$ route get google.comroute to: lga25s81-in-f14.1e100.netdestination: 136.0.0.0mask: 248.0.0.0interface: utun3flags: <UP,DONE,PRCLONING>recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire0 0 0 0 0 0 1280 0
In contrast, this DHCP address is excluded from WARP and uses the default interface:
$ route get 169.254.0.0route to: 169.254.0.0destination: 169.254.0.0mask: 255.255.0.0interface: en0flags: <UP,DONE,CLONING,STATIC>recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire0 0 0 0 0 0 1500 -210842
To view the entire routing table on Windows, run netstat -r
.
You can also search the routing table for an IP address. In this example, we see that traffic to 1.1.1.1
is sent through the WARP virtual interface:
PS C:/> Find-NetRoute -RemoteIPAddress "1.1.1.1" | Select-Object InterfaceAlias -Last 1InterfaceAlias--------------CloudflareWARP
In contrast, this DHCP address is excluded from WARP and uses the default interface :
PS C:\> Find-NetRoute -RemoteIPAddress "169.254.0.0" | Select-Object InterfaceAlias -Last 1InterfaceAlias--------------Wi-Fi
To view the entire routing table on Linux, run ip -6 route show table all
or ip -4 route show table all
.
You can also search the routing table for an IP address. In this example, we see that traffic to 1.1.1.1
is sent through the WARP virtual interface:
$ ip route get 1.1.1.11.1.1.1 dev CloudflareWARP table 65743 src 172.16.0.2 uid 1000cache
In contrast, this DHCP address is excluded from WARP and uses the default interface:
$ ip route get 169.254.0.0169.254.0.0 dev ens18 src 172.24.8.6 uid 1000cache
System firewall
WARP modifies the operating system firewall to enforce your Split Tunnel rules. This adds a layer of protection in case a service bypasses the routing table and tries to send traffic directly through another interface. For example, if traffic to 203.0.113.0
is supposed to be inspected by Gateway, we create a firewall rule that blocks 203.0.113.0
on all interfaces except for utun
.
iOS, Android, and ChromeOS
On iOS and Android/ChromeOS, the Cloudflare One Agent installs itself as a VPN client to capture and route all traffic. The app is built on the official VPN framework for iOS and Android. For more information, refer to Apple’s NetworkExtension documentation and Google’s Android developer documentation.
Note that ChromeOS runs the Android app in a virtual machine, rather than running a native Chrome app.