已彻底转向 Xray-core,本文不再维护,请自行判断是否过时
TIP观前提醒
本文仅给出三份重要的配置示例,阅读需具备相关知识
如果你是初次搭建,建议查看完整版
本教程基于
Xray 服务端 + Caddy 反代 + mihomo 客户端构建本教程几乎全程手敲命令,不借助 3x-ui 此类面板,需要一定耐心
如果想一键部署,很遗憾,本文不适合你
XHTTP 五合一指的是在同一台 VPS 的 443 端口实现了五个出站节点:
点击查看 适用场景
(此处部分引用 @Benjamin1919 大佬的教程原文案)
出站 1:XTLS(Vision) + REALITY 直连
- 客户端 GUI 不支持 XHTTP
- 不想开启 TCP 多路复用
- 想要尽可能低的延迟与尽可能高的上下行速度
出站 2:XHTTP + REALITY 直连
- VPS 去程和回程的线路都比较好
- 想要尽可能低的延迟与尽可能高的上下行速度
出站 3:上行 XHTTP + TLS(ECH) + CDN | 下行 XHTTP + REALITY(上下行不同 SNI)
- 去程(客户端 → VPS)线路较差,回程(VPS → 客户端)线路较好
- 日常使用更偏重下载,很少上传
- 隐藏上行 SNI 防探测封锁
出站 4:XHTTP + TLS(ECH) 过 CDN
- VPS 去程和回程的线路都很差
- 不希望 VPS 的 IP 暴露在公网
- VPS 的 IP 已被墙
- 隐藏 SNI 防探测封锁
出站 5:上行 XHTTP + REALITY | 下行 XHTTP + TLS(ECH) + CDN(上下行不同 SNI)
- 去程(客户端 → VPS)线路较好,回程(VPS → 客户端)线路较差
- 日常使用更偏重上传,很少下载
- 隐藏下行 SNI 防探测封锁
目录
1. 准备工作
在开始之前,请准备好以下内容:
- 一个个人域名
- 一个通过支付验证的 Cloudflare 账号
- 一台拥有 root 完全访问权限的 VPS
NOTE为避免纠纷,本文不提供任何 VPS 商家推荐或购买指导,请自行选择。
本方案属于 Xray 前置、REALITY 回落到本机 Caddy,不需要配置
limitFallbackUpload,本文中的
<VPS_IP>、<YOUR_USER>、<YOUR_DOMAIN>均为占位符,实际操作时请替换为你的真实 IP、用户名和域名。SSH 端口以
<SSH_PORT>表示(示例为54321),请根据实际部署修改。
2. Cloudflare 配置
2.1 添加 DNS 记录
将域名托管到 Cloudflare,添加 DNS 解析记录:
| 记录类型 | 子域名 | 值 | 小黄云(Proxy) | 用途 |
|---|---|---|---|---|
| A | cdn.<YOUR_DOMAIN> | VPS IPv4 | 开启 | CDN 回源 |
| A | REALITY.<YOUR_DOMAIN> | VPS IPv4 | 关闭 | REALITY 握手直连 |
如果需要双栈,可额外添加 AAAA 记录,可复用同一个子域名。
2.2 SSL/TLS 设置
面板左侧 -> SSL/TLS -> 概述 -> 配置 -> 加密模式和源连接设置 -> 加密模式设置为 完全(严格)
面板左侧 -> SSL/TLS -> 边缘证书 -> 开启 TLS 1.3
面板左侧 -> 网络 -> 开启 gRPC
2.3 缓存规则设置
为避免 XHTTP 请求被缓存,创建缓存规则:
面板左侧 -> 缓存 -> Cache Rules -> 创建缓存规则:
- 名称:随意
如果传入请求匹配…-> 选择自定义筛选表达式-> 点击编辑表达式- 输入(替换为你的域名和路径):
(http.host eq "cdn.<YOUR_DOMAIN>") or (http.request.uri.path contains "/<YOUR_XHTTP_PATH>")缓存资格→ 设置为绕过缓存
3. 安装 Xray-core 与 Caddy
3.1 安装 Xray-core
通过官方脚本裸装(Bare-metal)并使用 systemd 管理:
推荐安装 Pre-release 版本,目前 Stable 版本还停留在 v26.3.27,新版本包含 XHTTP 修复和功能修复等
发版策略说明
RPRX(Owner):
忘公开说明一下了,关于 Xray-core 的发版策略, pre-release 有可能是实际意义上的 stable,而 latest 也不等于“没有 bug”
没标 latest 通常是因为我觉得下个 stable 该包含什么但它还没有包含,
或者单纯懒得写 release notes 那就算了下次吧,感觉比写代码都麻烦
mihomo 客户端兼容性说明
Xray-core v26.7.11 增加了 REALITY 最低客户端版本校验(
minClientVer),默认要求客户端版本 ≥26.3.27由于 mihomo 底层硬编码了版本号1.8.2,两者不兼容时将导致 REALITY 握手失败本教程的服务端配置模板已在
realitySettings中显式添加"minClientVer": "1.8.2"以绕过此限制,安装最新版 Xray-core 即可正常工作具体情况请见相关 Issue / PR:
sudo bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install --beta如果你依然偏向
Stable,把命令的--beta去掉即为下载“正式版”
安装完成时会默认启动服务,需要先暂停:
sudo systemctl stop xray3.2 生成凭据
生成 UUID(需要两组,分别用于 Vision 和 XHTTP):
# 执行两次,得到两个不同的 UUIDxray uuidxray uuid分别记为 UUID_01 和 UUID_02,保存待用。
生成 REALITY 密钥对:
xray x25519保存输出的 Private key 和 Public key,私钥填在服务端的 config.json,公钥填在本地客户端里。
生成 shortID:
openssl rand -hex 83.3 写入 Xray 配置文件
TIP请在本地的文本编辑器,将以下代码块中的占位符替换为你自己的真实信息。替换完成后,粘贴到 VPS 终端中并回车
NOTE占位符说明:
| 占位符 | 替换为 |
|---|---|
UUID_01 | 第一组 UUID(Vision 用户) |
UUID_02 | 第二组 UUID(XHTTP 用户) |
YOUR_REALITY_PRIVATE_KEY | 刚才生成的 Private key |
YOUR_SHORT_ID | 刚才生成的 shortID |
reality.example.com | 你的 REALITY 子域名(小黄云关) |
cdn.example.com | 你的 CDN 子域名(小黄云开) |
/your-xhttp-path | 自定义路径 |
"minClientVer": "1.8.2" | 保持默认,不要改 |
sudo tee /usr/local/etc/xray/config.json >/dev/null <<'EOF'{ "log": { "loglevel": "info" // 调试完成后可改为 "warning" }, "inbounds": [ { "listen": "0.0.0.0", // 如果需要 IPv6,改为监听 "::" "port": 443, "protocol": "vless", "settings": { "clients": [ { "id": "UUID_01", // 对应客户端出站 1 "level": 0, "email": "vision-user", "flow": "xtls-rprx-vision" }, { "id": "UUID_02", // 对应客户端出站 2/3/4/5 "level": 0, "email": "xhttp-user" } ], "decryption": "none", "fallbacks": [ { "dest": "/run/xray/xhttp_in.sock", // 处理“直连”的 XHTTP 请求 (对应客户端出站 2/3/5 的直连部分) // 当 Reality 识别出 VLESS 协议但没有 flow 时,直接丢给内部 XHTTP Socket "xver": 0 } ] }, "streamSettings": { "network": "raw", "security": "reality", "realitySettings": { "show": false, "target": "/run/caddy/tls_gate.sock", // 处理“CDN 转发”或“普通 HTTPS”请求 (对应客户端出站 3/4/5 的 CDN 部分) // 任何 Reality 不识别的流量都丢给 Caddy 处理 "xver": 0, "serverNames": [ "reality.example.com", "cdn.example.com" ], "privateKey": "YOUR_REALITY_PRIVATE_KEY", "shortIds": ["YOUR_SHORT_ID"], "minClientVer": "1.8.2" }, "sockopt": { "tcpFastOpen": true, "tcpcongestion": "bbr", "tcpMptcp": true, "tcpNoDelay": true } }, "tag": "VISION+REALITY", "sniffing": { "enabled": true, "destOverride": ["http", "tls", "quic"], "metadataOnly": false, "routeOnly": true } }, { "listen": "/run/xray/xhttp_in.sock", "protocol": "vless", "settings": { "clients": [ { "id": "UUID_02", "level": 0, "email": "xhttp-user" } ], "decryption": "none" }, "streamSettings": { "network": "xhttp", "xhttpSettings": { "host": "", "path": "/your-xhttp-path", "mode": "auto", "extra": { "noSSEHeader": false, "scMaxEachPostBytes": 1000000, "scMaxBufferedPosts": 30, "xPaddingBytes": "100-1000", "xPaddingObfsMode": true, "xPaddingMethod": "tokenish", // 生成一个随机的 Base62 标记 "xPaddingPlacement": "queryInHeader", // 填充嵌入 Referer URL query(CF 兼容) "xPaddingKey": "t", // URL query 参数名 "xPaddingHeader": "Referer", "sessionIDPlacement": "path", "sessionIDKey": "SID", "sessionIDTable": "Base62", "sessionIDLength": "12-20" } }, "sockopt": { "tcpFastOpen": true, "acceptProxyProtocol": false, "tcpcongestion": "bbr", "tcpMptcp": true, "tcpNoDelay": true } }, "tag": "XHTTP_IN", "sniffing": { "enabled": true, "destOverride": ["http", "tls", "quic"], "metadataOnly": false, "routeOnly": true } } ], "outbounds": [ { "protocol": "freedom", "tag": "direct", "settings": {} }, { "protocol": "blackhole", "tag": "blocked", "settings": {} } ], "routing": { "domainStrategy": "AsIs", "rules": [ { "type": "field", "ip": ["geoip:private"], "outboundTag": "blocked" } ]}}EOF
geoip:private blocked在路由层阻断Xray v26.7.11 新增的
defaultBlockPrivateRule在 freedom 出站内部阻断两者功能重叠,保留作为纵深防御
3.4 安装 Caddy
使用 Caddy 官方针对 Debian 的软件源安装:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
# 导入 GPG 密钥curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
# 添加官方软件源curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
# 更新并安装sudo apt updatesudo apt install caddy -y3.5 编写 Caddyfile
TIP同理,请在本地编辑器中替换其中的占位符,替换后粘贴整段代码块至终端回车执行
sudo tee /etc/caddy/Caddyfile >/dev/null <<'EOF'# 1. REALITY 域名区块(专供 REALITY 握手与伪装网页)# 记得换成你自己的 REALITY 子域名!!!reality.example.com { # 监听 Xray REALITY 回落的 Unix Socket bind unix//run/caddy/tls_gate.sock
# 引用 acme.sh 申请的 Let's Encrypt 证书与私钥 tls /etc/caddy/certs/reality.crt /etc/caddy/certs/reality.key
log { output file /var/log/caddy/reality_access.log { roll_size 10mib roll_keep 7 roll_keep_for 168h } }
# 处理所有其他访问 # 外部扫描器或浏览器访问,直接给出伪装网页 handle { # 伪装网页路径:/var/www/html/index.html root * /var/www/html file_server }}
# 2. CDN 域名区块(处理从 Xray 回落的 CDN 代理流量)# 记得换成你自己的 CDN 子域名!!!cdn.example.com { bind unix//run/caddy/tls_gate.sock
# 申请的是多域名合并证书,引用相同的证书文件即可 tls /etc/caddy/certs/reality.crt /etc/caddy/certs/reality.key
log { output file /var/log/caddy/cdn_access.log { roll_size 10mib roll_keep 7 roll_keep_for 168h } }
# 捕获套 CDN 的出站(出站 3/4/5)传来的合法的 XHTTP 流量 # 记得换成你自己的 XHTTP 路径!!! # 记得换成你自己的 XHTTP 路径!!! # 记得换成你自己的 XHTTP 路径!!! handle /your-xhttp-path/* { reverse_proxy unix//run/xray/xhttp_in.sock { transport http { versions 2 } flush_interval -1 } }
# 可选:探针探活路径 handle /status { respond "ok" 200 }
handle /ping { respond "ok" 200 }
# 对于扫描器,直接重定向到伪装网页防扫描 # 记得换成你自己的 REALITY 子域名!!! handle { redir https://reality.example.com{uri} }}EOF请务必仔细检查你的
handle块配置,路径末尾的斜杠和星号/*不能省略XHTTP 流量请求的 URL 是动态长随机混淆参数的
如果前缀不通配,Caddy 就会将其视为未知的外部扫描探测,返回 302 伪装页
附:简单伪装导航页
如果你没有现成的网站,可以使用下面这段单文件 HTML 代码
但是后期建议让 GenAI 丰富一下,换成个人博客、OpenList 什么的
将以下代码块整体复制到终端回车执行,即可一键生成伪装站点:
sudo mkdir -p /var/www/htmlsudo tee /var/www/html/index.html >/dev/null <<'EOF'<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tech Hub</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
body { min-height: 100vh; display: flex; justify-content: center; align-items: center; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: linear-gradient(-45deg, #e0e7ff, #f3e8ff, #dbeafe, #ede9fe); background-size: 400% 400%; animation: gradientBG 18s ease infinite; }
@keyframes gradientBG { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }
.wrapper { display: flex; flex-direction: column; align-items: center; gap: 2rem; padding: 2rem; width: 100%; max-width: 720px; }
.title { font-size: clamp(2.4rem, 6vw, 3.6rem); font-weight: 600; color: #1e293b; letter-spacing: -0.02em; text-align: center; }
.sub { font-size: clamp(0.8rem, 1.5vw, 1rem); color: #64748b; text-transform: uppercase; letter-spacing: 0.2em; border-bottom: 1px solid #cbd5e1; padding-bottom: 1rem; width: 100%; text-align: center; }
.nav { display: flex; gap: 1.5rem; padding: 1.5rem 2.5rem; border-radius: 80px; background: rgba(255, 255, 255, 0.6); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.8); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.06); flex-wrap: wrap; justify-content: center; }
.nav-item { display: flex; justify-content: center; align-items: center; width: 3.4rem; height: 3.4rem; border-radius: 50%; background: rgba(255, 255, 255, 0.4); transition: all 0.25s ease; text-decoration: none; border: 1px solid rgba(255, 255, 255, 0.6); }
.nav-item img { width: 1.6rem; height: 1.6rem; transition: transform 0.2s ease; }
.nav-item:hover { transform: translateY(-4px); background: rgba(255, 255, 255, 0.9); border-color: #94a3b8; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08); }
.nav-item:hover img { transform: scale(1.1); }
@media (max-width: 600px) { .wrapper { gap: 1.5rem; padding: 1rem; } .nav { padding: 1rem 1.5rem; gap: 1rem; border-radius: 2rem; } .nav-item { width: 2.8rem; height: 2.8rem; } .nav-item img { width: 1.3rem; height: 1.3rem; } } </style></head><body> <div class="wrapper"> <h1 class="title">Dev Center</h1> <div class="sub">Let there be light</div> <div class="nav"> <a href="https://www.google.com" class="nav-item" title="Google"><img src="https://cdn.simpleicons.org/google/1e293b" alt="Google"></a> <a href="https://github.com" class="nav-item" title="GitHub"><img src="https://cdn.simpleicons.org/github/1e293b" alt="GitHub"></a> <a href="https://dash.cloudflare.com" class="nav-item" title="Cloudflare"><img src="https://cdn.simpleicons.org/cloudflare/1e293b" alt="Cloudflare"></a> <a href="https://hub.docker.com" class="nav-item" title="Docker Hub"><img src="https://cdn.simpleicons.org/docker/1e293b" alt="Docker"></a> <a href="https://stackoverflow.com" class="nav-item" title="Stack Overflow"><img src="https://cdn.simpleicons.org/stackoverflow/1e293b" alt="Stack Overflow"></a> <a href="https://www.npmjs.com" class="nav-item" title="npm"><img src="https://cdn.simpleicons.org/npm/1e293b" alt="npm"></a> <a href="https://gitlab.com" class="nav-item" title="GitLab"><img src="https://cdn.simpleicons.org/gitlab/1e293b" alt="GitLab"></a> </div> </div></body></html>EOF3.6 用户组与运行目录设置
启动 Xray 和 Caddy 前需统一运行用户为 caddy,否则会出现 socket 权限问题:
[Info] transport/internet/tcp: REALITY: failed to dial dest: dial unix /run/caddy/tls_gate.sock: connect: permission denied进一步,为避免两个服务重启时因 RuntimeDirectory 被 systemd 清理而导致 UDS 套接字文件丢失,我们将双方的套接字放入各自所属服务的运行时目录(Xray 使用 /run/xray/,Caddy 使用 /run/caddy/):
# 统一运行用户为 caddysudo mkdir -p /etc/systemd/system/xray.service.dsudo tee /etc/systemd/system/xray.service.d/override.conf <<EOF[Service]User=caddyEOF
# 为 Caddy 启用独立的运行目录以放套接字sudo mkdir -p /etc/systemd/system/caddy.service.dsudo tee /etc/systemd/system/caddy.service.d/override.conf <<EOF[Service]User=caddyRuntimeDirectory=caddyEOF
# 重新加载 Systemd 配置sudo systemctl daemon-reload3.7 申请公有受信任证书
点击查看:为什么不能用 Caddy 自带的自动申请证书功能
NOTECaddy 默认依赖 HTTP-01 或 TLS-ALPN-01 进行 ACME 自动化证书验证,此过程的硬性前置条件是 Web 服务器必须能够直接在操作系统层面接管并监听公网的 80 或 443 端口。
在当前架构中,公网 443 端口由 Xray 独占监听,Caddy 仅绑定于内网的 Unix Socket 充当回落目标。当 Let’s Encrypt 验证集群发起 TLS-ALPN-01 请求时,流量首先到达 Xray 的 REALITY 服务端。由于该请求不具备有效的 XTLS 身份特征,REALITY 服务端会将其视为未知流量,执行透明的双向 TCP 转发(直接回落至 Caddy 的 Unix Socket)。
尽管验证流量最终送达了 Caddy,但证书申请依然会失败。因为 Caddy 的 ACME 模块在处理 TLS-ALPN-01 挑战时,强依赖于标准 443 端口监听器来挂载专用的验证证书。面对来自 Unix Socket 的回落流量,Caddy 的验证上下文无法正确匹配并下发该证书。即便 Caddy 异常响应了临时的 ACME 验证证书,由于 REALITY 服务端需持续抓取目标后端返回的 ServerHello 以缓存真实证书,这种非标准的临时证书将引发 REALITY 内部证书缓存逻辑链异常,导致整个 TLS 握手在链路中被异常阻断。
所以转而使用 acme.sh 脚本动态下发 DNS TXT 记录(即基于 API 交互的 DNS-01 验证),以实现 TLS 证书合规签发。
另外,REALITY 节点需使用真实 IP 直接承载直连流量(CDN Proxy OFF),若部署未受公共根证书信任的 Cloudflare Origin CA 证书,浏览器直接访问伪装站时会触发 TLS 错误。
第一步:获取 Cloudflare API Token
- 登录你的 Cloudflare 网页后台;
- 展开左边栏 -> 选择 管理账户 -> 账户 API 令牌;
- 点击 创建令牌;
- 令牌名称自定义;
- 权限策略 -> 编辑策略:选择
指定域名,然后下拉框选你的主域名; - 在下方的权限组列表中,点击展开
DNS & Zones类别区域 (Zone)-区域 (Zone)- 勾选读取 (Read)区域 (Zone)-DNS- 勾选编辑 (Edit)
- 令牌过期时间建议直接选择 “无过期时间”;
- 客户端 IP 地址过滤,可以什么都不填,只要你不把 Token 泄露给别人,就是安全的;或者填上运行
acme.sh脚本的服务器的公网 IP 地址; - 审核令牌 -> 创建令牌;
- 接着会给出
账户ID和CF_Token,复制并保存
第二步:在 VPS 切换至 root 并安装 acme.sh
为了后续能够全自动在后台无感续签,这一步全程在 root 用户下执行,以免权限不足导致续签后重载 Caddy 失败。
# SSH 登录 VPS 并切换到 rootsudo -i
# 设置你的真实邮箱,并安装 acme.shEMAIL="your_email@example.com"curl https://get.acme.sh | sh -s email="$EMAIL"
# 切换默认颁发机构为 Let's EncryptACME=/root/.acme.sh/acme.sh$ACME --set-default-ca --server letsencrypt第三步:隐式导入 Token 并申请证书
为防止 Token 泄露到 .bash_history 中,我们使用静默输入:
# 执行后,直接粘贴你的 Token 并回车(屏幕上不会显示)read -rsp 'Cloudflare API Token: ' CF_Tokenechoexport CF_Tokenexport CF_Account_ID="你的Account_ID"
# 申请证书 (必须同时包含 Reality 直连域名和 CDN 回源域名,否则 Cloudflare 在“完全(严格)”模式下回源会报 526 证书错误)$ACME --issue --dns dns_cf -d "reality.example.com" -d "cdn.example.com"第四步:提取证书并配置自动授权重载
我们需要把证书提取到 Caddy 的配置目录,每次续签后,私钥文件的属主会被重置为 root,这将导致低权限运行的 Caddy 无法读取私钥而崩溃。因此必须在 --reloadcmd 中加入 chown 权限交接命令:
# 创建目录mkdir -p /etc/caddy/certs
# 提取证书并设定重载命令# 安装时只需要指定主域名(第一个 -d 域名),acme.sh 会自动关联$ACME --install-cert -d "reality.example.com" \--key-file /etc/caddy/certs/reality.key \--fullchain-file /etc/caddy/certs/reality.crt \--reloadcmd "chown caddy:caddy /etc/caddy/certs/reality.* && systemctl reload caddy"NOTE证书安装后,私钥文件默认权限为
-rw-------(600),仅属主(root)可读写。
若 Caddy 以caddy用户运行,需确保其能读取。上述reloadcmd中的chown已解决属主问题。
若需进一步限制权限,可额外执行chmod 640 /etc/caddy/certs/reality.key。
TIP此时报错
Reload error for: reality.example.com / caddy.service is not active无伤大雅,因为我们在下一步才正式启动应用。
完成后,输入 exit 退出 root 环境,返回普通用户。
3.8 启动服务
启动前检查
为避免 permission denied 错误,请再次确认以下路径的属主正确:
# Caddy 日志目录sudo mkdir -p /var/log/caddysudo chown -R caddy:caddy /var/log/caddysudo chmod 755 /var/log/caddy
# 证书文件ls -la /etc/caddy/certs/# 应显示 -rw-r--r-- 1 caddy caddy reality.crt# 应显示 -rw------- 1 caddy caddy reality.key
# 若属主不是 caddy,请执行修正:sudo chown -R caddy:caddy /var/log/caddysudo chown caddy:caddy /etc/caddy/certs/reality.*sudo chmod 640 /etc/caddy/certs/reality.key正式启动:
sudo systemctl enable --now xray caddy验证状态:
systemctl show xray --property=User,Groupsystemctl show caddy --property=User,Groupls -l /run/xray/ /run/caddy/理想输出:
User=caddyGroup=
---
User=caddyGroup=caddy
# /run/xray/srwxr-xr-x 1 caddy caddy 0 ... xhttp_in.sock-rw-r--r-- 1 caddy caddy 0 ... xhttp_in.sock.lock
# /run/caddy/s-w------- 1 caddy caddy 0 ... tls_gate.sock3.9 后续更新
更新 Xray-core
官方安装脚本支持直接升级,新版本发布后,重新运行安装命令即可:
# 检查是否有新版本sudo bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ check
# 升级到最新 Pre-release(推荐)sudo bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install --beta脚本会自动检测版本号差异、下载新二进制、替换并重启服务。你的 config.json、override.conf、日志等配置文件全部保留,不会被覆盖。
升级后 systemd 主 service 文件会被重写为默认的
User=nobody,但override.conf(User=caddy)优先级更高,运行时用户不受影响。 若要消除Special user nobody configured警告,可手动修复:Terminal window sudo sed -i 's/User=nobody/User=caddy/' /etc/systemd/system/xray.servicesudo systemctl daemon-reload
更新 Caddy
通过 apt 更新:
sudo apt updatesudo apt upgrade caddy -y4. 客户端配置
4.1 mihomo Client Config
由于 mihomo GUI 繁多,此处仅给出裸核 config:
proxies: # 1. XTLS(Vision) + REALITY 直连 - name: "出站1-XTLS+REALITY" type: vless server: "YOUR_VPS_IP" port: 443 uuid: "YOUR_UUID_01" encryption: "none" flow: xtls-rprx-vision network: tcp # 以下两项取决于你的实际 UDP 使用场景,不需要请注释或删除 # udp: true # 需要走代理的境外游戏/QUIC/WebRTC 则开启 # packet-encoding: xudp # UDP 编码方式,开启后支持 FullCone NAT(默认即此值) tls: true alpn: [h2] servername: "reality.example.com" # Reality 伪装域名 client-fingerprint: chrome reality-opts: public-key: "YOUR_PUB_KEY" short-id: "YOUR_SHORT_ID"
# 2. XHTTP + REALITY 直连 - name: "出站2-XHTTP+REALITY" type: vless server: "YOUR_VPS_IP" port: 443 uuid: "YOUR_UUID_02" encryption: "none" flow: "" network: xhttp # udp: true # packet-encoding: xudp tls: true alpn: [h2] servername: "reality.example.com" # Reality 伪装域名 client-fingerprint: chrome reality-opts: public-key: "YOUR_PUB_KEY" short-id: "YOUR_SHORT_ID" xhttp-opts: path: /your-xhttp-path # 必须与服务端配置的 path 一致 mode: auto # Reality 模式下 auto 会自动选择 stream-one # host: "reality.example.com" # 直连时可省略,默认继承 servername session-table: "Alphabet" # 自定义 session ID 字符集,降低 CDN 特征识别 session-length: "12-20" # session ID 长度范围(起始值不可为 0,总 ID 空间须 > 21 亿) session-placement: path # Session ID 放在 URL 路径中(path 模式下 session-key 无效) x-padding-obfs-mode: true # 启用填充混淆 x-padding-method: tokenish # 随机 Base62 标记,HPACK 编码后精确匹配目标长度 x-padding-placement: queryInHeader # 填充嵌入 Referer URL query 中(CF 兼容) x-padding-key: "t" # URL query 参数名,伪装成 analytics token x-padding-header: "Referer" # 填充存放的 HTTP Header 名,默认 Referer(CF 兼容) sc-stream-up-server-secs: "30-60" # 单连接流控保活心跳间隔,减少 CDN 超时断开 reuse-settings: # 链接复用设置(即XMUX) max-concurrency: "16-32" # 单连接最大并发请求数(0=不限制) # max-connections: "3" # 最大连接数(0=不限制)(与 max-concurrency 冲突,二选一) c-max-reuse-times: "0" # 单连接最大复用次数(0=不限制) # h-max-request-times: "600-900" # 单连接累计 HTTP 请求数(不严谨,慎用) h-max-reusable-secs: "1800-3000" # 单连接最长复用时间(秒) h-keep-alive-period: 0 # H2/H3 保活间隔 (0=默认智能值, -1=关闭, 支持填正数范围但不推荐)
# 3. 上行 XHTTP + TLS(ECH) + CDN | 下行 XHTTP + REALITY(上下行不同 SNI) - name: "出站3-CDN上行+XHTTP下行" type: vless server: "cdn.example.com" # CDN 域名或优选 IP (上行) port: 443 uuid: "YOUR_UUID_02" encryption: "none" flow: "" network: xhttp ech-opts: {enable: true} # 隐藏 SNI # udp: true # packet-encoding: xudp tls: true alpn: [h3] servername: "cdn.example.com" # 写你套 CDN 对应的子域名,CDN 通过它回源服务器 client-fingerprint: chrome skip-cert-verify: false # 强制校验服务端证书,防止中间人攻击 xhttp-opts: # 上行设置 host: "cdn.example.com" # CDN 转发所需的 HTTP Host,与 servername 保持相同 path: /your-xhttp-path mode: auto # CDN 模式下 auto 会自动选择 stream-up (H2) session-table: "Alphabet" # 自定义 session ID 字符集,降低 CDN 特征识别 session-length: "12-20" # session ID 长度范围 session-placement: path # Session ID 放在 URL 路径中(path 模式下 session-key 无效) x-padding-obfs-mode: true # 启用填充混淆 x-padding-method: tokenish # 随机 Base62 标记,HPACK 编码后精确匹配目标长度 x-padding-placement: queryInHeader # 填充嵌入 Referer URL query 中(CF 兼容) x-padding-key: "t" # URL query 参数名,伪装成 analytics token x-padding-header: "Referer" # 填充存放的 HTTP Header 名,默认 Referer(CF 兼容) sc-stream-up-server-secs: "30-60" # 单连接流控保活心跳间隔,减少 CDN 超时断开 reuse-settings: # 上行链接复用设置(即XMUX) max-concurrency: "16-32" # 单连接最大并发请求数(0=不限制) # max-connections: "3" # 最大连接数(0=不限制)(与 max-concurrency 冲突,二选一) c-max-reuse-times: "0" # 单连接最大复用次数(0=不限制) # h-max-request-times: "600-900" # 单连接累计 HTTP 请求数(不严谨,慎用) h-max-reusable-secs: "1800-3000" # 单连接最长复用时间(秒) h-keep-alive-period: 0 # H2/H3 保活间隔 (0=默认智能值, -1=关闭, 支持填正数范围但不推荐) download-settings: # 下行设置(Reality 不支持 h3,须显式覆盖为 h2) alpn: [h2] # 显式指定 h2,覆盖主代理继承来的 h3 server: "<YOUR_VPS_IP>" # 下行地址 (VPS 直连) port: 443 servername: "reality.example.com" # Reality 伪装域名 reality-opts: public-key: "YOUR_PUB_KEY" short-id: "YOUR_SHORT_ID" # host 继承自外层或省略;mode 强制继承外层 reuse-settings: # 下行链接复用设置(即XMUX) max-concurrency: "16-32" # 单连接最大并发请求数(0=不限制) # max-connections: "3" # 最大连接数(0=不限制)(与 max-concurrency 冲突,二选一) c-max-reuse-times: "0" # 单连接最大复用次数(0=不限制) # h-max-request-times: "600-900" # 单连接累计 HTTP 请求数(不严谨,慎用) h-max-reusable-secs: "1800-3000" # 单连接最长复用时间(秒) h-keep-alive-period: 0 # H2/H3 保活间隔 (0=默认智能值, -1=关闭, 支持填正数范围但不推荐)
# 4. XHTTP + TLS(ECH) 过 CDN(上下行不分离) - name: "出站4-CDN上下行" type: vless server: "cdn.example.com" # CDN 域名或优选 IP port: 443 uuid: "YOUR_UUID_02" encryption: "none" flow: "" network: xhttp ech-opts: {enable: true} # 隐藏 SNI # udp: true # packet-encoding: xudp tls: true alpn: [h3] servername: "cdn.example.com" # 写你套 CDN 对应的子域名,CDN 通过它回源服务器 client-fingerprint: chrome skip-cert-verify: false # 强制校验服务端证书,防止中间人攻击 xhttp-opts: host: "cdn.example.com" # CDN 转发所需的 HTTP Host,与 servername 保持相同 path: /your-xhttp-path mode: auto session-table: "Alphabet" # 自定义 session ID 字符集,降低 CDN 特征识别 session-length: "12-20" # session ID 长度范围 session-placement: path # Session ID 放在 URL 路径中(path 模式下 session-key 无效) x-padding-obfs-mode: true # 启用填充混淆 x-padding-method: tokenish # 随机 Base62 标记,HPACK 编码后精确匹配目标长度 x-padding-placement: queryInHeader # 填充嵌入 Referer URL query 中(CF 兼容) x-padding-key: "t" # URL query 参数名,伪装成 analytics token x-padding-header: "Referer" # 填充存放的 HTTP Header 名,默认 Referer(CF 兼容) sc-stream-up-server-secs: "30-60" # 单连接流控保活心跳间隔,减少 CDN 超时断开 reuse-settings: # 链接复用设置(即XMUX) max-concurrency: "16-32" # 单连接最大并发请求数(0=不限制) # max-connections: "3" # 最大连接数(0=不限制)(与 max-concurrency 冲突,二选一) c-max-reuse-times: "0" # 单连接最大复用次数(0=不限制) # h-max-request-times: "600-900" # 单连接累计 HTTP 请求数(不严谨,慎用) h-max-reusable-secs: "1800-3000" # 单连接最长复用时间(秒) h-keep-alive-period: 0 # H2/H3 保活间隔 (0=默认智能值, -1=关闭, 支持填正数范围但不推荐)
# 5. 上行 XHTTP + REALITY | 下行 XHTTP + TLS(ECH) + CDN(上下行不同 SNI) - name: "出站5-上XHTTP+REALITY下XHTTP+TLS+CDN" type: vless server: "YOUR_VPS_IP" port: 443 uuid: "YOUR_UUID_02" encryption: "none" flow: "" network: xhttp # udp: true # packet-encoding: xudp tls: true alpn: [h2] servername: "reality.example.com" # Reality 伪装域名 client-fingerprint: chrome skip-cert-verify: false # 强制校验服务端证书,防止中间人攻击 reality-opts: public-key: "YOUR_PUB_KEY" short-id: "YOUR_SHORT_ID" xhttp-opts: host: "cdn.example.com" # CDN 转发所需的 HTTP Host,与 servername 保持相同 path: /your-xhttp-path mode: auto session-table: "Alphabet" # 自定义 session ID 字符集,降低 CDN 特征识别 session-length: "12-20" # session ID 长度范围 session-placement: path # Session ID 放在 URL 路径中(path 模式下 session-key 无效) x-padding-obfs-mode: true # 启用填充混淆 x-padding-method: tokenish # 随机 Base62 标记,HPACK 编码后精确匹配目标长度 x-padding-placement: queryInHeader # 填充嵌入 Referer URL query 中(CF 兼容) x-padding-key: "t" # URL query 参数名,伪装成 analytics token x-padding-header: "Referer" # 填充存放的 HTTP Header 名,默认 Referer(CF 兼容) sc-stream-up-server-secs: "30-60" # 单连接流控保活心跳间隔,减少 CDN 超时断开 reuse-settings: # 上行链接复用设置(即XMUX) max-concurrency: "16-32" # 单连接最大并发请求数(0=不限制) # max-connections: "3" # 最大连接数(0=不限制)(与 max-concurrency 冲突,二选一) c-max-reuse-times: "0" # 单连接最大复用次数(0=不限制) # h-max-request-times: "600-900" # 单连接累计 HTTP 请求数(不严谨,慎用) h-max-reusable-secs: "1800-3000" # 单连接最长复用时间(秒) h-keep-alive-period: 0 # H2/H3 保活间隔 (0=默认智能值, -1=关闭, 支持填正数范围但不推荐) download-settings: # 下行设置(CDN 路径,改用 h3) path: /your-xhttp-path host: "" # host 继承自外层或省略;mode 强制继承外层 server: "cdn.example.com" # CDN / 优选 IP (下行连接地址) port: 443 tls: true alpn: [h3] servername: "cdn.example.com" # 写你套 CDN 对应的子域名,CDN 通过它回源服务器 client-fingerprint: chrome skip-cert-verify: false # 强制校验服务端证书,防止中间人攻击 ech-opts: {enable: true} # 隐藏 SNI reality-opts: { public-key: "" } # 强制清空 Reality 公钥,否则下行连接 CDN 将会携带 Reality 握手 reuse-settings: # 下行链接复用设置(即XMUX) max-concurrency: "16-32" # 单连接最大并发请求数(0=不限制) # max-connections: "3" # 最大连接数(0=不限制)(与 max-concurrency 冲突,二选一) c-max-reuse-times: "0" # 单连接最大复用次数(0=不限制) # h-max-request-times: "600-900" # 单连接累计 HTTP 请求数(不严谨,慎用) h-max-reusable-secs: "1800-3000" # 单连接最长复用时间(秒) h-keep-alive-period: 0 # H2/H3 保活间隔 (0=默认智能值, -1=关闭, 支持填正数范围但不推荐)锚点写法
# 定义锚点x-anchors: # 0. 用户变量 (请在此处统一修改为自己的配置,下方会自动引用) variables: vps_ip: &vps_ip "YOUR_VPS_IP" uuid_01: &uuid_01 "YOUR_UUID_01" uuid_02: &uuid_02 "YOUR_UUID_02" reality_domain: &reality_domain "reality.example.com" cdn_domain: &cdn_domain "cdn.example.com" xhttp_path: &xhttp_path "/your-xhttp-path"
# 1. Reality 密钥配置 reality-opts: &reality-opts public-key: "YOUR_PUB_KEY" short-id: "YOUR_SHORT_ID"
# 2. 链接复用设置参数 reuse-settings: &reuse-settings max-concurrency: "16-32" # 单连接最大并发请求数(0=不限制) # max-connections: "3" # 最大连接数(0=不限制)(与 max-concurrency 冲突,二选一) c-max-reuse-times: "0" # 单连接最大复用次数(0=不限制) # h-max-request-times: "600-900" # 单连接累计 HTTP 请求数(不严谨,慎用) h-max-reusable-secs: "1800-3000" # 单连接最长复用时间(秒) h-keep-alive-period: 0 # H2/H3 保活间隔 (0=默认智能值, -1=关闭, 支持填正数范围但不推荐)
# 3. XHTTP 混淆配置 xhttp-obfs: &xhttp-obfs path: *xhttp_path mode: auto session-table: "Alphabet" # 自定义 session ID 字符集,降低 CDN 特征识别 session-length: "12-20" # session ID 长度范围 session-placement: path # Session ID 放在 URL 路径中 x-padding-obfs-mode: true # 启用填充混淆 x-padding-method: tokenish # 随机 Base62 标记,HPACK 编码后精确匹配目标长度 x-padding-placement: queryInHeader # 填充嵌入 Referer URL query 中 x-padding-key: "t" # URL query 参数名,伪装成 analytics token x-padding-header: "Referer" # 填充存放的 HTTP Header 名,默认 Referer sc-stream-up-server-secs: "30-60" # 单连接流控保活心跳间隔,减少 CDN 超时断开 reuse-settings: *reuse-settings
# 4. UDP 配置 udp-opts: &udp-opts # 以下两项取决于你的实际 UDP 使用场景 udp: false # 境外游戏/QUIC/WebRTC 有需要走代理的则改为 true # packet-encoding: xudp # UDP 编码方式
# 最终节点配置proxies: # 1. XTLS(Vision) + REALITY 直连 - name: "出站1-XTLS+REALITY" type: vless server: *vps_ip port: 443 uuid: *uuid_01 encryption: "none" flow: xtls-rprx-vision network: tcp <<: *udp-opts tls: true alpn: [h2] servername: *reality_domain client-fingerprint: chrome reality-opts: *reality-opts
# 2. XHTTP + REALITY 直连 - name: "出站2-XHTTP+REALITY" type: vless server: *vps_ip port: 443 uuid: *uuid_02 encryption: "none" flow: "" network: xhttp <<: *udp-opts tls: true alpn: [h2] servername: *reality_domain client-fingerprint: chrome reality-opts: *reality-opts xhttp-opts: *xhttp-obfs
# 3. 上行 XHTTP + TLS(ECH) + CDN | 下行 XHTTP + REALITY - name: "出站3-CDN上行+XHTTP下行" type: vless server: *cdn_domain port: 443 uuid: *uuid_02 encryption: "none" flow: "" network: xhttp <<: *udp-opts tls: true alpn: [h3] servername: *cdn_domain client-fingerprint: chrome skip-cert-verify: false ech-opts: {enable: true} xhttp-opts: <<: *xhttp-obfs host: *cdn_domain download-settings: server: *vps_ip port: 443 tls: true alpn: [h2] servername: *reality_domain client-fingerprint: chrome reality-opts: *reality-opts reuse-settings: *reuse-settings
# 4. XHTTP + TLS(ECH) 过 CDN(上下行不分离) - name: "出站4-CDN上下行" type: vless server: *cdn_domain port: 443 uuid: *uuid_02 encryption: "none" flow: "" network: xhttp <<: *udp-opts tls: true alpn: [h3] servername: *cdn_domain client-fingerprint: chrome skip-cert-verify: false ech-opts: {enable: true} xhttp-opts: <<: *xhttp-obfs host: *cdn_domain
# 5. 上行 XHTTP + REALITY | 下行 XHTTP + TLS(ECH) + CDN - name: "出站5-上XHTTP+REALITY下XHTTP+TLS+CDN" type: vless server: *vps_ip port: 443 uuid: *uuid_02 encryption: "none" flow: "" network: xhttp <<: *udp-opts tls: true alpn: [h2] servername: *reality_domain client-fingerprint: chrome skip-cert-verify: false reality-opts: *reality-opts xhttp-opts: <<: *xhttp-obfs host: *cdn_domain download-settings: server: *cdn_domain port: 443 tls: true alpn: [h3] servername: *cdn_domain client-fingerprint: chrome skip-cert-verify: false ech-opts: {enable: true} path: *xhttp_path host: "" reality-opts: { public-key: "" } reuse-settings: *reuse-settings4.2 ALPN、ECH 与 XMUX 说明
ALPN
- mihomo v1.19.23:仅支持
h2 - mihomo v1.19.24+:支持
http/1.1和h3,但不支持多协议动态回退,写法如下:
proxies: - name: xxx alpn: [h2] # 使用 HTTP/2(默认) # alpn: [http/1.1] # 强制使用 HTTP/1.1 # alpn: [h3] # 强制使用 HTTP/3。注意:不支持 REALITY,必须 tls: trueECH
proxies: - name: xxx ech-opts: {enable: true}Cloudflare 免费版现已默认启用 ECH(Encrypted ClientHello)
针对通过 CDN 回源的出站节点,加上此参数后,mihomo 会自动发起 HTTPS DNS 记录查询,拉取 Cloudflare 下发的 ECH 公钥,并在 TLS 握手时加密 SNI,可以有效防止 GFW 通过嗅探 SNI 来封锁连接,一定程度上提升连接的隐蔽性
NOTE
- 只有套了 CDN 的节点才能用
- mihomo 需要写支持 DoH 解析的 DNS
- 域名需要开启 TLS 1.3
更多详情请查看下面推荐的文章
XMUX(链接复用)
IMPORTANTXray-core 近期的版本演进中(Issue #6376),对 XMUX 的默认策略经历了多次调整(从最初的
16-32,到1,再到3)。
- 本模板中显式写了
max-concurrency: "16-32"。效果是强制锁定在较稳定的多路复用状态,避免因继承内核默认值而导致并发 TCP 连接数突增爆表(仅为个人理解)- 如果为了对抗严格的审查环境(像 issue 提到的俄罗斯抗 TSPU 封锁)的话,可改为
max-connections: 3
【完】
友情推荐
- 使用 Nginx 作为反代的教程:
- Debian 13 VPS 安全加固与 Xray VLESS + REALITY 手动部署
- 本文从中学习到了
read -rsp静默输入这一用法
- 本文从中学习到了
- Debian 13 VPS 安全加固与 Xray VLESS + REALITY 手动部署
- ECH 相关教程: