NEW Check if your VPN is honest — a free subscription audit in 60 seconds
← Back to library
Bypass Practice

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

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:

get-wgcf.sh
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.conf

From wgcf-profile.conf we need PrivateKey and Address (v4/v6). From wgcf-account.toml we'll need client_idreserved 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:

config.json
{
  "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:

  • secretKeyPrivateKey from wgcf-profile.conf.
  • address — the v4/v6 Address from 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 IPv4 162.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:

config.json
{
  "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:

node-log
failed to disable ipv4 rp_filter for all: open /proc/sys/net/ipv4/conf/all/rp_filter: read-only file system

The 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.ru see 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:

warp-plus.sh
wgcf update --license-key YOUR_KEY
wgcf generate

For 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 →
This material is educational and covers network-infrastructure engineering. You are responsible for complying with the laws of your jurisdiction.