IP 没被墙不代表永远不会被墙。CDN 套上去之前做好准备,等到真正出事的时候就不用慌。这篇记录我在一台独立节点 VPS 上用 xbnode 部署 VLESS+WS+TLS+Cloudflare CDN 的完整过程。
整体架构
客户端
↓ HTTPS/WSS(443)
Cloudflare CDN(Proxied,隐藏真实 IP)
↓ HTTPS(Full Strict TLS,CF 与源站之间加密)
节点 VPS:xbnode + sing-box
↓ WebSocket API 对接
Xboard 面板流量链路:客户端只知道 CF 的 IP,真实节点 IP 被隐藏在 CDN 后面。即便节点 IP 将来被针对,换一台机器重新指向同一域名就能恢复,面板侧几乎不需要动。
前置条件
- 节点 VPS:Debian/Ubuntu,有公网 IP
- Xboard 面板可正常添加节点
- 域名已在 Cloudflare 托管
- Docker + Docker Compose 已安装
安装 Docker(如未安装):
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker第一步:Cloudflare 准备
1.1 添加 DNS 记录
在 CF 控制台 → DNS → Records,添加一条 A 记录:
| 类型 | 名称 | 内容 | 代理状态 |
|---|---|---|---|
| A | 自选 | 节点 VPS 的真实 IP | 已代理(橙色云朵) |
橙色云朵是关键。流量经过 CF CDN,真实 IP 才会被隐藏在后面。灰色云朵(DNS Only)只做解析,没有任何防护效果。
1.2 SSL/TLS 模式设为 Full (Strict)
CF 控制台 → SSL/TLS → 概述,选择完全。
原因:CF 和源站之间的流量也走 HTTPS,且 CF 会验证源站证书有效性。如果选"灵活",CF 到源站这段是明文,sing-box 那侧因为期望 TLS 握手会直接拒绝,表现为 502/504。
1.3 确认 WebSocket 已开启
CF 控制台 → 网络 → WebSocket,确认为开启状态。VLESS+WS 的流量本质是 WebSocket 连接,CF 默认开启,可以确认一下。
第二步:Xboard 面板添加节点
在 Xboard 面板后台 → 节点管理 → 新增节点,配置如下:
| 字段 | 值 |
|---|---|
| 节点地址 | node.yourdomain.com(CF 代理的域名) |
| 协议 | VLESS |
| 传输方式 | WebSocket (WS) |
| 证书 | 自签或不填 |
| TLS | 开启 |
| 端口 | 443 |

保存后,记下该节点的节点 ID 和**通信密钥(在系统配置中的节点配置)。
第三步:节点 VPS 部署 xbnode
3.1 克隆 compose 分支
git clone -b compose --depth 1 https://github.com/cedar2025/xboard-node.git /opt/xbnode/app
cd /opt/xbnode/app3.2 编辑配置文件
nano config/config.yml修改以下内容:
panel:
url: "https://panel.yourdomain.com" # Xboard 面板地址
token: "your-server-token" # 面板通信 Token
node_id: 1 # 面板中的节点 ID3.4 启动服务
docker compose up -d查看日志确认启动正常:
docker compose logs -f正常启动后,日志里应能看到 sing-box 配置加载成功、与 Xboard 面板 WebSocket 同步建立的信息。
第五步:验证
用订阅链接导入节点到客户端,测试连通性。
在 CF 控制台 → 分析,确认有流量经过——这说明流量真正走了 CDN,而非直连节点 IP。
在客户端测速或查看出口 IP,显示的应是 CF 的节点 IP,而非 VPS 真实 IP。
后续维护
更新 xbnode 镜像:
cd /opt/xbnode/app
docker compose pull
docker compose up -d查看实时日志:
docker compose logs -f --tail=100容易踩的坑
CF SSL 模式选"灵活":CF 到源站这段变成明文,sing-box 期望 TLS 握手,直接拒绝,客户端看到 502/504。必须选"完全(严格)"。
橙色云朵没开:DNS Only 模式下 VPS 真实 IP 完全暴露,CDN 保护形同虚设。
443 端口被占用:network_mode: host 模式下,如果宿主机上已有其他服务占用 443(比如 Nginx),sing-box 会 bind 失败。需要先腾出 443,或者改用端口映射并在 CF → 节点 DNS 那侧选择 CF 支持的非标准端口(如 8443、2053 等)。


