How to Run Cloudflare WARP and a Corporate VPN Simultaneously on Linux
Modern Linux systems often need to run multiple VPNs at the same time. A common setup: Cloudflare WARP for secure internet access and an enterprise VPN (Array Networks / MotionPro) for internal company servers, where only specific internal IPs should go through the enterprise VPN.
What We’re Solving
| Traffic | Route |
|---|---|
| Internet | Cloudflare WARP |
| Internal server (10.0.50.10) | MotionPro VPN |
| Everything else | Unchanged |
Environment Overview
VPNs
- Enterprise VPN: Array Networks / Ivanti MotionPro
- CLI:
vpn_cmdline - Tunnel interface:
tun0
- CLI:
- External VPN: Cloudflare WARP
- Interface:
CloudflareWARP - Uses policy routing
- Interface:
Target
- Internal SSH server:
10.0.50.10
Part 1: Connecting to MotionPro on Linux
Installation (Arch Linux)
yay -S motionproVerify:
which vpn_cmdline
# /usr/bin/vpn_cmdlineHost Format
vpn_cmdline expects:
<gateway_host>[/alias]
Do NOT use https://, browser URLs, /login/index.html, or /prx/000/http/....
Correct examples:
vpn.example.com
vpn.example.com/employee
198.51.100.10
198.51.100.10/demoBasic Connection
sudo vpn_cmdline \
-h 198.51.100.10 \
-u demo_user \
-p 'your_password'Successful output:
login successfully!
starting vpn......
connect successfully!
vpn is running...
Authentication Method (if required)
Some gateways require specifying the auth backend:
sudo vpn_cmdline \
-h 198.51.100.10 \
-u demo_user \
-p 'your_password' \
-m LDAP_METHODSafer Password Handling
read -s VPN_PASS
sudo vpn_cmdline -h 198.51.100.10 -u demo_user -p "$VPN_PASS"
unset VPN_PASSVerify VPN Tunnel
ip addr | grep tun0Expected:
tun0 ... inet 192.168.x.x peer 1.1.1.1
Disconnecting
sudo vpn_cmdline --stopPart 2: Understanding the Routing Conflict
Why SSH Doesn’t Work Initially
Check how traffic to the internal server is routed:
ip route get 10.0.50.10Problematic output:
10.0.50.10 via 1.1.1.1 dev CloudflareWARP src 172.16.0.2
This means Cloudflare WARP captured the traffic. MotionPro never sees the packets. SSH hangs or times out.
Why This Happens
Cloudflare WARP uses its own routing table, policy routing (ip rule), and high-priority rules that override normal routes. Because of this, ip route add alone is not enough — we must override both routing and policy.
Part 3: Routing a Specific IP Through MotionPro
Step 1: Replace the Route
sudo ip route replace 10.0.50.10/32 dev tun0
sudo ip route flush cacheVerify:
ip route get 10.0.50.10Expected:
10.0.50.10 dev tun0 src 192.168.x.x
Step 2: Override WARP Policy Routing
Check policy rules:
ip ruleTypical output includes:
1000: from all lookup warp
Step 3: Add a Higher-Priority Policy Rule
sudo ip rule add to 10.0.50.10/32 lookup main priority 100
sudo ip route flush cacheVerify again:
ip route get 10.0.50.10Now traffic flows through tun0.
Step 4: Test SSH
ssh demo_user@10.0.50.10If it connects, routing is correct and VPN coexistence is successful.
Part 4: Optional Enhancements
Routing an Entire Subnet
sudo ip route replace 10.0.0.0/8 dev tun0
sudo ip rule add to 10.0.0.0/8 lookup main priority 100
sudo ip route flush cacheMake It Persistent
sudo nano /usr/local/bin/motionpro-split-routing.sh#!/bin/bash
ip route replace 10.0.50.10/32 dev tun0
ip rule add to 10.0.50.10/32 lookup main priority 100 || true
ip route flush cachesudo chmod +x /usr/local/bin/motionpro-split-routing.shKey Takeaways
- Multiple VPNs can coexist on Linux
- Cloudflare WARP uses policy routing
/32host routes are precise and safeip route replace>ip route addip ruleenables deterministic control- WARP never had to be disabled
Final Architecture
Internet traffic → Cloudflare WARP
10.0.50.10 (SSH) → MotionPro VPN (tun0)
Everything else → unchanged