WARP on the exit: connecting it
Why WARP on the exit — we covered that in the theory. Now let's set it up. I'll show how I connect a WARP outbound on a production node: credentials via wgcf, a wireguard outbound, routing rules for OpenAI/Spotify/Netflix, and the two traps everyone stumbles on — reserved and noKernelTun.
Read the theory →This material is about engineering your own infrastructure and is educational in nature. Complying with the laws of your own jurisdiction is on you.
Step 1: WARP credentials via wgcf
wgcf registers a free WARP account and issues a WireGuard profile (private key, v4/v6 addresses). The asset has a versioned name — there's no static link, so we pull the current one via the GitHub API:
WGCF_URL=$(curl -fsSL https://api.github.com/repos/ViRb3/wgcf/releases/latest \
| grep -oE 'https://[^"]*wgcf_[0-9.]+_linux_amd64' | head -1)
curl -fsSL -o /usr/bin/wgcf "$WGCF_URL"
chmod +x /usr/bin/wgcf
wgcf register # creates wgcf-account.toml (accept the ToS)
wgcf generate # creates wgcf-profile.conf (PrivateKey, Address v4/v6)
cat wgcf-profile.confFrom wgcf-profile.conf we need PrivateKey and Address (v4/v6). From wgcf-account.toml we'll need client_id — reserved is computed from it (more on that below).
Step 2: the wireguard outbound in the node config
Into the outbounds section of the config we add WARP. The comments say where to get what:
{
"tag": "warp",
"protocol": "wireguard",
"settings": {
"secretKey": "PRIVATE_KEY_X25519",
"address": ["172.16.0.2/32", "2606:4700:110:XXXX/128"],
"peers": [{
"publicKey": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=",
"endpoint": "162.159.192.1:2408"
}],
"mtu": 1280,
"reserved": [0, 0, 0],
"noKernelTun": true
}
}Breakdown of the fields:
secretKey—PrivateKeyfromwgcf-profile.conf.address— the v4/v6Addressfrom the profile. No IPv6 on the kernel — remove the v6 address, WARP will issue v6 itself.- the peer's
publicKey— the Cloudflare WARP public key (a constant, as in the example). endpoint— an explicit IPv4162.159.192.1:2408. If you leave the domain name, it resolves to IPv6, and on a node without v6 WARP "hangs."reserved— critical, see the traps.noKernelTun: true— mandatory on a node in Docker.
Step 3: routing — what to send through WARP
Above the DIRECT/proxy rules we add: the domains of services that cut data centers → into warp. Everything else goes as it went:
{
"type": "field",
"outboundTag": "warp",
"domain": [
"geosite:openai",
"domain:chatgpt.com",
"domain:oaistatic.com",
"domain:spotify.com",
"domain:scdn.co",
"geosite:netflix"
]
}This way only what otherwise wouldn't work goes through WARP — the speed of the main traffic doesn't sag.
Trap 1: reserved (or the handshake hangs)
reserved is 3 bytes computed from your account's client_id. Without a correct reserved, the handshake to fresh WARP endpoints doesn't go through — the connection simply hangs. It's not directly in wgcf-profile.conf: get it via a "wgcf → Xray reserved" converter from the client_id/Reserved in wgcf-account.toml. Many panels compute it themselves — if you've set it and WARP hangs, recompute reserved first.
Trap 2: noKernelTun on a node in Docker
The top trap specifically on panel nodes. The symptom — WARP won't start, and in the node's logs:
failed to disable ipv4 rp_filter for all: open /proc/sys/net/ipv4/conf/all/rp_filter: read-only file systemThe cause: the node's Xray runs in Docker, where /proc/sys is mounted read-only, while fresh Xray by default brings up WireGuard via kernel-TUN, which needs write access to /proc/sys. Cured by a single line "noKernelTun": true in the WARP outbound's settings — this is a return to the userspace stack, /proc/sys is no longer touched. After the change — restart the node, and the line Using kernel TUN should disappear from the log.
Step 4: verification
WARP isn't visible to the client and creates no Host — it's an internal node egress. We check it like this:
- Connect with the client, open
chat.openai.com— it should work. - On
2ip.rusee what your IP appears as: for OpenAI/Spotify it'll be Cloudflare, for everything else — your node.
If OpenAI came to life while the rest of the traffic still goes through the node — WARP is assembled correctly: a targeted white exit only for the problem services.
WARP+ (if you need speed)
Free WARP is rate-limited. There's a WARP+ license key — bind it and regenerate the profile:
wgcf update --license-key YOUR_KEY
wgcf generateFor serious load — WARP+ or several WARP accounts with balancing between the warp outbounds.
Why all of this and what WARP solves and doesn't (geo, account, residency) — we covered in the paired theory "WARP on the exit: why and what it gives."
Next guide Zapret and unblocking YouTube → ↗ Article unclear or something off? Message me and I will help or fix it. @notrealvpn →