Xray gRPC API 實戰:用腳本挑選節點並掌握流量狀態

以 gRPC API 串接 Xray 節點管理流程,透過 StatsService 取得流量資料,再用 HandlerService 操作出站。附上 JSON 設定、安全建議與腳本化維運的實作方向。

本文重點

本文示範如何在 Xray 設定本機 gRPC API,透過 StatsService 讀取使用者或出站流量計數,再由腳本依健康檢查結果管理指定出站。適合已有 Xray 設定與節點管理經驗、希望自動化切換流程的讀者。請先注意:StatsService 回報的是統計值,不會替你判定最佳節點;HandlerService 可管理入站與出站,但不能直接改寫路由規則。把兩者的職責分清楚,才能設計可回復、可驗證的切換流程。

先釐清 API 能做什麼:統計與出站管理是兩件事

Xray 的 gRPC API 是核心提供的管理介面,可讓本機程式呼叫服務,而不是供瀏覽器或一般代理應用程式使用的代理入口。本文聚焦兩項服務:StatsService 用來查詢流量統計,HandlerService 用來管理執行中的入站與出站。要讓服務可用,必須在 Xray 設定中啟用 API,並透過路由規則將 API 入站的流量送往標籤為 api 的出站。

StatsService 回傳的是累積計數,不是即時速度,也不會附上節點延遲、丟包率或伺服器負載。腳本要估算傳輸速率,需讀取兩次計數並計算差值,再除以取樣間隔。例如,兩次讀取相隔 10 秒,計數增加 5,000,000 bytes,平均速率約為 500,000 bytes/s;這是該計數器在此區間的平均值,不代表之後的可用頻寬。

讀取統計值 估算流量變化 檢查候選節點 管理指定出站 驗證切換結果

HandlerService 的出站操作也不等於修改 routing。若多條路由規則仍指向舊的 outboundTag,只新增另一個出站不會令流量自動改走新節點。較容易控制的做法,是讓一條指定路由固定指向單一的出站標籤,再由控制程式依目前 Xray 版本支援的 HandlerService 操作更新該出站設定;操作前先確認請求格式、目標標籤和更新方式,並準備可回復的舊設定。

設定 Xray API:啟用服務並限制在本機

以下是可供參考的最小化設定範例,包含本機 API 入站、API 路由、統計項目,以及示範用的直連出站。若要套用到現有設定,請合併相應欄位,不要直接以這份示範覆蓋訂閱產生的設定。特別是 inbounds、outbounds、routing.rules、api 與 policy 都可能已有內容,重複定義或替換原有規則會使既有代理行為改變。

{
  "api": {
    "tag": "api",
    "services": [
      "HandlerService",
      "StatsService"
    ]
  },
  "inbounds": [
    {
      "tag": "api-in",
      "listen": "127.0.0.1",
      "port": 10085,
      "protocol": "dokodemo-door",
      "settings": {
        "address": "127.0.0.1"
      }
    }
  ],
  "outbounds": [
    {
      "tag": "api",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    }
  ],
  "routing": {
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "api-in"
        ],
        "outboundTag": "api"
      }
    ]
  },
  "stats": {},
  "policy": {
    "levels": {
      "0": {
        "statsUserUplink": true,
        "statsUserDownlink": true
      }
    },
    "system": {
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  }
}

API 服務名稱、入站標籤與 API 出站標籤各有用途:api.services 列出要啟用的服務;inboundTag 指向接收本機管理連線的入站;outboundTag 必須對應到設定中的 api 出站。這個管理出站不應拿來當一般瀏覽流量的代理出口。範例使用 127.0.0.1:10085,只能由本機連線;若需要從另一部管理主機操作,應透過具存取控制的安全通道,不要將 gRPC 連接埠直接暴露至公網。

API 管理入口

監聽位址
127.0.0.1
示範連接埠
10085
服務
HandlerService、StatsService
路由標籤
api-in → api

連接埠可自行調整,但 Xray 設定與控制程式必須使用相同值。

流量統計開關

使用者上行
statsUserUplink
使用者下行
statsUserDownlink
出站上行
statsOutboundUplink
出站下行
statsOutboundDownlink

只啟用系統或使用者所需的計數器;使用者統計還須符合對應帳戶層級設定。

使用者統計與出站統計的查詢名稱不同。使用者計數通常以設定中的使用者 email 為識別,例如 user>>>[email protected]>>>traffic>>>uplink;出站計數則可依出站標籤查詢,例如 outbound>>>node-a>>>traffic>>>downlink。這些名稱的前提是對應計數器已啟用,且標籤、帳戶識別資料與執行中的設定一致。更改設定後,先確認核心已載入新設定,再進行查詢。

實作切換流程:先取樣,再操作出站

開始寫控制程式前,先定義節點候選清單、健康檢查目標與失敗處理方式。腳本不宜只依照某一個流量計數器挑選節點:流量增加表示該計數器有資料經過,不代表節點延遲較低或仍能穩定連線。較穩健的判斷會結合連線測試、必要的服務回應檢查,以及固定期間內的上下載變化;當所有候選都不合格時,保留原節點通常比切換到未驗證節點安全。

  1. 檢查核心與連接埠

    確認執行中的 Xray 設定已啟用 HandlerService 與 StatsService,API 入站只監聽 127.0.0.1:10085。在控制程式中設定相同的主機與連接埠,並先確認連線可建立。

  2. 讀取流量計數

    呼叫 StatsService 的統計查詢介面,依已啟用的名稱篩選所需項目。先以不重設計數器的方式讀取,將每個名稱、數值與時間存檔,避免把一次查詢結果誤當成速率。

  3. 計算區間變化

    間隔一段時間再查一次,使用新值減去舊值並除以實際經過的秒數。若 Xray 重啟、計數器被重設或新值小於舊值,將該區間標記為無效,重新建立基準值,而不是把負數當成流量。

  4. 驗證候選節點

    對候選節點執行獨立連線測試,確認 DNS、傳輸連線及預期服務回應。依相同測試目標與逾時設定比較結果;不要只使用 TCP 連線成功或節點名稱中的地區標示作為選擇依據。

  5. 更新並確認出站

    依目前 Xray 版本支援的 HandlerService 請求更新指定出站,並確認回應成功。接著檢查核心記錄與實際連線,確定新設定已生效;失敗時恢復先前保存的出站設定並記錄原因。

切換策略應避免短時間內來回震盪。可採用連續多次檢查合格才切換、設定最短停留時間,以及為切換設定冷卻期。這些是控制程式的判斷邏輯,不是 Xray API 自動提供的能力。假設每 30 秒取樣一次,可要求連續 3 次健康檢查失敗才離開目前節點,並在切換後至少觀察數分鐘;這只是可調整的範例,應依服務的延遲需求和容錯目標設定。

結論:將「挑選」與「切換」分成兩個可驗證步驟

先由健康檢查選出候選,再透過 HandlerService 更新預先指定的出站,最後以實際流量與連線結果確認。若控制程式無法證明路由仍指向預期標籤,便不應宣稱節點已成功切換。

HandlerService 的請求格式屬於 gRPC protobuf,而不是把一段 JSON 直接送到連接埠就能完成操作。控制程式應使用與 Xray API 定義相容的 gRPC 用戶端及訊息型別,並針對正在執行的核心版本測試。除非已確認該版本的操作語意,不要假定新增出站、替換出站與修改出站是同一種行為;也不要在執行中刪除目前仍被路由引用的標籤。若自動化流程需要改動 routing 規則,應採用明確支援該流程的設定部署與重載方式,而非把它說成 HandlerService 的功能。

維運與安全:控制權限、保留紀錄、準備復原

能讀取統計或變更出站的 API 是管理介面,應按管理憑證看待。一般使用情境下,將 API 限制在回環位址,並確保作業系統防火牆不允許外部主機連入該管理連接埠。如果控制程式與核心不在同一主機,先規劃安全的管理通道與主機存取權限;不要為了方便將監聽位址改為所有網路介面。若 API 流量可能經過其他主機,還要檢查通道的加密、驗證與記錄方式。

若使用 StatsService 的查詢功能重設計數器,必須先確認其他監控程式是否共用同一組計數值。重設會影響後續差值計算,也可能使不同時間段的紀錄無法比較。常見做法是保留累積計數,由控制程式保存上一次的數值與時間戳;遇到核心重啟或計數回退時,再重新初始化基準。

此外,流量統計值是用於觀察資料量,不是帳單或服務商用量的權威憑證。核心統計的範圍、協定開銷與遠端計費方式可能不同;若要核對服務商用量,應以服務商提供的計費資料為準。需要對外分享排查記錄時,先遮蔽使用者 email、伺服器位址與訂閱憑證。

常見問題

查詢不到出站流量,是 API 壞了嗎?

先確認 policy.system.statsOutboundUplink 與 statsOutboundDownlink 已啟用,再比對查詢名稱中的出站標籤是否與目前設定一致。重新載入設定後,產生該出站流量,再查詢計數器;沒有流量時,數值維持不變可能是正常現象。

StatsService 能直接告訴我哪個節點最快嗎?

不能。它提供已啟用的流量計數,不提供完整速度測試或節點健康評分。請另外以一致的目標與逾時條件測試候選節點,再將結果交由腳本評估。

新增出站後,流量為什麼還走舊節點?

檢查 routing 規則的 outboundTag。HandlerService 管理出站不會自動把其他路由改指向新標籤;要使用新節點,必須確保路由與出站操作的設計相符,並以實際連線驗證。

可以把 API 連接埠開放給外部監控主機嗎?

不要直接暴露管理連接埠。優先讓控制程式在核心所在主機執行;若確實需要遠端管理,應使用受控的安全通道、來源限制與最小權限,並在變更前測試復原流程。

下載v2rayN