vercel-xhttp-relay
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel 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 domain acts as a CDN front, hiding your origin VPS IP from censors.
*.vercel.app由ara.so提供的技能——Daily 2026技能合集。
这是一个轻量的Vercel Edge Function中继,可将Xray/V2Ray客户端的XHTTP流量转发到后端Xray服务器。Vercel的域名作为CDN前端,可向审查者隐藏你的源VPS IP。
*.vercel.appArchitecture
架构
Client (v2rayN/Hiddify)
→ TLS (SNI=vercel.com) to *.vercel.app
→ Vercel Edge Function (relay, no buffer)
→ HTTP/2 to backend Xray XHTTP inboundSupported transports: XHTTP only
Not supported on Vercel Edge: WebSocket, gRPC, TCP, mKCP, QUIC, Reality
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
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
undefinedbash
undefinedUpdate 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
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
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
undefinedbash
undefinedInstall 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"
--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"
--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.jsonjson
{
"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.jsonjson
{
"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
undefinedApply 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
undefinedbash
undefinedInstall 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
undefinedvercel --prod
undefinedVia Dashboard (no CLI needed)
通过控制台部署(无需CLI)
- Push repo to GitHub
- Go to vercel.com/new → Import repo
- Settings → Environment Variables → add
XRAY_BACKEND_URL - Deploy
Your relay URL will be:
https://your-project.vercel.app- 将代码仓库推送到GitHub
- 访问vercel.com/new → 导入仓库
- 设置 → 环境变量 → 添加
XRAY_BACKEND_URL - 部署
你的中继URL为:
https://your-project.vercel.appStep 8 — Client Configuration (v2rayN / Hiddify)
步骤8 — 客户端配置(v2rayN / Hiddify)
| Field | Value |
|---|---|
| Protocol | VLESS |
| Address | |
| Port | |
| UUID | |
| Transport | XHTTP |
| Path | |
| TLS | TLS |
| SNI | |
| Fingerprint | |
| 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 |
| 地址 | |
| 端口 | |
| UUID | |
| 传输协议 | XHTTP |
| 路径 | |
| TLS | 开启TLS |
| SNI | |
| 指纹 | |
| 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#MyVercelRelayProject File Structure
项目文件结构
vercel-xhttp-relay/
├── api/
│ └── proxy.js # Edge Function relay
├── vercel.json # Rewrite rules
└── package.jsonvercel-xhttp-relay/
├── api/
│ └── proxy.js # Edge Function中继
├── vercel.json # 重写规则
└── package.jsonEnvironment Variables
环境变量
| Variable | Description | Example |
|---|---|---|
| Full URL to your Xray XHTTP inbound | |
Set via CLI:
bash
vercel env add XRAY_BACKEND_URL production
vercel env add XRAY_BACKEND_URL previewOr in for non-secret config (not recommended for backend URLs):
vercel.jsonjson
{
"env": {
"XRAY_BACKEND_URL": "@xray-backend-url"
}
}| 变量 | 描述 | 示例 |
|---|---|---|
| Xray XHTTP入站的完整URL | |
通过CLI设置:
bash
vercel env add XRAY_BACKEND_URL production
vercel env add XRAY_BACKEND_URL preview或在中设置非敏感配置(不推荐用于后端URL):
vercel.jsonjson
{
"env": {
"XRAY_BACKEND_URL": "@xray-backend-url"
}
}Firewall Setup on VPS
VPS防火墙设置
bash
undefinedbash
undefinedAllow 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 billingbash
vercel billingOr monitor at: https://vercel.com/dashboard → Usage tab
或在以下地址监控:https://vercel.com/dashboard → 使用情况标签页
undefinedundefinedRedeploy After Config Change
配置变更后重新部署
bash
vercel --prodbash
vercel --prodView Logs
查看日志
bash
vercel logs your-project.vercel.app --followbash
vercel logs your-project.vercel.app --followTroubleshooting
故障排查
502 Bad Gateway from Vercel
Vercel返回502 Bad Gateway
bash
undefinedbash
undefinedCheck 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)
直接测试后端(从非伊朗地区的本地机器执行)
undefinedundefinedDNS Not Resolving
DNS解析失败
bash
undefinedbash
undefinedMac/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
undefinedbash
undefinedCheck 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
undefinedopenssl x509 -in /etc/xray/cert.crt -noout -dates
undefinedXray Config Validation
Xray配置验证
bash
xray run -test -c /etc/xray/config.jsonbash
xray run -test -c /etc/xray/config.jsonShould output: Configuration OK
应输出:Configuration OK
undefinedundefinedClient Can't Connect
客户端无法连接
- Confirm SNI is set to , not your project domain
vercel.com - Confirm transport is (not
xhttp,ws, etc.)grpc - 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套餐限制(参考)
| Resource | Limit |
|---|---|
| Edge Function invocations | 500,000 / month |
| Fast Origin Transfer | 10 GB / month (counts both directions) |
| Bandwidth (to client) | 100 GB / month |
| Edge Function duration | 30 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
undefinedbash
undefinedVPS: 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
undefinednpm i -g vercel
vercel login
vercel # 部署预览版
vercel --prod # 部署生产版
vercel env add XRAY_BACKEND_URL
vercel logs your-project.vercel.app --follow
vercel billing
undefined