本文示範如何透過 Xray gRPC API 在執行期間新增或移除出站代理,並查詢核心流量統計。內容涵蓋 API 入口與路由設定、動態出站的資料格式、操作步驟、流量統計條件,以及如何限制 API 存取權。API 呼叫只會變更目前執行中的核心狀態,不等同於永久修改 JSON 設定檔;正式維運時,必須同時設計設定持久化與故障復原流程。
Xray gRPC API 能管理什麼
Xray 的 gRPC API 是核心提供的管理介面,讓管理程式可以在核心執行期間呼叫服務。它適合需要自動建立出站、依排程回收節點,或定期讀取流量計數的環境。這裡的「新增節點」指新增一個 outbound 出站設定,不是建立新的入站使用者,也不會自動替客戶端產生訂閱連結。
常見管理服務是 HandlerService,可用來新增或移除入站、出站等處理器;流量統計則由 StatsService 提供。兩者是不同的 API 服務:能成功新增出站,不代表統計一定已啟用;查得到全域統計,也不代表每個使用者或每個節點都已有獨立計數。
| 需求 | 對應功能 | 實際效果 | 不會自動處理的事 |
|---|---|---|---|
| 新增代理出口 | HandlerService 的新增出站操作 | 讓目前執行中的核心載入指定出站設定 | 不會永久寫回原始 JSON 檔 |
| 移除代理出口 | HandlerService 的移除出站操作 | 從執行中的核心移除指定標籤的出站 | 不會自動切換仍引用該出口的路由規則 |
| 讀取流量計數 | StatsService | 查詢已啟用並累計的統計項目 | 不會替未啟用的統計項目補回歷史用量 |
先設定本機 API 入站與路由
呼叫 gRPC API 前,Xray 設定必須建立 API 服務、承載 API 請求的入站,以及把該入站流量送往 API 出站的路由。以下是結構示意,應合併至現有設定,而不是直接取代整份設定檔。範例將 API 監聽在本機連接埠 10085;如果該連接埠已被占用,請換成未使用的本機連接埠,並同步更新管理程式的連線目標。
{
"api": {
"tag": "api",
"services": ["HandlerService", "StatsService"]
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 10085,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api-in"
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "api"
}
],
"routing": {
"rules": [
{
"type": "field",
"inboundTag": ["api-in"],
"outboundTag": "api"
}
]
}
}
這段設定的要點是三個標籤必須互相對應:API 服務的 tag 為 api,API 入站使用 api-in,路由再將該入站導向標籤為 api 的出站。不要將 API 入站路由至一般代理出口,否則管理請求可能進入一般流量處理路徑。修改設定後,先以目前部署方式驗證設定格式,再重新啟動核心;重啟只是為了載入初始 API 設定,後續動態管理才透過 gRPC 進行。
- 監聽位址:管理程式與 Xray 在同一台主機時,優先使用
127.0.0.1,避免其他主機直接連入。 - 服務清單:只加入實際需要的服務。若不需要遠端調整路由,不要為了方便而開啟額外管理服務。
- 路由規則:確認 API 入站標籤能命中專用規則,並且 API 出站標籤確實存在。
- 核心版本:不同版本與打包方式可能影響 API 型別和管理工具支援;部署前應以正在執行的 Xray 版本及其 API 定義驗證請求格式。
動態新增與移除出站的操作流程
在管理程式中,新增出站不是把一段普通 JSON 原文直接當成任意 gRPC 訊息傳送。gRPC 使用 Protobuf 型別;管理端必須依 Xray API 定義建立對應的出站設定訊息,再送交 HandlerService。JSON 可以作為管理系統的輸入或儲存格式,但需要由相容的解析與轉換流程產生 API 所需的 Protobuf 資料。請先在測試核心與測試節點上驗證轉換結果,不要假設所有版本都接受完全相同的 JSON 欄位。
-
確認管理端點
在管理程式中設定 gRPC 伺服器位址,例如同機管理時使用
127.0.0.1:10085。連線失敗時,先檢查 Xray 是否已啟動、API 入站是否監聽該連接埠,以及本機防火牆是否允許管理程式連線。 -
產生唯一標籤
為每個動態出站指定穩定且不重複的
tag,例如由系統建立的節點識別碼組成。不要將標籤設為可能重複的顯示名稱;後續移除出站與檢查路由引用,都需要依賴這個標籤。 -
驗證出站內容
在送出前檢查協定、伺服器位址、遠端連接埠和必要的驗證參數,並確認該設定能轉換成目前核心版本支援的 Protobuf 型別。避免把密碼、UUID 或私鑰寫入一般應用程式日誌。
-
呼叫新增操作
透過
HandlerService的新增出站操作提交設定。收到成功回應後,再從管理程式檢查該標籤是否已納入執行中配置;若呼叫逾時,不要直接重送不同標籤的新增請求,應先確認核心狀態,避免建立重複出站。 -
測試路由與連線
新增出站本身不會讓一般流量自動改走該出口。還要確認現有路由規則或上層管理邏輯會選取這個出站,並以受控的測試請求檢查核心日誌與目標連線結果。
-
檢查引用再移除
移除前先停用指向該標籤的路由或工作佇列,確認沒有其他設定依賴它,再呼叫移除出站操作。收到成功回應後,重新讀取執行狀態;不要把移除成功等同於已更新磁碟上的設定檔。
自動化流程宜採用「檢查目前狀態、套用變更、再次檢查」的方式,而不是只依賴 API 回應碼。對新增操作使用固定標籤與冪等檢查,對移除操作保留明確的變更紀錄;如果操作中途失敗,管理程式應能判斷核心目前處於變更前、變更後,還是部分完成的狀態。
JSON 範本、動態狀態與持久化
建議將「管理系統中的節點資料」與「送給 Xray 的出站設定」分開管理。管理系統保存經過權限控管的來源資料,再依目標核心版本產生 API 請求;這樣更新欄位或替換協定時,不必直接對執行中的設定字串做搜尋取代。以下是資料欄位的檢查清單,不是可直接傳給 gRPC 的完整請求,也不是可直接啟動的 Xray 設定。
- 識別欄位:管理系統的節點 ID 與 Xray 出站
tag建立可追蹤的對應關係。 - 協定欄位:根據實際協定提供相應的伺服器、連接埠及驗證資料;不同協定的欄位不能互相套用。
- 傳輸與安全欄位:需要時才提供傳輸方式、TLS 或其他安全設定,並完整保留伺服器端要求。
- 路由欄位:記錄哪些規則會引用該出站標籤,以便移除或替換前檢查依賴項目。
動態 API 變更通常作用於目前執行中的核心狀態。核心重啟後會載入啟動設定,因此若沒有將變更同步到部署系統管理的 JSON 或其他持久化來源,動態新增的出站可能在重啟後消失。反過來說,若只更新磁碟設定而未更新執行中核心,當下的流量也不會因此立即切換。
正式環境應把持久化視為另一個受控步驟:先驗證候選設定與標籤,再以原子方式更新設定來源並保存可復原版本;只有在確認執行中核心與持久化狀態一致後,才回報變更完成。不要讓多個管理程式各自改寫同一份設定檔,否則容易發生覆寫、狀態分歧或重啟後回退。
啟用流量統計並設計監控週期
StatsService 只能查詢核心已啟用及已累計的統計項目。需要統計入站或出站流量時,應在啟動設定中啟用相應的統計選項與政策計數,再重新載入核心。實際計數粒度取決於政策設定;若要按使用者統計,通常還必須有對應的使用者識別與計數政策。只有一條出站標籤,並不必然能得到按終端使用者區分的用量。
監控端可以每 30 秒查詢一次統計,並保存相鄰兩次讀值與查詢時間。若計數器單調增加,區間用量可由新讀值減去舊讀值;計算速率時,再除以兩次查詢的實際時間差。不要假定排程每次都準時,也不要將累積位元組數誤當成每秒速度。
查詢與重設統計是不同操作。一般監控應避免使用會重設計數的請求,否則同一時間可能有其他監控程式或維運人員正在讀取資料。若確實要重設,應先確認核心版本對重設行為的支援、記錄重設時間,並讓所有監控端使用一致的基準。
結論:先確認計數來源,再換算用量
部署前先確認所需的入站、出站或使用者統計已啟用,並用兩次不重設的讀值驗證計數方向與增量;否則報表可能顯示零值或錯誤速率,卻被誤判成流量沒有經過代理。
權限控管與常見問題
gRPC API 可以改動執行中的代理處理器,應視為高權限管理介面。不要將 0.0.0.0:10085 直接暴露在公網,也不要把 API 連接埠轉發到一般使用者網路。若管理服務必須跨主機連線,請以網路層限制來源,並採用受控的加密通道與作業系統權限;管理憑證、節點密碼和完整請求內容也不應寫入公開日誌。
新增成功,為什麼流量沒有走新出站?
新增出站不會自動改寫路由。確認路由規則或管理程式已將目標流量指向該出站標籤,再透過核心日誌與受控測試請求驗證實際出口。
重啟 Xray 後,動態新增的出站不見了?
這通常表示變更只套用於執行中狀態,沒有同步到啟動設定。請檢查持久化流程是否成功保存候選設定,並確認重啟時載入的是預期的設定檔。
API 查不到流量統計,該從哪裡檢查?
先確認啟動設定包含 StatsService,再檢查相關統計與政策計數是否啟用。若要查個別使用者,也要確認該使用者具有對應的流量計數設定。
移除出站後,設定檔也會一起刪除嗎?
不會。API 操作針對執行中的核心狀態;請另外更新受版本控管的設定來源,並確認沒有路由或其他出站仍引用已移除的標籤。