vercel-xhttp-relay

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vercel XHTTP Relay

Vercel XHTTP中继

Skill by ara.so — Daily 2026 Skills collection.
A minimal Vercel Edge Function relay that forwards XHTTP traffic from Xray/V2Ray clients to a backend Xray server. Vercel's
*.vercel.app
domain acts as a CDN front, hiding your origin VPS IP from censors.

ara.so提供的技能——Daily 2026技能合集。
这是一个轻量的Vercel Edge Function中继,可将Xray/V2Ray客户端的XHTTP流量转发到后端Xray服务器。Vercel的
*.vercel.app
域名作为CDN前端,可向审查者隐藏你的源VPS IP。

Architecture

架构

Client (v2rayN/Hiddify)
  → TLS (SNI=vercel.com) to *.vercel.app
    → Vercel Edge Function (relay, no buffer)
      → HTTP/2 to backend Xray XHTTP inbound
Supported transports: XHTTP only
Not supported on Vercel Edge: WebSocket, gRPC, TCP, mKCP, QUIC, Reality

客户端 (v2rayN/Hiddify)
  → TLS (SNI=vercel.com) 连接至 *.vercel.app
    → Vercel Edge Function (中继,无缓冲)
      → HTTP/2 连接至后端Xray XHTTP入站
支持的传输协议:仅XHTTP
Vercel Edge不支持: WebSocket、gRPC、TCP、mKCP、QUIC、Reality

Prerequisites

前置条件

  • Linux VPS outside Iran (Ubuntu 22.04/24.04 recommended), min 1 vCPU / 1 GB RAM
  • A domain with an A record pointing to your VPS (DNS only, not proxied)
  • Vercel account (free Hobby tier works for light personal use)
  • Node.js + npm installed locally (for Vercel CLI)
  • Xray v1.8.16+ installed on VPS

  • 伊朗境外的Linux VPS(推荐Ubuntu 22.04/24.04),至少1核CPU / 1GB内存
  • 一条A记录指向你的VPS的域名(仅DNS解析,不开启代理)
  • Vercel账户(免费Hobby套餐适用于轻度个人使用)
  • 本地安装Node.js + npm(用于Vercel CLI)
  • VPS上安装Xray v1.8.16+版本

Step 1 — Install Xray on VPS

步骤1 — 在VPS上安装Xray

bash
undefined
bash
undefined

Update system

更新系统

apt update && apt upgrade -y apt install -y curl socat cron ufw
apt update && apt upgrade -y apt install -y curl socat cron ufw

Install Xray via official script

通过官方脚本安装Xray

Verify version (must be >= 1.8.16)

验证版本(必须 >= 1.8.16)

xray version
xray version

Generate a UUID for your inbound

为入站生成UUID

xray uuid
xray uuid

Save this UUID — you'll need it in client and server configs

保存此UUID——客户端和服务器配置都会用到


---

---

Step 2 — Obtain a TLS Certificate

步骤2 — 获取TLS证书

bash
undefined
bash
undefined

Install acme.sh

安装acme.sh

curl https://get.acme.sh | sh source ~/.bashrc # or re-login
curl https://get.acme.sh | sh source ~/.bashrc # 或重新登录

Issue certificate (replace with your domain)

申请证书(替换为你的域名)

~/.acme.sh/acme.sh --issue --standalone -d xray.yourdomain.com
~/.acme.sh/acme.sh --issue --standalone -d xray.yourdomain.com

Install certificate to Xray paths

将证书安装到Xray路径

~/.acme.sh/acme.sh --install-cert -d xray.yourdomain.com
--key-file /etc/xray/private.key
--fullchain-file /etc/xray/cert.crt
--reloadcmd "systemctl restart xray"

---
~/.acme.sh/acme.sh --install-cert -d xray.yourdomain.com
--key-file /etc/xray/private.key
--fullchain-file /etc/xray/cert.crt
--reloadcmd "systemctl restart xray"

---

Step 3 — Xray Server Config (XHTTP Inbound)

步骤3 — Xray服务器配置(XHTTP入站)

/etc/xray/config.json
:
json
{
  "log": { "loglevel": "warning" },
  "inbounds": [
    {
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "$YOUR_UUID",
            "flow": ""
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "xhttp",
        "security": "tls",
        "tlsSettings": {
          "certificates": [
            {
              "certificateFile": "/etc/xray/cert.crt",
              "keyFile": "/etc/xray/private.key"
            }
          ]
        },
        "xhttpSettings": {
          "path": "/your-secret-path",
          "mode": "auto"
        }
      }
    }
  ],
  "outbounds": [
    { "protocol": "freedom", "tag": "direct" }
  ]
}
bash
undefined
/etc/xray/config.json
:
json
{
  "log": { "loglevel": "warning" },
  "inbounds": [
    {
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "$YOUR_UUID",
            "flow": ""
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "xhttp",
        "security": "tls",
        "tlsSettings": {
          "certificates": [
            {
              "certificateFile": "/etc/xray/cert.crt",
              "keyFile": "/etc/xray/private.key"
            }
          ]
        },
        "xhttpSettings": {
          "path": "/your-secret-path",
          "mode": "auto"
        }
      }
    }
  ],
  "outbounds": [
    { "protocol": "freedom", "tag": "direct" }
  ]
}
bash
undefined

Apply and start

应用配置并启动

systemctl restart xray systemctl enable xray systemctl status xray

---
systemctl restart xray systemctl enable xray systemctl status xray

---

Step 4 — The Vercel Edge Relay (api/proxy.js)

步骤4 — Vercel Edge中继(api/proxy.js)

The relay function streams request bodies and responses without buffering:
javascript
// api/proxy.js  — Vercel Edge Function
export const config = { runtime: 'edge' };

const BACKEND = process.env.XRAY_BACKEND_URL;
// e.g. https://xray.yourdomain.com:443/your-secret-path

export default async function handler(req) {
  if (!BACKEND) {
    return new Response('Backend not configured', { status: 500 });
  }

  const url = new URL(req.url);
  const targetUrl = BACKEND + url.pathname.replace(/^\/proxy/, '') + url.search;

  // Forward all headers except host
  const headers = new Headers();
  for (const [key, value] of req.headers.entries()) {
    if (key.toLowerCase() !== 'host') {
      headers.set(key, value);
    }
  }

  try {
    const response = await fetch(targetUrl, {
      method: req.method,
      headers,
      body: req.method !== 'GET' && req.method !== 'HEAD' ? req.body : undefined,
      // @ts-ignore — duplex required for streaming body
      duplex: 'half',
    });

    return new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: response.headers,
    });
  } catch (err) {
    return new Response(`Relay error: ${err.message}`, { status: 502 });
  }
}

中继函数会流式传输请求体和响应,无缓冲:
javascript
// api/proxy.js  — Vercel Edge Function
export const config = { runtime: 'edge' };

const BACKEND = process.env.XRAY_BACKEND_URL;
// 示例:https://xray.yourdomain.com:443/your-secret-path

export default async function handler(req) {
  if (!BACKEND) {
    return new Response('Backend not configured', { status: 500 });
  }

  const url = new URL(req.url);
  const targetUrl = BACKEND + url.pathname.replace(/^\/proxy/, '') + url.search;

  // 转发除host外的所有请求头
  const headers = new Headers();
  for (const [key, value] of req.headers.entries()) {
    if (key.toLowerCase() !== 'host') {
      headers.set(key, value);
    }
  }

  try {
    const response = await fetch(targetUrl, {
      method: req.method,
      headers,
      body: req.method !== 'GET' && req.method !== 'HEAD' ? req.body : undefined,
      // @ts-ignore — 流式传输body需要duplex参数
      duplex: 'half',
    });

    return new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: response.headers,
    });
  } catch (err) {
    return new Response(`Relay error: ${err.message}`, { status: 502 });
  }
}

Step 5 — vercel.json

步骤5 — vercel.json

json
{
  "rewrites": [
    { "source": "/(.*)", "destination": "/api/proxy" }
  ]
}

json
{
  "rewrites": [
    { "source": "/(.*)", "destination": "/api/proxy" }
  ]
}

Step 6 — package.json (minimal)

步骤6 — package.json(最简版)

json
{
  "name": "vercel-xhttp-relay",
  "version": "1.0.0",
  "private": true
}

json
{
  "name": "vercel-xhttp-relay",
  "version": "1.0.0",
  "private": true
}

Step 7 — Deploy to Vercel

步骤7 — 部署到Vercel

Via CLI

通过CLI部署

bash
undefined
bash
undefined

Install Vercel CLI

安装Vercel CLI

npm i -g vercel
npm i -g vercel

Login

登录

vercel login
vercel login

Deploy (from project root)

部署(从项目根目录执行)

vercel
vercel

Set the backend environment variable

设置后端环境变量

vercel env add XRAY_BACKEND_URL
vercel env add XRAY_BACKEND_URL

Redeploy with env var active

重新部署并启用环境变量

vercel --prod
undefined
vercel --prod
undefined

Via Dashboard (no CLI needed)

通过控制台部署(无需CLI)

  1. Push repo to GitHub
  2. Go to vercel.com/new → Import repo
  3. Settings → Environment Variables → add
    XRAY_BACKEND_URL
  4. Deploy
Your relay URL will be:
https://your-project.vercel.app

  1. 将代码仓库推送到GitHub
  2. 访问vercel.com/new → 导入仓库
  3. 设置 → 环境变量 → 添加
    XRAY_BACKEND_URL
  4. 部署
你的中继URL为:
https://your-project.vercel.app

Step 8 — Client Configuration (v2rayN / Hiddify)

步骤8 — 客户端配置(v2rayN / Hiddify)

FieldValue
ProtocolVLESS
Address
your-project.vercel.app
Port
443
UUID
$YOUR_UUID
(from
xray uuid
)
TransportXHTTP
Path
/your-secret-path
TLSTLS
SNI
vercel.com
Fingerprint
chrome
Flow(empty)
VLESS link format:
vless://$YOUR_UUID@your-project.vercel.app:443?encryption=none&security=tls&sni=vercel.com&fp=chrome&type=xhttp&path=%2Fyour-secret-path#MyVercelRelay

字段
协议VLESS
地址
your-project.vercel.app
端口
443
UUID
$YOUR_UUID
(来自
xray uuid
命令)
传输协议XHTTP
路径
/your-secret-path
TLS开启TLS
SNI
vercel.com
指纹
chrome
Flow(留空)
VLESS链接格式:
vless://$YOUR_UUID@your-project.vercel.app:443?encryption=none&security=tls&sni=vercel.com&fp=chrome&type=xhttp&path=%2Fyour-secret-path#MyVercelRelay

Project File Structure

项目文件结构

vercel-xhttp-relay/
├── api/
│   └── proxy.js        # Edge Function relay
├── vercel.json         # Rewrite rules
└── package.json

vercel-xhttp-relay/
├── api/
│   └── proxy.js        # Edge Function中继
├── vercel.json         # 重写规则
└── package.json

Environment Variables

环境变量

VariableDescriptionExample
XRAY_BACKEND_URL
Full URL to your Xray XHTTP inbound
https://xray.yourdomain.com:443/secret-path
Set via CLI:
bash
vercel env add XRAY_BACKEND_URL production
vercel env add XRAY_BACKEND_URL preview
Or in
vercel.json
for non-secret config (not recommended for backend URLs):
json
{
  "env": {
    "XRAY_BACKEND_URL": "@xray-backend-url"
  }
}

变量描述示例
XRAY_BACKEND_URL
Xray XHTTP入站的完整URL
https://xray.yourdomain.com:443/secret-path
通过CLI设置:
bash
vercel env add XRAY_BACKEND_URL production
vercel env add XRAY_BACKEND_URL preview
或在
vercel.json
中设置非敏感配置(不推荐用于后端URL):
json
{
  "env": {
    "XRAY_BACKEND_URL": "@xray-backend-url"
  }
}

Firewall Setup on VPS

VPS防火墙设置

bash
undefined
bash
undefined

Allow SSH, XHTTP port

允许SSH和XHTTP端口

ufw allow 22/tcp ufw allow 443/tcp ufw enable ufw status

---
ufw allow 22/tcp ufw allow 443/tcp ufw enable ufw status

---

Common Patterns

常见用法

Multiple Vercel Projects for Failover

多Vercel项目实现故障转移

Deploy the same relay to multiple Vercel accounts and configure load balance in v2rayN:
json
// v2rayN outbound balancer (simplified concept)
{
  "tag": "balancer",
  "selector": ["relay1", "relay2", "relay3"]
}
将相同中继部署到多个Vercel账户,并在v2rayN中配置负载均衡:
json
// v2rayN出站负载均衡(简化示例)
{
  "tag": "balancer",
  "selector": ["relay1", "relay2", "relay3"]
}

Check Vercel Usage

查看Vercel使用情况

bash
vercel billing
bash
vercel billing

Or monitor at: https://vercel.com/dashboard → Usage tab

或在以下地址监控:https://vercel.com/dashboard → 使用情况标签页

undefined
undefined

Redeploy After Config Change

配置变更后重新部署

bash
vercel --prod
bash
vercel --prod

View Logs

查看日志

bash
vercel logs your-project.vercel.app --follow

bash
vercel logs your-project.vercel.app --follow

Troubleshooting

故障排查

502 Bad Gateway from Vercel

Vercel返回502 Bad Gateway

bash
undefined
bash
undefined

Check Xray is running

检查Xray是否运行

systemctl status xray
systemctl status xray

Check Xray logs

查看Xray日志

journalctl -u xray -f
journalctl -u xray -f

Verify port 443 is open

验证443端口是否开放

ufw status ss -tlnp | grep 443
ufw status ss -tlnp | grep 443

Test backend directly (from your local machine, not Iran)

直接测试后端(从非伊朗地区的本地机器执行)

DNS Not Resolving

DNS解析失败

bash
undefined
bash
undefined

Mac/Linux

Mac/Linux

dig @8.8.8.8 xray.yourdomain.com +short
dig @8.8.8.8 xray.yourdomain.com +short

Windows PowerShell

Windows PowerShell

Resolve-DnsName xray.yourdomain.com -Server 8.8.8.8 -Type A

DNS record must be **DNS only** (grey cloud in Cloudflare), not proxied.
Resolve-DnsName xray.yourdomain.com -Server 8.8.8.8 -Type A

DNS记录必须设置为**仅DNS解析**(Cloudflare中显示灰色云朵),不能开启代理。

TLS Certificate Issues

TLS证书问题

bash
undefined
bash
undefined

Check cert expiry

检查证书有效期

~/.acme.sh/acme.sh --list
~/.acme.sh/acme.sh --list

Renew manually

手动更新证书

~/.acme.sh/acme.sh --renew -d xray.yourdomain.com --force
~/.acme.sh/acme.sh --renew -d xray.yourdomain.com --force

Verify cert is valid

验证证书有效性

openssl x509 -in /etc/xray/cert.crt -noout -dates
undefined
openssl x509 -in /etc/xray/cert.crt -noout -dates
undefined

Xray Config Validation

Xray配置验证

bash
xray run -test -c /etc/xray/config.json
bash
xray run -test -c /etc/xray/config.json

Should output: Configuration OK

应输出:Configuration OK

undefined
undefined

Client Can't Connect

客户端无法连接

  • Confirm SNI is set to
    vercel.com
    , not your project domain
  • Confirm transport is
    xhttp
    (not
    ws
    ,
    grpc
    , etc.)
  • Confirm path matches exactly between server config and client
  • Check UUID matches exactly
  • 确认SNI设置为
    vercel.com
    ,而非你的项目域名
  • 确认传输协议为
    xhttp
    (不是
    ws
    grpc
    等)
  • 确认服务器配置和客户端的路径完全一致
  • 确认UUID完全匹配

Vercel Account Paused (Hobby Bandwidth Exceeded)

Vercel账户暂停(Hobby套餐带宽超限)

Hobby plan counts bandwidth twice (client↔Vercel + Vercel↔origin). To avoid:
  • Exclude 4K video and large downloads from the proxy
  • Use multiple Hobby accounts with failover
  • Upgrade to Pro ($20/month) and set Spend Management limits

Hobby套餐的带宽会双向计算(客户端↔Vercel + Vercel↔源服务器)。避免超限的方法:
  • 排除4K视频和大文件下载使用代理
  • 使用多个Hobby账户实现故障转移
  • 升级到Pro套餐(每月20美元)并设置消费限额

Vercel Hobby Plan Limits (Reference)

Vercel Hobby套餐限制(参考)

ResourceLimit
Edge Function invocations500,000 / month
Fast Origin Transfer10 GB / month (counts both directions)
Bandwidth (to client)100 GB / month
Edge Function duration30 seconds max per request
Monitor at Vercel Dashboard → Usage. Vercel sends email alerts at 80% and 100%.

资源限制
Edge Function调用次数每月500,000次
快速源传输每月10GB(双向计算)
客户端带宽每月100GB
Edge Function单次请求时长最长30秒
Vercel控制台 → 使用情况中监控。当使用量达到80%和100%时,Vercel会发送邮件提醒。

Key Commands Cheatsheet

常用命令速查表

bash
undefined
bash
undefined

VPS: install/manage Xray

VPS:安装/管理Xray

bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install xray uuid xray version xray run -test -c /etc/xray/config.json systemctl restart xray && systemctl status xray journalctl -u xray -f
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install xray uuid xray version xray run -test -c /etc/xray/config.json systemctl restart xray && systemctl status xray journalctl -u xray -f

Local: Vercel CLI

本地:Vercel CLI

npm i -g vercel vercel login vercel # deploy preview vercel --prod # deploy production vercel env add XRAY_BACKEND_URL vercel logs your-project.vercel.app --follow vercel billing
undefined
npm i -g vercel vercel login vercel # 部署预览版 vercel --prod # 部署生产版 vercel env add XRAY_BACKEND_URL vercel logs your-project.vercel.app --follow vercel billing
undefined