← 返回主頁
Nous Research · MIT 開源 · 2026

科學上網實戰:Oracle VM + Cloudflare 雙通道

VLESS/REALITY 主力(VM 直連)+ CF Worker 後備(edgetunnel)
全部免費,零封鎖風險,所有踩坑已替你踩平

⚠️ 法律聲明:本教程僅供個人學習與研究網絡技術之用。搭建者須遵守所在地區法律法規,不得用於任何非法用途。所有責任由搭建者自行承擔。
0 架構 1 準備 2 VM sing-box 3 CF edgetunnel 4 手機配置 5 驗證過牆 6 命令速查 7 踩坑合集 8 安全 9 Pi-hole

0 雙通道架構

唔好將所有雞蛋放同一個籃。呢個方案用兩條獨立通道互相後備:VM 嘅 VLESS/REALITY 係主力,CF Worker 嘅 edgetunnel 係後備 — 一條出事另一條即刻頂上。

📱 手機→ 自動切換→ 🟢 VM REALITY(主力)→ 🌐 互聯網
📱 手機→ 自動切換→ 🟠 CF edgetunnel(後備)→ 🌐 互聯網
VM REALITY(主力)CF edgetunnel(後備)
協議VLESS + REALITY(TLS 偽裝真實網站)VLESS + WebSocket + TLS(CF CDN 隧道)
伺服器Oracle ARM VM(大阪)Cloudflare Worker(邊緣節點全球)
費用永久免費(OCI Always Free)永久免費(CF Workers Free Tier)
過牆能力⭐⭐⭐⭐⭐ 最穩(偽裝iTunes,無SNI標記)⭐⭐⭐⭐ 強(自訂 domain,睇落係普通CF網站)
速度穩定但延遲略高Ping低(CF Anycast),但WS有overhead
風險VM IP可能被封(Oracle段)CF整段被干擾機率較低,但免費tier有限額
核心理念:兩條通道走完全唔同嘅基建(Oracle vs Cloudflare),唔會同時出事。VM IP 被封 → 手機自動跳 CF 後備 → 繼續上網。呢個就係「雙通道」嘅意義。

1 準備工作

需要點攞狀態
Oracle Cloud 帳號Oracle VM 部署指南 §1見指南
Oracle ARM VM(4 vCPU / 24GB)OCI Console 建立見指南 §2
Cloudflare 帳號 + 域名CF 補充指南 §0見指南
CF API Token(Workers 部署用)Dashboard → API Tokens → Edit Cloudflare Workers§3 會用
sing-boxVM 內自帶(Oracle VM 部署指南 §4)VM 內建
手機 sing-box AppApp Store / Google Play 搜 sing-box免費
⚠️ 敏感帳戶提醒:Oracle 帳號綁信用卡(免費但驗證用);CF 帳號管理域名 DNS。兩個都唔好同人共用密碼,API Token 千萬唔好提交去 GitHub。

2 VM 部署 sing-box(VLESS/REALITY 主力)

呢部分喺 Oracle VM 上面安裝 sing-box,建立 VLESS + REALITY 入站 — 世界最先進嘅反偵測協議,偽裝成正常 HTTPS 網站(iTunes.apple.com),GFW 無法分辨。

安裝 sing-box

curl -fsSL https://get.sing-box.dev | bash

或者用包管理:Ubuntu 22.04+ snap install sing-box。

生成憑證 唯一需要記低嘅嘢

sing-box generate uuid sing-box generate reality-keypair sing-box generate rand 4 --hex

輸出三個關鍵值,全部要記低:

  • UUID:用戶身分(例如 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
  • PrivateKey:伺服器私鑰(配對公鑰用,例如 xxxxxxxxxxxxxxxxxxxxxxx)
  • PublicKey:公鑰(手機 App 用,例如 xxxxxxxxxxxxxxxxxxxxxxx)
  • ShortID:短碼(例如 ab12,4-8個hex字元)

寫 sing-box server config

sudo nano /etc/sing-box/config.json
{ "inbounds": [ { "type": "vless", "tag": "vless-reality", "listen": "0.0.0.0", "listen_port": 443, "users": [ { "uuid": "<你的UUID>", "flow": "xtls-rprx-vision" } ], "tls": { "enabled": true, "server_name": "itunes.apple.com", "reality": { "enabled": true, "handshake": { "server": "itunes.apple.com", "server_port": 443 }, "private_key": "<你的PrivateKey>", "short_id": ["<你的ShortID>"] } } } ], "route": { "rules": [{ "outbound": "any", "action": "hijack-dns" }], "final": "direct", "auto_detect_interface": true } }

改四個 placeholder:<你的UUID>、<你的PrivateKey>、<你的ShortID>。其他照抄。

驗證 + 啟動

sudo sing-box check -c /etc/sing-box/config.json sudo systemctl enable sing-box sudo systemctl start sing-box sudo systemctl status sing-box

顯示 active (running) 即成功。

⚠️ 實測踩坑:
• Oracle NSG ≠ iptables:VM 入面開咗 UFW 唔代表通,OCI Console 嘅 Security List 都要開(兩層防火牆)
• 443 port 可能被佔用:裝 sing-box 前先 ss -tlnp | grep 443,俾其他服務佔咗就移走先
• Bot 409 Conflict:sing-box 服務同舊 polling 進程撞 → pkill -f sing-box 先啟動新服務

3 CF 雙後備:Tunnel(穩定主力)+ edgetunnel(Worker 備用)

除咗 VM REALITY 直連,我哋仲有兩條獨立 CF 通道互相後備:Cloudflare Tunnel(cloudflared,穩定穿 GFW)同 edgetunnel(Worker)。三條通道任一條出事,其他即刻頂上。

💡 Cloudflare Tunnel 完全免費:包含喺 CF Free plan,無限 tunnel / 無限流量 / 自動 SSL / 全球 Anycast。無需開 port、無需公網 IP。付費版只多 SSO / Access policies / Audit logs。

安裝 cloudflared + 建立 Tunnel(推薦先做)

# 安裝 curl -sL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb -o /tmp/cloudflared.deb sudo dpkg -i /tmp/cloudflared.deb # 用 CF Global API Key 建立 tunnel(替換 YOUR_KEY / YOUR_EMAIL / YOUR_ACCOUNT_ID) TID=$(curl -s -X POST -H "X-Auth-Email: YOUR_EMAIL" -H "X-Auth-Key: YOUR_KEY" \ -H "Content-Type: application/json" \ "https://api.cloudflare.com/client/v4/accounts/YOUR_ACCOUNT_ID/cfd_tunnel" \ -d '{"name":"vm-ws","config_src":"local"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['result']['id'])") # 攞 token + 寫 credentials TOKEN=$(curl -s -H "X-Auth-Email: YOUR_EMAIL" -H "X-Auth-Key: YOUR_KEY" \ "https://api.cloudflare.com/client/v4/accounts/YOUR_ACCOUNT_ID/cfd_tunnel/$TID/token" \ | python3 -c "import sys,json;print(json.load(sys.stdin)['result'])") mkdir -p ~/.cloudflared echo "$TOKEN" > ~/.cloudflared/tunnel-token.txt # 寫 config(假設 nginx 已加 /ws → sing-box :10001) cat > ~/.cloudflared/config.yml << EOF tunnel: $TID credentials-file: /home/ubuntu/.cloudflared/$TID.json no-autoupdate: true ingress: - hostname: ws.你的域名.com service: http://127.0.0.1:80 - service: http_status:404 EOF # DNS record(CNAME → tunnel) curl -s -X POST -H "X-Auth-Email: YOUR_EMAIL" -H "X-Auth-Key: YOUR_KEY" \ -H "Content-Type: application/json" \ "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/dns_records" \ -d "{\"type\":\"CNAME\",\"name\":\"ws.你的域名.com\",\"content\":\"$TID.cfargotunnel.com\",\"proxied\":true}" # systemd service sudo tee /etc/systemd/system/cloudflared-vmws.service << EOF [Unit] Description=Cloudflare Tunnel (vm-ws) After=network-online.target [Service] Type=simple User=ubuntu ExecStart=/usr/bin/cloudflared tunnel --config /home/ubuntu/.cloudflared/config.yml run --token $TOKEN Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload && sudo systemctl enable --now cloudflared-vmws

Tunnel 建好後,ws.你的域名.com/ws 會經 CF 轉發到 VM nginx → sing-box VLESS-WS inbound。

⚠️ nginx /ws 路由:必須用專屬 server block(真實事故教訓 2026-08-26)

唔可以求其喺任何 server block 加個 location /ws 就算。ws.你的域名.com 必須有精確 server_name 嘅專屬 block——否則日後加新 conf 改變 default_server 時,WS 握手會靜靜跌入 catch-all 網頁 app 被 404 食咗,節點直接死但伺服器一切「正常」。

sudo tee /etc/nginx/conf.d/ws-vless.conf > /dev/null <<'EOF' server { listen 80; server_name ws.你的域名.com; location /ws { proxy_pass http://127.0.0.1:10001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 3600s; proxy_send_timeout 3600s; } location / { return 404; } } EOF sudo nginx -t && sudo systemctl reload nginx

驗證(預期 101 Switching Protocols,404 即係路由錯):

curl -s --http1.1 -i -H "Upgrade: websocket" -H "Connection: Upgrade" \ -H "Sec-WebSocket-Key: dGVzdA==" -H "Sec-WebSocket-Version: 13" \ https://ws.你的域名.com/ws | head -1

(備用)下載 edgetunnel Worker 代碼

curl -sL "https://raw.githubusercontent.com/cmliu/edgetunnel/main/_worker.js" -o _worker.js

CM liu 嘅 edgetunnel 2.x — 支援 VLESS/Trojan + 管理後台 + 訂閱生成。

生成 UUID(同 VM 唔同,各自獨立)

python3 -c "import uuid; print(uuid.uuid4())"

記低,格式 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx。

部署到 Cloudflare(wrangler CLI 或 Dashboard)

最穩陣:Dashboard 手動

  • CF Console → Workers & Pages → Create Worker → 命名 edgetunnel
  • 貼上 _worker.js 內容 → Deploy
  • Settings → Variables → 加 secret:ADMIN(管理密碼)+ UUID(你嘅 UUID)
  • Settings → Bindings → 加 KV namespace(名稱 KV)
  • Trigger → Add Custom Domain → 填 vpn.你的域名.com
⚠️ 關鍵:一定要綁自訂 domain(唔係 *.workers.dev)— *.workers.dev 喺大陸多數被牆!自訂 domain 睇落係你嘅正常網站,GFW 唔會封。

驗證後台

瀏覽器開 https://vpn.你的域名.com/admin → 輸入 ADMIN 密碼登入管理後台。

攞訂閱連結

訂閱 URL 格式:
https://vpn.你的域名.com/sub?token=<計算得出嘅token>

或者直接用 vless:// 連結(見 §4 手機配置)。

4 手機客戶端配置

sing-box / v2rayNG / Shadowrocket 等 App 都支援 vless:// 連結直接匯入。

匯入三條 vless:// 連結

① VM-REALITY(直連,低延遲):vless://@:443?encryption=none&security=reality&sni=itunes.apple.com&fp=chrome&pbk=&sid=&flow=xtls-rprx-vision&type=tcp#VM-REALITY-443 ② VM-WS-CF(Tunnel,穩定主力):vless://@ws.你的域名.com:443?encryption=none&security=tls&sni=ws.你的域名.com&fp=chrome&type=ws&host=ws.你的域名.com&path=%2Fws#VM-WS-CF ③ CF-Edgetunnel(Worker 備用):vless://@vpn.你的域名.com:443?security=tls&type=ws&host=vpn.你的域名.com&fp=chrome&sni=vpn.你的域名.com&path=%2F&encryption=none#CF-Edgetunnel

⚠️ pbk 必須用 URL-safe base64(/ → _,去掉尾部 =)。標準 base64 會導致客戶端 decode 失敗(-1ms)。用真實值替換 <UUID>、<VM_IP>、<PublicKey>、<CF_UUID> 等。

設定自動切換(自動選擇最快節點)

  • v2rayNG:長按節點 → 勾選多個 → 顶按右上角 ⟳ 測速 → 揀「自動選擇」
  • sing-box GUI:選多個 outbound → urltest 自動揀
  • Shadowrocket / Stash:選「自動選擇」模式
自動切換效果:正常時用 VM REALITY(最快最穩);VM IP 被封時 → 自動跳 VM-WS-CF(Tunnel)或 CF edgetunnel → 上網無中斷。恢復後自動跳返主力。三條通道互為後備,確保任何情況下都有路可出。

5 驗證過牆

連上代理後,訪問以下網站確認過牆成功

網站預期結果用途
https://google.com正常載入基本過牆驗證
https://ipinfo.io/ip顯示代理IP(CF IP 或 VM IP)確認流量經代理出街
https://news.rthk.hk正常載入中文新聞站驗證
https://github.com正常載入開發者常用站驗證

驗證後備切換

臨時禁用主力(喺 App 入面停用 VM 節點)→ 確認仍可以上網(經 CF 後備)→ 恢復主力。呢個測試確認後備通道有效。

⚠️ myip.com / ip.sb 唔通係正常嘅:呢啲 IP 檢查站會封 Cloudflare Worker IP(太多人用 CF 代理 check IP),換 ipinfo.io/ip 就得。唔代表代理有問題。

6 命令速查表

需求命令
生成 UUIDsing-box generate uuid
生成 REALITY 金鑰對sing-box generate reality-keypair
驗證 sing-box configsing-box check -c /etc/sing-box/config.json
重啟 sing-boxsudo systemctl restart sing-box
查看 sing-box 日誌journalctl -u sing-box -f
檢查 port 有冇被佔ss -tlnp | grep 443
查看 VM IPcurl ipinfo.io/ip

7 踩坑合集(全部親測)

Q:所有網頁報 ERR_QUIC_PROTOCOL_ERROR?

原因:edgetunnel 係 WebSocket(TCP only),唔支援 QUIC(UDP)。Chrome 預設優先試 QUIC,撞牆就報錯。
解決:手機 App 設定加入路由規則 block QUIC,或者喺 Chrome 設定 chrome://flags/#enable-quic → Disabled。REALITY 通道冇呢個問題。

Q:Oracle VM 偵測到 NSG 阻擋?

原因:Oracle 有兩層防火牆 — VM 入面 UFW + OCI Console Security List,兩層都要開。
解決:OCI Console → Networking → Security Lists → Add Ingress Rules → 開 22/443/8443。

Q:sing-box 409 Conflict?

原因:兩個 sing-box 進程撞同一個 inbound port。
解決:pkill -f sing-box 停晒所有舊進程,再 systemctl start sing-box。

Q:edgetunnel 自訂 domain 顯示 CF 錯誤頁?

原因:Cert 仲喺 provisioning 或者 Worker 路由衝突。
解決:等 1-3 分鐘 cert 自動生效;如果仲係,確認 Worker Route 冇同其他 record 搶。

Q:Oracle 回收實例?

免費 VM 長期冇活動會被回收。sing-box 24/7 運行本身維持活動。加 keepalive:
crontab -e → */30 * * * * echo "alive $(date)" >> ~/keepalive.log

🔒 安全注意事項

✅ 應該做❌ 唔好做
UUID 隨機生成(唔好用網上範本)唔好同人共用 UUID / 私鑰
API Token 只賦予最小權限(Workers only)唔好將 Token / Key 提交去 GitHub
VM SSH 用金鑰認證(唔用密碼)唔好開放 Root SSH 登入
定期更新 sing-box(有安全修復)唔好用過時嘅 sing-box 版本
edgetunnel 後台設 ADMIN 密碼唔好留空 ADMIN(任何人都可以管理)
⚠️ 法律聲明(再強調):本教程僅供技術學習與個人研究用途。任何搭建者需遵守所在地區法律法規,不得將本方案用於非法用途。搭建者需自行承擔所有法律責任。

9 Pi-hole 私人 DNS(全機擋廣告)

承接返前面嘅 VM,喺同一部機行 Pi-hole + DNS-over-TLS(DoT),手機、電腦、平板全部經你嘅私人 DNS 出街 — 廣告喺 DNS 層直接擋走,唔使喺每部機裝 blocker,亦都唔使開住任何 VPN App 先有擋廣告。

VM 起 Pi-hole(Docker)

預設 admin 密碼會印喺 container log(WEBPASSWORD),網頁後台:http://<VM_IP>:8080/admin。DNS 只 bind 喺本機 5353,留返畀下一步嘅 DoT 前端轉發。

docker run -d --name pihole --restart unless-stopped \ -e TZ=Asia/Hong_Kong \ -p 127.0.0.1:5353:53/tcp -p 127.0.0.1:5353:53/udp \ -p 8080:80/tcp pihole/pihole:latest docker logs pihole 2>&1 | grep -i password

一定要更新 blocklist(新高裝係 0 條規則)

親測:新裝 Pi-hole 一個廣告都唔會擋,因為 gravity 係空嘅。要手動跑一次先載入官方默認列表;之後可以喺 Web UI → Adlists 加自己鍾意嘅 list(例如 oisd / hagezi)。

docker exec pihole pihole -g
⚠️ 唔好漏咗呢步:pihole -g 唔跑,裝完會以為部機「壞咗」——實際只係列表未載入。之後 blocklist 更新可以經 Web UI 或 cron 定時跑。

攞真 SSL cert(DoT 驗證要用)

用 acme.sh + DNS-01(Cloudflare token),唔使開 80 port,cert 自動續期。

export CF_Token="<你的CF_API_Token>" CF_Zone_ID="<你的Zone_ID>" ~/.acme.sh/acme.sh --issue --dns dns_cf -d dns.你的域名.com \ --server letsencrypt --keylength ec-256 ~/.acme.sh/acme.sh --install-cert -d dns.你的域名.com --ecc \ --key-file /etc/dnsproxy/key.pem --fullchain-file /etc/dnsproxy/fullchain.pem \ --reloadcmd "sudo systemctl restart dnsproxy"

dnsproxy 起 DoT(853)

用 AdGuard 嘅 dnsproxy(單一 binary),聽 853,上游指返 Pi-hole。systemd unit:

[Unit] Description=DoT -> Pi-hole After=docker.service [Service] ExecStart=/usr/local/bin/dnsproxy --listen=0.0.0.0 --port=0 --tls-port=853 \ --tls-crt=/etc/dnsproxy/fullchain.pem --tls-key=/etc/dnsproxy/key.pem \ --upstream=127.0.0.1:5353 --cache --cache-size=65536 Restart=always [Install] WantedBy=multi-user.target

--port=0 好重要:唔係嘅話 dnsproxy 會連 plain DNS 53 一齊開,同 VM 上其他嘢爭 port。

OCI Security List 開 853

Oracle 有兩層防火牆(同 §7 講嘅一樣):OCI Console → Networking → Security Lists → Add Ingress Rule:TCP 853。

DNS record(灰雲 A record)

CF Dashboard → DNS → 加一條:dns.你的域名.com → A record → <VM_IP>,一定要灰雲(Proxy off)— DoT 係直接 TCP 到 VM,行唔到 CF proxy。

手機 / 電腦設定

  • Android(原生):設定 → 私人 DNS → 主機名稱填 dns.你的域名.com(系統 DoT,唔使裝 App)
  • iPhone / iPad:用 DNS configuration profile(.mobileconfig,DoT),Safari 開 → 設定 → 一般 → VPN 與裝置管理 → 安裝 + 信任。可以叫 AI 幫手生成個 profile
  • Windows 11:設定 → 網路和網際網路 → DNS → 手動 → DoT 填 dns.你的域名.com
驗證:dig +tls @dns.你的域名.com google.com 出到 IP 即係通;再 dig +tls @dns.你的域名.com doubleclick.net 應該出 0.0.0.0(blocked)。
⚠️ 注意事項:

鍾意呢份指南?請我飲杯咖啡 ☕

☕ 請我喝杯咖啡