Cloudflare CDN 中转节点 搭建详细文档
Cloudflare CDN 中转节点 搭建详细文档
(VLESS + WebSocket + TLS over Cloudflare,绕过 IP/协议封锁)
适用:当你的 VPS 直连节点(Reality、Hysteria2 等)被墙/运营商封了(连上没网), 用 Cloudflare 当中转保命。本文档从零开始,纯小白照抄命令即可。 实测环境:Ubuntu 22.04 + sing-box。其他 Debian/Ubuntu 通用。
0. 这玩意儿解决什么问题(先看懂)
正常直连节点,客户端是直接连你 VPS 的 IP。一旦这个 IP 被墙盯上(常见于敏感时期、 或 IP 用久了被标记),就会出现「连上了图标,但打不开任何网页」——握手被干扰/丢包。
本方案让客户端不直接连你的 VPS,而是:
你的手机/电脑客户端
│ ① 连的是 Cloudflare 的 IP(伪装成访问普通 https 网站)
▼
Cloudflare 全球 CDN 节点 ← 墙封不动它(几亿网站都用 CF,封了就大面积误伤)
│ ② CF 回源
▼
你的 VPS :443 ──► sing-box(VLESS+WS+TLS) ──► 翻墙出口上网
优点:CF 的 IP 封不掉,流量看着像访问普通 HTTPS 网站,DPI 识别不出来。 缺点:
- 经 CF 中转一圈,比直连慢(延迟高),别拿它猛看 4K / 大流量下载。
- 只能走 TCP,CF 不代理 UDP(所以这条用 VLESS+WS,不能用 Hysteria2)。
- CF 免费版拿来代理翻墙流量是踩 ToS 的,轻度用没事,往死里用可能被限。
定位:直连能用时用直连(快);被封了切到这条 CF 中转(保命)。
1. 开搭前你要准备的东西
- 一台 VPS(Vultr / 搬瓦工 / 任意),有公网 IP,能 root SSH 登录。
- 一个域名,并且已经托管到 Cloudflare(域名的 NS 指向 Cloudflare)。
- 没托管的:登录 cloudflare.com → 右上 Add a site → 输入你的域名 → 按它提示把 域名注册商那边的 NS(域名服务器)改成 CF 给的两个 → 等十几分钟到几小时生效。
- 托管成功的标志:CF 后台能看到你的域名,状态 Active。
- 会用 SSH 连服务器、会复制粘贴命令。
下文所有命令里出现的
node.example.com都换成你自己的子域名(比如jp1.abc.com)。 子域名你随便起一个,不用提前去注册,下面第 2 步在 CF 里加一条解析就有了。
2. 第一步:Cloudflare 加解析 + 设 SSL 模式
2.1 加一条 DNS 解析(开橙云代理)
CF 后台 → 选你的域名 → 左边 DNS → Add record:
- Type(类型):
A - Name(名字):
node(这样完整域名就是node.你的域名.com) - IPv4 address:填你 VPS 的公网 IP
- Proxy status(代理状态):必须是橙色云朵 Proxied(已代理) ← 关键!灰色不行
- Save
2.2 设 SSL/TLS 模式
CF 后台 → 选你的域名 → 左边 SSL/TLS → Overview → 把加密模式设成 Full(完全) 或 Full (strict)(完全·严格) 都行。 (本文档第 3 步会给域名申请正规证书,所以 strict 也能过,更安全。)
验证解析生效:在你电脑上
ping node.你的域名.com,返回的 IP 是 104.x / 172.6x 这类 Cloudflare 的 IP(不是你 VPS 的 IP),就说明橙云代理成功了。
3. 第二步:VPS 上装 sing-box 和 certbot
SSH 登录你的 VPS(root),依次执行:
# 更新 + 装基础工具
apt update && apt install -y curl certbot ufw qrencode
# 装 sing-box(官方脚本,自带 systemd 服务)
bash -c "$(curl -fsSL https://sing-box.app/deb-install.sh)"
# 确认装好了
sing-box version
4. 第三步:给子域名申请 TLS 证书(Let’s Encrypt)
CF 严格回源要校验源站证书,所以得给 node.你的域名.com 申一张正规证书。
因为域名开了橙云(CF 代理),直接申会被 CF 挡,最省事的办法是申证书时临时关代理:
- 临时关橙云:CF 后台 → DNS → 找到刚才那条
node记录 → 点橙色云朵让它变灰色 (DNS only)→ 等 1~2 分钟。 - 申证书(VPS 上执行,把域名换成你的):
看到certbot certonly --standalone -d node.example.com \ --non-interactive --agree-tos --register-unsafely-without-emailSuccessfully received certificate就成了。证书在:- 证书链:
/etc/letsencrypt/live/node.example.com/fullchain.pem - 私钥:
/etc/letsencrypt/live/node.example.com/privkey.pem
- 证书链:
- 把橙云开回来:CF 后台 → DNS → 那条
node记录的云朵点回橙色 Proxied。
注:certbot 会自动设置每 60 天续期,不用你管。续期时若再遇到 CF 代理拦截, 可在续期前临时关橙云,或改用 DNS 验证(进阶,见文末)。
5. 第四步:写 sing-box 配置
先生成两个随机值(每台新服务器都要重新生成,别和别人重复):
# 生成一个 UUID(客户端身份)
sing-box generate uuid
# 生成一个随机 ws 路径(伪装路径,越随机越好)
echo "/$(head -c 6 /dev/urandom | xxd -p)"
把上面两个输出记下来(比如 UUID=xxxx-xxxx,路径=/a1b2c3)。
编辑配置文件 /etc/sing-box/config.json,写成下面这样
(把 4 处占位替换成你的:域名、UUID、ws 路径):
{
"log": { "level": "info" },
"inbounds": [
{
"type": "vless",
"tag": "vless-ws-cf",
"listen": "::",
"listen_port": 443,
"users": [
{ "uuid": "把这里换成你生成的UUID" }
],
"transport": {
"type": "ws",
"path": "把这里换成你生成的ws路径,比如 /a1b2c3"
},
"tls": {
"enabled": true,
"certificate_path": "/etc/letsencrypt/live/node.example.com/fullchain.pem",
"key_path": "/etc/letsencrypt/live/node.example.com/privkey.pem"
}
}
],
"outbounds": [
{ "type": "direct", "tag": "direct" }
]
}
说明:
listen_port: 443——CF 回源默认走 443,所以 sing-box 直接监听 443 最省事 (前提:这台 VPS 的 443 没被别的网站/nginx 占用。被占用了看文末「进阶」)。certificate_path里的域名改成你的。outbound只写 direct(流量从本机直接出去)。
校验 + 启动:
sing-box check -c /etc/sing-box/config.json # 必须显示 ok / 无报错
systemctl restart sing-box
systemctl enable sing-box
systemctl is-active sing-box # 显示 active 就行
ss -tlnp | grep :443 # 能看到 sing-box 在听 443
6. 第五步:防火墙——只放行 Cloudflare 的 IP(重要安全步骤)
不限制的话,任何人都能扫到你的 443、直连探测,容易暴露/被封。 只允许 Cloudflare 的回源 IP 访问 443:
ufw --force reset # 如果你这台没别的服务在用 ufw,可用;有的话跳过这句
# 先放行 SSH(否则会把自己关在外面!端口换成你实际的 SSH 端口,默认 22)
ufw allow 22/tcp
# 只允许 Cloudflare 的 IP 段访问 443
for ip in 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 \
141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 \
197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 \
104.24.0.0/14 172.64.0.0/13 131.0.72.0/22; do
ufw allow from $ip to any port 443 proto tcp
done
ufw --force enable
ufw status # 检查 22 和 443(来自CF) 都放行了
Cloudflare 的 IP 段官方列表:https://www.cloudflare.com/ips/ (以后若有变动以官网为准)。
7. 第六步:生成客户端链接 + 二维码
客户端用的是这条 VLESS 链接(替换 3 处:UUID、域名、ws 路径)。
注意 ws 路径里的 / 要写成 %2F(比如路径 /a1b2c3 → 链接里写 path=%2Fa1b2c3):
vless://你的UUID@node.example.com:443?encryption=none&security=tls&sni=node.example.com&type=ws&host=node.example.com&path=%2F你的路径&fp=chrome#CF中转节点
在 VPS 上把它生成二维码(手机扫码导入):
LINK='vless://你的UUID@node.example.com:443?encryption=none&security=tls&sni=node.example.com&type=ws&host=node.example.com&path=%2F你的路径&fp=chrome#CF中转节点'
qrencode -o /root/node-qr.png -s 9 -m 3 "$LINK"
# 然后把 /root/node-qr.png 下载到本地用手机扫,或用 sftp 取走
客户端(手机 sing-box / v2rayN / Shadowrocket 等):
- 从剪贴板导入那条
vless://链接,或扫二维码。 - 关键参数对照:地址=你的域名、端口=443、传输=ws、路径=你的、TLS=开、SNI=你的域名、flow=空。
8. 第七步:验证整条链路通不通(在 VPS 上自测)
# 测 WS 握手能不能穿过 CF 到 sing-box(返回 101 = 全链路通)
curl -s -m 15 -o /dev/null -w "HTTP: %{http_code}\n" --http1.1 \
-H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" \
"https://node.example.com:443/你的路径"
- 返回 101 → 成功!整条 CF→源站→sing-box 通了,客户端导入就能用。
- 返回 526 → CF 校验源站证书没过(证书没申好/域名不对,回第 4 步)。
- 返回 520 → 源站异常(sing-box 没起来 / 路径不对)。
- 返回 522/超时 → CF 回源连不上你 443(防火墙没放行 CF / sing-box 没监听 443)。
客户端导入后,关 WiFi 用流量、选这个 CF 节点、打开网页,能上网就成了。
9. 常见故障排查
| 现象 | 原因 | 解决 |
|---|---|---|
| 连上没网,curl 测返回 526 | CF 严格回源校验证书失败 | 确认第 4 步证书申成功、域名和 sing-box 配置里一致 |
| 返回 522 / 超时 | CF 回源到不了 443 | 检查 ufw 放行了 CF 段、sing-box 在听 443、VPS 防火墙/安全组也放行 443 |
| 返回 520 | 源站(sing-box)报错 | systemctl status sing-box、journalctl -u sing-box -n 50 看日志 |
| ping 域名返回的是 VPS IP 不是 CF IP | 橙云没开 | DNS 记录云朵点成橙色 Proxied |
| 一切正常但客户端还连不上 | 客户端参数错 | 核对 端口 443、传输 ws、路径前面带 /、TLS 开、SNI=域名 |
排查时在 VPS 上盯日志很有用:
journalctl -u sing-box -f # 实时看 sing-box(客户端连进来会有记录)
10. 进阶:如果这台 VPS 的 443 已经被网站(nginx)占用
有些服务器 443 已经跑着网站/面板(nginx/openresty),不能让 sing-box 独占 443。 办法:让 nginx 在 443 上接住,把那个 ws 路径反向代理给 sing-box(sing-box 改听本地端口)。
- sing-box 入站
listen改成127.0.0.1、listen_port改成比如8443(其余不变,TLS 仍开)。 - nginx 里给你的子域名加一个 server 块(443 ssl,证书用第 4 步申的那张),核心是:
server { listen 443 ssl; server_name node.example.com; ssl_certificate /etc/letsencrypt/live/node.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/node.example.com/privkey.pem; location /你的路径 { proxy_pass https://127.0.0.1:8443; proxy_ssl_verify off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 300; } # 根路径:伪装成普通网站,见第 11 节(别用 return 444) location / { root /var/www/node-landing; try_files $uri /index.html; } } nginx -t校验通过再nginx -s reload。客户端链接里的端口仍是 443(连的是 nginx)。
本次给你搭的就是这个进阶版(因为那台 443 上跑着交易面板)。 新服务器若 443 空着,用第 5 步的简单版(sing-box 直接听 443)即可,省去 nginx。
11. 根路径伪装:别让首页暴露你是个”空壳”
为什么要做这步:上面 nginx 版如果根路径写 location / { return 444; },
别人(或墙的主动探测)直接访问 https://node.example.com/ 时,源站直接断连,
Cloudflare 会回退到它自己的错误页(521/522 之类)。一个”域名解析正常、
但首页永远报错”的站点是很可疑的特征——正常网站首页都能打开。伪装的核心思想是
让这个域名从任何角度看都像个普普通通的网站,翻墙流量只藏在那条随机 ws 路径里。
所以给根路径放一个平平无奇的落地页,而不是断连:
mkdir -p /var/www/node-landing
cat > /var/www/node-landing/index.html <<'HTML'
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome</title>
<style>
body{font-family:-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:#f5f6f8;
color:#333;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0}
.card{text-align:center;padding:48px 40px;background:#fff;border-radius:12px;
box-shadow:0 2px 16px rgba(0,0,0,.06);max-width:420px}
h1{font-size:24px;margin:0 0 12px}p{color:#666;line-height:1.6;margin:6px 0}
.foot{margin-top:24px;font-size:13px;color:#999}
</style></head><body>
<div class="card"><h1>It works!</h1>
<p>This server is up and running.</p>
<p class="foot">If you are the site administrator, your content will appear here.</p>
</div></body></html>
HTML
然后把第 10 节 server 块里的 location / 指向它(上面第 10 节示例已经是改好的版本),
nginx -t && nginx -s reload。之后浏览器访问域名首页会看到这个正常页面,
而 CF 错误页消失。
验证(在 VPS 上,模拟经 CF 回源的请求):
curl -sI -H "Host: node.example.com" https://127.0.0.1/ -k | head -1 # 应为 200
进阶伪装(可选,越像真站越好):
- 把落地页换成一个真实用途的静态站(个人博客、作品集、“建设中”通知页均可), 比空壳 “It works” 更自然。
- 那条 ws 路径(第 5 步生成的)保持够随机、够长,别人猜不到;不要用
/ws、/vless这种一看就懂的路径。 - 如果同一台机器还开了别的域名(比如面板站),CF 那边每个域名都单独配,互不影响。
简单版(sing-box 直接听 443、无 nginx)没有这个问题:因为客户端直接是 TLS+ws 握手,普通浏览器访问会被 sing-box 拒绝(不是 CF 错误页)。但装了 nginx 的进阶版 一定要补这个落地页——这是最容易被忽略、也最容易露馅的一环。
12. 一句话备忘
- 直连快但易被封;CF 中转慢但封不掉。两条都留着,被封了切 CF。
- 核心四样:①域名橙云代理 ②sing-box VLESS+WS+TLS ③子域名正规证书 ④只放行 CF 的 IP。
- 装 nginx 的进阶版再加一样:⑤根路径放个正常落地页,别用 return 444(第 11 节)。
- 每台新机器:重新生成 UUID 和 ws 路径,重新申证书,别复用。
(文档结束)
Cloudflare CDN 中转节点 搭建详细文档
(VLESS + WebSocket + TLS over Cloudflare,绕过 IP/协议封锁)
适用:当你的 VPS 直连节点(Reality、Hysteria2 等)被墙/运营商封了(连上没网), 用 Cloudflare 当中转保命。本文档从零开始,纯小白照抄命令即可。 实测环境:Ubuntu 22.04 + sing-box。其他 Debian/Ubuntu 通用。
0. 这玩意儿解决什么问题(先看懂)
正常直连节点,客户端是直接连你 VPS 的 IP。一旦这个 IP 被墙盯上(常见于敏感时期、 或 IP 用久了被标记),就会出现「连上了图标,但打不开任何网页」——握手被干扰/丢包。
本方案让客户端不直接连你的 VPS,而是:
你的手机/电脑客户端
│ ① 连的是 Cloudflare 的 IP(伪装成访问普通 https 网站)
▼
Cloudflare 全球 CDN 节点 ← 墙封不动它(几亿网站都用 CF,封了就大面积误伤)
│ ② CF 回源
▼
你的 VPS :443 ──► sing-box(VLESS+WS+TLS) ──► 翻墙出口上网
优点:CF 的 IP 封不掉,流量看着像访问普通 HTTPS 网站,DPI 识别不出来。 缺点:
- 经 CF 中转一圈,比直连慢(延迟高),别拿它猛看 4K / 大流量下载。
- 只能走 TCP,CF 不代理 UDP(所以这条用 VLESS+WS,不能用 Hysteria2)。
- CF 免费版拿来代理翻墙流量是踩 ToS 的,轻度用没事,往死里用可能被限。
定位:直连能用时用直连(快);被封了切到这条 CF 中转(保命)。
1. 开搭前你要准备的东西
- 一台 VPS(Vultr / 搬瓦工 / 任意),有公网 IP,能 root SSH 登录。
- 一个域名,并且已经托管到 Cloudflare(域名的 NS 指向 Cloudflare)。
- 没托管的:登录 cloudflare.com → 右上 Add a site → 输入你的域名 → 按它提示把 域名注册商那边的 NS(域名服务器)改成 CF 给的两个 → 等十几分钟到几小时生效。
- 托管成功的标志:CF 后台能看到你的域名,状态 Active。
- 会用 SSH 连服务器、会复制粘贴命令。
下文所有命令里出现的
node.example.com都换成你自己的子域名(比如jp1.abc.com)。 子域名你随便起一个,不用提前去注册,下面第 2 步在 CF 里加一条解析就有了。
2. 第一步:Cloudflare 加解析 + 设 SSL 模式
2.1 加一条 DNS 解析(开橙云代理)
CF 后台 → 选你的域名 → 左边 DNS → Add record:
- Type(类型):
A - Name(名字):
node(这样完整域名就是node.你的域名.com) - IPv4 address:填你 VPS 的公网 IP
- Proxy status(代理状态):必须是橙色云朵 Proxied(已代理) ← 关键!灰色不行
- Save
2.2 设 SSL/TLS 模式
CF 后台 → 选你的域名 → 左边 SSL/TLS → Overview → 把加密模式设成 Full(完全) 或 Full (strict)(完全·严格) 都行。 (本文档第 3 步会给域名申请正规证书,所以 strict 也能过,更安全。)
验证解析生效:在你电脑上
ping node.你的域名.com,返回的 IP 是 104.x / 172.6x 这类 Cloudflare 的 IP(不是你 VPS 的 IP),就说明橙云代理成功了。
3. 第二步:VPS 上装 sing-box 和 certbot
SSH 登录你的 VPS(root),依次执行:
# 更新 + 装基础工具
apt update && apt install -y curl certbot ufw qrencode
# 装 sing-box(官方脚本,自带 systemd 服务)
bash -c "$(curl -fsSL https://sing-box.app/deb-install.sh)"
# 确认装好了
sing-box version
4. 第三步:给子域名申请 TLS 证书(Let’s Encrypt)
CF 严格回源要校验源站证书,所以得给 node.你的域名.com 申一张正规证书。
因为域名开了橙云(CF 代理),直接申会被 CF 挡,最省事的办法是申证书时临时关代理:
- 临时关橙云:CF 后台 → DNS → 找到刚才那条
node记录 → 点橙色云朵让它变灰色 (DNS only)→ 等 1~2 分钟。 - 申证书(VPS 上执行,把域名换成你的):
看到certbot certonly --standalone -d node.example.com \ --non-interactive --agree-tos --register-unsafely-without-emailSuccessfully received certificate就成了。证书在:- 证书链:
/etc/letsencrypt/live/node.example.com/fullchain.pem - 私钥:
/etc/letsencrypt/live/node.example.com/privkey.pem
- 证书链:
- 把橙云开回来:CF 后台 → DNS → 那条
node记录的云朵点回橙色 Proxied。
注:certbot 会自动设置每 60 天续期,不用你管。续期时若再遇到 CF 代理拦截, 可在续期前临时关橙云,或改用 DNS 验证(进阶,见文末)。
5. 第四步:写 sing-box 配置
先生成两个随机值(每台新服务器都要重新生成,别和别人重复):
# 生成一个 UUID(客户端身份)
sing-box generate uuid
# 生成一个随机 ws 路径(伪装路径,越随机越好)
echo "/$(head -c 6 /dev/urandom | xxd -p)"
把上面两个输出记下来(比如 UUID=xxxx-xxxx,路径=/a1b2c3)。
编辑配置文件 /etc/sing-box/config.json,写成下面这样
(把 4 处占位替换成你的:域名、UUID、ws 路径):
{
"log": { "level": "info" },
"inbounds": [
{
"type": "vless",
"tag": "vless-ws-cf",
"listen": "::",
"listen_port": 443,
"users": [
{ "uuid": "把这里换成你生成的UUID" }
],
"transport": {
"type": "ws",
"path": "把这里换成你生成的ws路径,比如 /a1b2c3"
},
"tls": {
"enabled": true,
"certificate_path": "/etc/letsencrypt/live/node.example.com/fullchain.pem",
"key_path": "/etc/letsencrypt/live/node.example.com/privkey.pem"
}
}
],
"outbounds": [
{ "type": "direct", "tag": "direct" }
]
}
说明:
listen_port: 443——CF 回源默认走 443,所以 sing-box 直接监听 443 最省事 (前提:这台 VPS 的 443 没被别的网站/nginx 占用。被占用了看文末「进阶」)。certificate_path里的域名改成你的。outbound只写 direct(流量从本机直接出去)。
校验 + 启动:
sing-box check -c /etc/sing-box/config.json # 必须显示 ok / 无报错
systemctl restart sing-box
systemctl enable sing-box
systemctl is-active sing-box # 显示 active 就行
ss -tlnp | grep :443 # 能看到 sing-box 在听 443
6. 第五步:防火墙——只放行 Cloudflare 的 IP(重要安全步骤)
不限制的话,任何人都能扫到你的 443、直连探测,容易暴露/被封。 只允许 Cloudflare 的回源 IP 访问 443:
ufw --force reset # 如果你这台没别的服务在用 ufw,可用;有的话跳过这句
# 先放行 SSH(否则会把自己关在外面!端口换成你实际的 SSH 端口,默认 22)
ufw allow 22/tcp
# 只允许 Cloudflare 的 IP 段访问 443
for ip in 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 \
141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 \
197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 \
104.24.0.0/14 172.64.0.0/13 131.0.72.0/22; do
ufw allow from $ip to any port 443 proto tcp
done
ufw --force enable
ufw status # 检查 22 和 443(来自CF) 都放行了
Cloudflare 的 IP 段官方列表:https://www.cloudflare.com/ips/ (以后若有变动以官网为准)。
7. 第六步:生成客户端链接 + 二维码
客户端用的是这条 VLESS 链接(替换 3 处:UUID、域名、ws 路径)。
注意 ws 路径里的 / 要写成 %2F(比如路径 /a1b2c3 → 链接里写 path=%2Fa1b2c3):
vless://你的UUID@node.example.com:443?encryption=none&security=tls&sni=node.example.com&type=ws&host=node.example.com&path=%2F你的路径&fp=chrome#CF中转节点
在 VPS 上把它生成二维码(手机扫码导入):
LINK='vless://你的UUID@node.example.com:443?encryption=none&security=tls&sni=node.example.com&type=ws&host=node.example.com&path=%2F你的路径&fp=chrome#CF中转节点'
qrencode -o /root/node-qr.png -s 9 -m 3 "$LINK"
# 然后把 /root/node-qr.png 下载到本地用手机扫,或用 sftp 取走
客户端(手机 sing-box / v2rayN / Shadowrocket 等):
- 从剪贴板导入那条
vless://链接,或扫二维码。 - 关键参数对照:地址=你的域名、端口=443、传输=ws、路径=你的、TLS=开、SNI=你的域名、flow=空。
8. 第七步:验证整条链路通不通(在 VPS 上自测)
# 测 WS 握手能不能穿过 CF 到 sing-box(返回 101 = 全链路通)
curl -s -m 15 -o /dev/null -w "HTTP: %{http_code}\n" --http1.1 \
-H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" \
"https://node.example.com:443/你的路径"
- 返回 101 → 成功!整条 CF→源站→sing-box 通了,客户端导入就能用。
- 返回 526 → CF 校验源站证书没过(证书没申好/域名不对,回第 4 步)。
- 返回 520 → 源站异常(sing-box 没起来 / 路径不对)。
- 返回 522/超时 → CF 回源连不上你 443(防火墙没放行 CF / sing-box 没监听 443)。
客户端导入后,关 WiFi 用流量、选这个 CF 节点、打开网页,能上网就成了。
9. 常见故障排查
| 现象 | 原因 | 解决 |
|---|---|---|
| 连上没网,curl 测返回 526 | CF 严格回源校验证书失败 | 确认第 4 步证书申成功、域名和 sing-box 配置里一致 |
| 返回 522 / 超时 | CF 回源到不了 443 | 检查 ufw 放行了 CF 段、sing-box 在听 443、VPS 防火墙/安全组也放行 443 |
| 返回 520 | 源站(sing-box)报错 | systemctl status sing-box、journalctl -u sing-box -n 50 看日志 |
| ping 域名返回的是 VPS IP 不是 CF IP | 橙云没开 | DNS 记录云朵点成橙色 Proxied |
| 一切正常但客户端还连不上 | 客户端参数错 | 核对 端口 443、传输 ws、路径前面带 /、TLS 开、SNI=域名 |
排查时在 VPS 上盯日志很有用:
journalctl -u sing-box -f # 实时看 sing-box(客户端连进来会有记录)
10. 进阶:如果这台 VPS 的 443 已经被网站(nginx)占用
有些服务器 443 已经跑着网站/面板(nginx/openresty),不能让 sing-box 独占 443。 办法:让 nginx 在 443 上接住,把那个 ws 路径反向代理给 sing-box(sing-box 改听本地端口)。
- sing-box 入站
listen改成127.0.0.1、listen_port改成比如8443(其余不变,TLS 仍开)。 - nginx 里给你的子域名加一个 server 块(443 ssl,证书用第 4 步申的那张),核心是:
server { listen 443 ssl; server_name node.example.com; ssl_certificate /etc/letsencrypt/live/node.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/node.example.com/privkey.pem; location /你的路径 { proxy_pass https://127.0.0.1:8443; proxy_ssl_verify off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 300; } # 根路径:伪装成普通网站,见第 11 节(别用 return 444) location / { root /var/www/node-landing; try_files $uri /index.html; } } nginx -t校验通过再nginx -s reload。客户端链接里的端口仍是 443(连的是 nginx)。
本次给你搭的就是这个进阶版(因为那台 443 上跑着交易面板)。 新服务器若 443 空着,用第 5 步的简单版(sing-box 直接听 443)即可,省去 nginx。
11. 根路径伪装:别让首页暴露你是个”空壳”
为什么要做这步:上面 nginx 版如果根路径写 location / { return 444; },
别人(或墙的主动探测)直接访问 https://node.example.com/ 时,源站直接断连,
Cloudflare 会回退到它自己的错误页(521/522 之类)。一个”域名解析正常、
但首页永远报错”的站点是很可疑的特征——正常网站首页都能打开。伪装的核心思想是
让这个域名从任何角度看都像个普普通通的网站,翻墙流量只藏在那条随机 ws 路径里。
所以给根路径放一个平平无奇的落地页,而不是断连:
mkdir -p /var/www/node-landing
cat > /var/www/node-landing/index.html <<'HTML'
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome</title>
<style>
body{font-family:-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:#f5f6f8;
color:#333;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0}
.card{text-align:center;padding:48px 40px;background:#fff;border-radius:12px;
box-shadow:0 2px 16px rgba(0,0,0,.06);max-width:420px}
h1{font-size:24px;margin:0 0 12px}p{color:#666;line-height:1.6;margin:6px 0}
.foot{margin-top:24px;font-size:13px;color:#999}
</style></head><body>
<div class="card"><h1>It works!</h1>
<p>This server is up and running.</p>
<p class="foot">If you are the site administrator, your content will appear here.</p>
</div></body></html>
HTML
然后把第 10 节 server 块里的 location / 指向它(上面第 10 节示例已经是改好的版本),
nginx -t && nginx -s reload。之后浏览器访问域名首页会看到这个正常页面,
而 CF 错误页消失。
验证(在 VPS 上,模拟经 CF 回源的请求):
curl -sI -H "Host: node.example.com" https://127.0.0.1/ -k | head -1 # 应为 200
进阶伪装(可选,越像真站越好):
- 把落地页换成一个真实用途的静态站(个人博客、作品集、“建设中”通知页均可), 比空壳 “It works” 更自然。
- 那条 ws 路径(第 5 步生成的)保持够随机、够长,别人猜不到;不要用
/ws、/vless这种一看就懂的路径。 - 如果同一台机器还开了别的域名(比如面板站),CF 那边每个域名都单独配,互不影响。
简单版(sing-box 直接听 443、无 nginx)没有这个问题:因为客户端直接是 TLS+ws 握手,普通浏览器访问会被 sing-box 拒绝(不是 CF 错误页)。但装了 nginx 的进阶版 一定要补这个落地页——这是最容易被忽略、也最容易露馅的一环。
12. 一句话备忘
- 直连快但易被封;CF 中转慢但封不掉。两条都留着,被封了切 CF。
- 核心四样:①域名橙云代理 ②sing-box VLESS+WS+TLS ③子域名正规证书 ④只放行 CF 的 IP。
- 装 nginx 的进阶版再加一样:⑤根路径放个正常落地页,别用 return 444(第 11 节)。
- 每台新机器:重新生成 UUID 和 ws 路径,重新申证书,别复用。
(文档结束)
加载评论中…