Deploy cf-xray-proxy with Wrangler or the Cloudflare dashboard, then validate tunnel paths and observability.
Protocols: VLESS / VMess / Trojan; Transports: ws / xhttp / httpupgrade.
- Authenticate:
wrangler login-
Confirm Worker settings in
wrangler.toml:namemaincompatibility_date[vars]values (backend pool, retries, limits, transport, debug settings, andHIDE_BACKEND_URLS)
-
Deploy:
wrangler deploy- Verify:
- open the deployed Worker URL in a browser for the landing page (
/), - run the Quickstart transport checks against the deployed domain.
- open the deployed Worker URL in a browser for the landing page (
- Go to Workers & Pages and create/import the Worker.
- Ensure the main script entry maps to this repository Worker.
- In Settings -> Variables and Secrets, add runtime variables.
- Deploy from the dashboard.
- Test:
GET /for the landing page,- transport checks (
/ws/<path>,/xhttp/<path>,/httpupgrade/<path>).
Use the checks below to isolate the issue quickly.
ss -ltnp | grep -E '(:10000|:443|:80)'
lsof -iTCP -sTCP:LISTEN -n -P
curl -i --http1.1 "http://<backend-host>:<backend-port>/<path>"curl -i --http1.1 \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
"http://<backend-host>:<backend-port>/<path>"| Field | Where to set | Must align with |
|---|---|---|
| Host | Client URI/headers | Worker domain and backend expectations |
| SNI | Client TLS config | Worker certificate domain |
| Path | Client path |
Backend inbound path |
| Transport type | Client config | Worker route selection and backend inbound type |
Use matching transports on both client and backend (ws, xhttp, httpupgrade).
DEBUG="true" wrangler dev
wrangler tailLook for handler prefixes: [cf-xray-proxy], [ws], [xhttp], [httpupgrade].
- Backend Xray/sing-box remains the authority for authentication and protocol policy.
- Enable
RATE_LIMIT_ENABLED=trueto reduce abusive connection churn without limiting normal tunnel payload traffic. - Use
UUID_MAX_CONNECTIONSto cap concurrent usage per UUID (0keeps the feature disabled). - Prefer private/internal backend addresses and restrict backend ingress to expected sources.
- Use
BACKEND_LISTto isolate failure domains across backend instances. - Keep
DEBUG=falsein normal production operation.
When SUBSCRIPTION_ENABLED=false:
GET /andGET /index.htmldocument requests are served bysrc/landing.tswith:
Cache-Control: public, max-age=3600
When SUBSCRIPTION_ENABLED=true:
- root requests return subscription info text instead of the HTML landing page.