整體架構
要解決的問題:家用浮動 IP 頻繁變動,中國各地 DNS 快取跟不上,朋友端常常連不上。 解法是讓朋友端不再依賴「網域解析」,改用訂閱功能,App 定時自動抓取目前的最新 IP, 全程不需要人工通知、也不受 DNS 傳播速度影響。
核心是一個 Cloudflare Worker:依網址路徑判斷是哪個朋友/哪組裝置,去 KV 讀取「現在的 IP」,
再依 ?v= 參數決定輸出格式(v2ray / Clash / 裸 xray-core config / 一鍵安裝腳本),
即時拼出對應內容回傳。KV 只存一個共用值(目前 IP),所有朋友共用同一份;
每個朋友的差異(UUID、shortId、路徑、名稱)寫死在 Worker 程式碼裡,手動維護。
flowchart TD
A["DDNS PowerShell 腳本"] -->|更新 A 記錄| B["Cloudflare DNS"]
A -->|寫入 current_ip| C["Cloudflare KV"]
C --> D["Cloudflare Worker"]
D -->|"依路徑判斷 client"| E["讀取 KV 目前 IP"]
E -->|"?v=v2ray(預設)"| F["base64 vless 連結"]
E -->|"?v=clash"| G["完整 Clash config.yaml"]
E -->|"?v=xrayclient"| H["裸 xray-core config.json"]
E -->|"?v=install"| I["PowerShell 一鍵安裝腳本"]
F --> J["Shadowrocket / v2rayN 訂閱"]
G --> K["Clash / Mihomo 訂閱"]
H --> L["irm 下載後手動跑 xray-core"]
I --> M["irm ... | iex 一鍵安裝/更新"]
另外還有一組獨立的 IP_TOKENS 路徑空間,跟節點用的 CLIENTS 完全分開,
單純回傳目前 IP 的純文字,不含任何節點資訊,給只需要知道「目前 IP 是多少」的其他用途用。
目前的伺服器環境
伺服器端 Windows 電腦跑 xray + config.json,實際上有 4 個 inbound:
| Inbound | 監聽 | 用途 |
|---|---|---|
| ① VLESS Reality Vision(對外) | 區網 IP:443 | 給所有外部朋友直連,主力入口 |
| ② VLESS Reality(本機迴環) | 127.0.0.1:12345 | 客戶端設定裡的迴環測試用,不對外開放 |
| ③ VLESS + WebSocket | 127.0.0.1:8080 | 走 Cloudflare CDN 中轉的備援線路 |
| ④ SOCKS(給 WARP 用) | 127.0.0.1:50000 | 走 wgcf-warp outbound 的流量入口 |
路由規則依 client 的 email 欄位分流:指定給 warp 分組的 user 全部流量走
Cloudflare WARP 出去;指定給 direct 分組的 user 直接從家裡出去;其餘沒特別指定的
client 走 fallback 規則(TCP 走 warp、UDP 走 wgcf-warp)。email 只是內部路由比對用的識別字,
跟朋友實際看到的訂閱節點名稱是兩回事,可以不一樣,但維持對應關係比較好維護。
config.json(含 4 個 inbound、routing 規則、wireguard/warp outbound 設定)內容較長,
點下方可展開查看佔位結構,實際部署時對照原始檔案整段貼回即可,結構不會因為這篇文章而改變。
點擊展開/收起:伺服器端完整 config.json(佔位,稍後貼回)
// ===== 伺服器端完整 config.json(佔位,稍後貼回)=====
// {
// "log": { "loglevel": "warning" },
// "inbounds": [
// // ① VLESS Reality Vision,監聽區網 IP:443,clients 陣列含所有朋友的 uuid/email/flow
// // ② VLESS Reality,監聽 127.0.0.1:12345,僅供本機迴環測試
// // ③ VLESS + WebSocket,監聽 127.0.0.1:8080,path 隨機字串,走 CF CDN 中轉
// // ④ SOCKS,監聽 127.0.0.1:50000,tag: wgcf-socks-in,供 wgcf-warp outbound 使用
// ],
// "dns": { "servers": [ /* 1.1.1.1 / 1.0.0.1 / 8.8.8.8 / 8.8.4.4 DoH */ ] },
// "routing": {
// "domainStrategy": "IPIfNonMatch",
// "rules": [ /* 依 user(email)分流 warp / direct,詳見本節文字說明 */ ]
// },
// "outbounds": [
// // wireguard(tag: wgcf-warp,Cloudflare WARP 端點)
// // socks(tag: warp,轉給本機 wgcf 代理)
// // freedom(tag: direct,sendThrough 綁定區網 IP)
// // blackhole(tag: block)
// ]
// }
//
// 完整內容見「Cloudflare KV Worker 訂閱自動更新 建置指南 v2.md」,之後直接整段貼回這裡。
建置步驟
1. 建立 Cloudflare KV Namespace(只需做一次)
- Dashboard →「Workers 和 Pages」→「KV」,建立 namespace(例如
vpn-sub) - 記下 Namespace ID、Account ID
- API Token 要有
Workers KV Storage:Edit權限(可沿用 DDNS 腳本現有 Token 加上這個權限)
這一步做完之後 KV 就設定好了,之後只會透過 API 被腳本自動更新「值」,不用再手動碰它。
2. 部署 Worker(四種輸出格式)
路徑格式一覽:
| 路徑寫法 | 對應功能 | 給誰用 |
|---|---|---|
/{token} 或 ?v=v2ray | base64 編碼的 vless 連結(可多節點多行) | Shadowrocket / v2rayN |
?v=clash | 完整 Mihomo / Clash config.yaml | Clash 系列 App |
?v=xrayclient | 裸 xray-core config.json(?i= 可指定多節點群組第幾個) | 桌機直接跑 xray-core |
?v=install | PowerShell 一鍵安裝/更新腳本 | irm ... | iex 直接執行 |
/{ip_token}(獨立於 CLIENTS) | 純文字,只回傳目前 IP | 其他只需要知道目前 IP 的用途 |
CLIENTS 物件支援兩種寫法:單一 client 直接寫
{ uuid, sid, name };多節點群組(例如同一人要 direct + warp 兩個節點包在同一份訂閱裡)
寫成 { clients: [ {...}, {...} ] },Worker 內部統一用
client.clients || [client] 轉成陣列處理。
點擊展開/收起:Cloudflare Worker 完整程式碼(佔位,稍後貼回)
// ===== Cloudflare Worker 完整程式碼(佔位,稍後貼回)=====
// 內容包含:
// - const IP_TOKENS = { "隨機字串": { name } }
// - const CLIENTS = { "隨機路徑": { uuid, sid, name } | { clients: [...] } }
// - const SNI / PBK 共用參數
// - export default { async fetch(request, env) { ... } }
// 依 path 比對 IP_TOKENS → 純文字回傳 IP
// 依 ?v= 參數分流到 buildXrayConfig() / buildInstallScript() / buildClashConfig()
// 預設輸出 base64 編碼的 vless 連結
// - function buildXrayConfig(client, ip) { ... } 裸 xray-core config.json
// - function buildInstallScript(token, origin) { ... } 一鍵安裝 PowerShell 腳本
// - function buildClashConfig(clients, ip) { ... } 完整 Clash config.yaml
// - const RULES_BODY = `...` 628 條分流規則本體(從 Shadowrocket 遷移)
//
// 完整版本見「Cloudflare KV Worker 訂閱自動更新 建置指南 v2.md」,之後直接整段貼回這裡。
部署後到 Worker「設定 → 繫結」新增 KV 命名空間繫結,變數名稱設成 VPN_SUB。
[guid]::NewGuid().ToString("N") 獨立生成,跟 UUID 完全脫鉤。
3. 更新 DDNS PowerShell 腳本
在原本「更新 Cloudflare A 記錄成功」的程式碼後面加一段 Update-SubscriptionKV 函式,
把目前 IP PUT 到 KV 的 current_ip 這個 key。
點擊展開/收起:DDNS 腳本新增段落(佔位,稍後貼回)
// ===== DDNS 腳本新增段落(佔位,稍後貼回)=====
// function Update-SubscriptionKV { param($NewIP, $AccountId, $NamespaceId, $ApiToken) ... }
// 呼叫 Cloudflare API: PUT /accounts/{id}/storage/kv/namespaces/{id}/values/current_ip
// 完整程式碼見建置指南 v2.md 第三節。
4. 一鍵安裝腳本的使用方式
Windows 桌機直接跑 xray-core(不透過 App)的情境,可在資料夾裡(已放好 xray.exe)執行:
irm https://auto-update.doggycxj.com/{token}?v=install | iex
會自動:檢查 xray.exe 是否存在 → 從 ?v=xrayclient 端點下載最新設定寫入
config.json → 找到同資料夾裡的舊 xray 行程並關掉 → 用新設定重新啟動,
印出 SOCKS5 監聽位址(127.0.0.1:10808)。每一步失敗都會印出明確錯誤訊息並暫停視窗。
5. 驗證
- v2ray 格式:解碼 base64 後應還原出正確的
vless://...連結,IP 是最新的 - clash 格式:檢查
proxies區塊的server是不是最新 IP - xrayclient 格式:JSON 語法正確
- install 格式:顯示原始 PowerShell 腳本文字(不會被瀏覽器執行)
- IP_TOKENS:直接顯示純文字 IP,不含其他資訊
- App 端設定「訂閱自動更新」,間隔建議 15~30 分鐘
日常維運 SOP
新增一個朋友(單一節點)
config.json的clients加一組新 UUID → 存檔並重啟 Xray- Worker 的
CLIENTS加一行{ uuid, sid, name }→ 重新部署 - 把訂閱網址(不是 QR code)私下傳給新朋友
新增一組多節點群組(例如 direct + warp)
config.json加兩組 UUID,對應不同email走不同路由分流 → 重啟 Xray- Worker 的
CLIENTS加群組格式{ clients: [ {...}, {...} ] }→ 重新部署 - 訂閱後 App 端會看到兩個可選節點
停用一個朋友
順序相反:先移除 Worker 的 CLIENTS(訂閱立刻失效)→ 重新部署,
再刪 config.json 裡的 UUID 並重啟 Xray(徹底收回連線權限)。
IP 變動
完全不用管,DDNS 腳本自動處理、KV 自動更新,四種格式都是即時讀取同一個 KV 值。
調整 Clash 分流規則
規則寫在獨立的 RULES_BODY 常數裡,改完存檔重新部署即可,不影響其他三種格式。
安全性重點提醒
- 訂閱網址等同完整連線憑證,解碼後含完整 UUID,走私下一對一管道傳遞,不要公開貼出
?v=xrayclient/?v=install格式一樣包含完整 UUID 跟目前 IP,敏感等級相同- IP_TOKENS 路徑雖不含 UUID,但會洩漏真實 IP,同樣要用隨機路徑
- 路徑建議至少 32 字元(
[guid]::NewGuid().ToString("N")),每個朋友獨立一組 - 懷疑外流:先移除 Worker 對應那行讓訂閱立即失效,再回頭刪
config.json的 UUID 並重啟 Xray
DDNS 網域還要留著嗎
要,繼續保留。訂閱機制上線後朋友端不再依賴網域,但 DDNS 腳本建議照常運作: 自己的裝置如果還是用網域連線仍然需要它;也可以當備援,萬一 Worker/KV 出狀況, DDNS 網域至少是一個人工能查、能排除問題的管道。兩條線並行、互不影響,成本幾乎是零。
待辦清單
- 建立 KV namespace,記下 Namespace ID、Account ID
- Token 加上
Workers KV Storage:Edit權限 - 部署 Worker(四格式版),先放一個朋友測試
- Worker 綁定 KV(變數名
VPN_SUB) - 手動塞一筆
current_ip測試值進 KV,驗證四種格式都能正確吐出 - 修改 DDNS PowerShell 腳本,加入
Update-SubscriptionKV呼叫 - 觸發一次 IP 變動,確認 KV 真的被自動更新
- Shadowrocket / Clash App 實測訂閱,確認能正常連線
- 桌機實測
irm ...?v=install | iex一鍵安裝流程 - 開啟訂閱自動更新,設定合理間隔(15~30 分鐘)
- 其餘朋友依 SOP 逐一加入
- 【待補】把 Clash
RULES_BODY裡刪減的 628 條規則貼回去