A lightweight VLESS proxy running on Cloudflare Workers, using WebSocket transport over Cloudflare's global edge network.
- Original project: FoxCloud by Hossein Pira & IRCF
- This fork: maintained by AliSawari — refactored transport layer, fixed Blob/ArrayBuffer handling for newer Cloudflare Workers runtime
V2ray Client ──(VLESS over WebSocket/TLS)──► Cloudflare Worker ──► Destination
The Worker accepts VLESS connections over WebSocket, parses the protocol header, and proxies TCP traffic (and DNS over UDP) to the target host using Cloudflare's connect() socket API.
git clone <your-fork-url>
cd foxcloud
npm install
npm run build
wrangler deployDownload worker.js from Releases and deploy directly:
wrangler deploy worker.js --name your-worker-nameSet these in your Cloudflare Worker settings or wrangler.toml:
| Variable | Description | Example |
|---|---|---|
UUID |
Comma-separated list of allowed UUIDs | 08dad8a6-8a6c-4424-9d63-62f3a9bf7f4f |
PROXY_IP |
Fallback relay IPs if direct connect fails | 172.66.45.9:443,104.18.128.25:443 |
Generate a UUID:
node -e "console.log(crypto.randomUUID())"PROXY_IP is a fallback exit relay — when the Worker can't reach a destination directly, it retries through these IPs. If you have a VPS with clean routing, put its IP here. Otherwise use public Cloudflare IPs.
After deploying, visit:
https://your-worker.workers.dev/<your-uuid>
This returns a base64-encoded subscription. Import it as a Subscription URL in your V2ray client — don't paste the raw output.
| Field | Value |
|---|---|
| Protocol | VLESS |
| Address | Your worker domain (or a clean CF IP — see below) |
| Port | 443 |
| UUID | Your configured UUID |
| Transport | WebSocket |
| Path | / |
| TLS | Enabled |
| SNI | Your worker domain |
| Fingerprint | chrome |
Disable Mux in your client config — the worker does not support multiplexing.
workers.dev is blocked on many ISPs. Two approaches:
1. CF IP scanning (quick) Use a tool like CloudflareScanner to find a low-latency Cloudflare IP that isn't blocked on your ISP. Put that IP in the Address field of your config, keep the worker domain in SNI and Host. Cloudflare routes by Host header, so your worker still receives the traffic.
2. Custom domain (recommended)
Attach your own domain to the worker in the Cloudflare dashboard (Workers → your worker → Domains & Routes). A domain on a less-blocked TLD (.xyz, .top, etc.) is more resilient than workers.dev and you can change it anytime.
npm run dev
# Worker runs at http://localhost:8787Note: cloudflare:sockets (used for outbound TCP) only works fully with --remote:
wrangler dev --remote- Transport layer abstracted to
ITransportinterface —tcp.tsanddns.tsare no longer coupled toWebSocket - Fixed
BlobvsArrayBuffernormalization in WebSocket message handling (causedDataViewconstructor errors on newer CF runtime) - Removed XHTTP/SplitHTTP code — not viable on CF Workers due to stateless isolate constraints and lack of long-lived streaming support
MIT — see LICENSE