Xray gRPC APIで通信量を取得しノードを自動切替する実装ガイド

Xray-coreのノード管理をスクリプト化したい方向けに、gRPC APIのStatsServiceで通信量を取得し、HandlerServiceで出 outbound を操作する方法を解説します。JSON設定例を交え、ノード選択の自動化、APIのアクセス制限、運用時の注意点やログを使ったトラブルシューティング…

この記事の概要

XrayのgRPC APIを使って、outboundごとの通信量を取得し、しきい値や接続状態を判断材料にする実装方法を解説します。StatsServiceで確認できるカウンター、HandlerServiceで操作できる範囲、実際に自動切替を運用する際の設計上の注意点を整理します。APIはローカル限定で公開し、サンプル設定と段階的なテスト手順を使って、安全に監視処理を組み立てましょう。

gRPC APIの役割:通信量の取得とoutbound操作を分ける

XrayのgRPC APIは、コアの機能を外部プログラムから呼び出すための管理インターフェースです。設定にAPIサービスを登録し、API用inboundを通じて接続します。アプリ画面のノード一覧やサブスクリプションと同じものではなく、サーバーアドレスや認証情報を自動で収集する仕組みでもありません。監視スクリプトは、コアが実際に読み込んだ設定と、APIが返す統計情報の両方を確認する必要があります。

本題で使う中心的なサービスはStatsServiceとHandlerServiceです。StatsServiceのQueryStatsは、統計名に一致するカウンターを取得できます。HandlerServiceは実行中のコアにinboundやoutboundを追加・削除するための操作を提供します。ただし、outboundを追加・削除することと、ルーティングルールやロードバランサーの選択条件を切り替えることは別の操作です。HandlerServiceだけで任意のルーティング設定を書き換えられると考えてはいけません。

通信を処理する 統計カウンターを照会する 差分と状態を判定する 切替条件を評価する 管理APIへ操作を送る

送受信量の統計を有効にするには、設定のトップレベルに"stats": {}を置き、必要なシステム統計をポリシーで有効にします。outboundの通信量は、たとえばoutbound>>>node-a>>>traffic>>>uplinkやoutbound>>>node-a>>>traffic>>>downlinkという統計名で照会します。uplinkはコアからoutboundへ送る方向、downlinkはoutboundからコアへ戻る方向です。利用者が画面で想像する「アップロード」「ダウンロード」と向きが逆に見える場合があるため、実データで確認してください。

API設定例:統計を有効にし、待受先をlocalhostに限定

次の例は設定の要点を示す抜粋です。既存のconfig.json全体をこの内容で置き換えるものではありません。ほかのinbounds、outbounds、ルーティングルールとタグが重複しないよう統合してください。Xrayのバージョンや設定形式によって対応項目が異なるため、起動前にそのバージョンの設定検証機能で確認します。

APIとローカルinbound

サービス
StatsService、HandlerService
listen
127.0.0.1
port
10085
inbound tag
api-in
outbound tag
api

API用inboundからの通信は、API用outboundへ送るルーティング規則を設定します。

統計とポリシー

stats
空オブジェクトを有効化
outbound uplink
system.statsOutboundUplink
outbound downlink
system.statsOutboundDownlink
記録間隔
例:5秒
照会方法
QueryStatsでタグを指定

ポリシーで必要なカウンターを有効にし、使わない統計は増やさない構成にします。

設定の形を把握するための短い例を示します。実環境では既存のルールを保ち、api-inからのリクエストをAPIサービスへ到達させるルールを通常の通信ルールより優先して配置します。apiタグのoutboundも実際の設定に存在しなければなりません。

{
  "api": {
    "tag": "api",
    "services": ["StatsService", "HandlerService"]
  },
  "stats": {},
  "policy": {
    "system": {
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  },
  "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"
  }]
}

この抜粋だけではAPI用inboundのルーティング規則や通常のプロキシoutboundは完成していません。設定にAPI用ルールを加える際は、API用inboundを公開ネットワーク側の待受先にしないことが重要です。ポート10085は例であり、他のプロセスや設定と競合する場合は別の空きポートを選び、クライアント側の接続先も合わせて変更してください。ファイアウォールで遮断するだけでなく、待受アドレスを127.0.0.1にするのが基本です。

実装手順:5秒間隔で差分を測り、切替条件を判定する

自動切替は「通信量が増えたら別ノードへ移る」だけでは安定しません。通信量はユーザーの利用状況でも変わり、カウンターが増えないことはノード障害を意味しません。遅延や接続失敗などの健全性情報と、通信量上限などの運用ルールを分けて扱い、切替後に元へ戻る条件も設けます。まずは監視のみで動かし、判定結果をログに記録してから自動操作を有効にしてください。

  1. API接続を確認

    コアの起動ログでAPIサービスとポートを確認します。監視プロセスから127.0.0.1:10085へgRPC接続し、外部インターフェースから同じポートに接続できないことも確認してください。

  2. カウンターを照会

    生成済みのXray gRPCクライアントからStatsServiceのQueryStatsを呼び出します。最初は統計名のパターンを絞り、node-aのuplinkとdownlinkが取得できることを確認します。

  3. 差分を計算

    5秒間隔で前回値を保存し、現在値から差し引きます。値が減った場合は、再起動やカウンターリセットの可能性があるため、負の転送量として処理せず新しい基準値として記録し直します。

  4. 切替条件を評価

    たとえば3回連続で健全性チェックに失敗した場合、または運用上定めた累積上限に達した場合だけ切替候補にします。1回のサンプルだけで判断せず、クールダウン時間を設けて頻繁な往復を防ぎます。

  5. 段階的に反映

    まず候補outboundを用意し、ルーティング方式がその候補を選べることを確認します。HandlerServiceで追加・削除する場合はAPIの応答を検証し、切替後に新しいタグの統計が増えることを確認します。

実装の中心は、照会処理と切替処理を分離することです。概念上の監視ループは次のようになります。これは特定言語でそのまま実行できるコードではなく、gRPCスタブの生成方法やTypedMessageの構築は、採用するXrayの.proto定義とクライアントライブラリーに合わせて実装します。

every 5 seconds:
  stats = StatsService.QueryStats(pattern="outbound>>>node-a>>>traffic>>>")
  delta = current_counters - previous_counters
  update_previous_counters()

  if health_failures >= 3 and cooldown_expired:
      record_switch_decision()
      request_controlled_route_change()
      verify_new_outbound_traffic()

QueryStatsのリセット指定を毎回有効にすると、他の監視処理や利用者が参照するカウンターにも影響する可能性があります。基本は累積値を読み、監視側で差分を計算します。Xrayの再起動をまたぐ場合はプロセス稼働時間やカウンター減少を検出し、前回値を引き継いで誤った巨大差分を作らないようにしてください。監視プロセス自身の再起動も考慮し、必要なら前回値と時刻を小さな状態ファイルなどに保存します。

HandlerServiceの範囲と安全な切替方式

HandlerServiceの追加・削除操作は、稼働中のコアにoutboundハンドラーを反映する用途に使えます。しかし、通常のルーティング設定を自由に編集するAPIと同一ではありません。たとえばルールが常にnode-aタグを参照している状態でnode-bを追加しても、その通信が自動的にnode-bへ移るとは限りません。また、参照中のoutboundを削除して同じタグで別設定を追加する手順は、一時的な通信断や処理タイミングの問題を生む可能性があります。

ノード切替を安定させる構成としては、切替先を事前に定義したルーティングや、使用中のXrayバージョンが対応するバランサー・監視機能を検討します。通信量を理由に切替する場合、統計の収集だけをStatsServiceに任せ、設定変更は生成済み設定を管理する外部コントローラーが担当する設計も選択肢です。設定ファイルを更新してコアを再起動する方式では短い通信断が発生し得るため、構文検証、バックアップ、復旧手順を含めてください。

判断の要点:通信量の取得と経路の変更は別の制御面

StatsServiceで特定outboundのカウンターを取得できても、その数値だけで切替先が決まるわけではありません。ルーティングが候補を選べる構成か、変更を反映する制御手段があるかを先に確かめ、HandlerServiceの追加・削除をルール変更の代用として扱わないでください。

HandlerServiceを使うプログラムでは、API応答を成功とみなす条件を明確にします。RPCエラーの有無だけでなく、対象タグが追加されたか、ルーティングから参照できるか、実際にそのoutboundのカウンターが増えたかを確認します。サービス定義やTypedMessageのフィールドはコアのバージョンによって差があり得るため、異なるバージョンの.protoファイルを混ぜてスタブを生成しないでください。

トラブルシューティングとよくある質問

接続できない場合は、まずXrayがAPI設定を読み込んで起動しているか、API用inboundが想定ポートで待ち受けているか、ルーティングがAPI用outboundへ到達するかを順に確認します。次にgRPCクライアントとコアのバージョン、呼び出しているサービス名、統計名のタグを照合してください。通信量がゼロでも、ただちにノード故障と決めつけず、対象タグを通る実通信があるか、必要なpolicy統計が有効かを調べます。

QueryStatsを呼べるのに値が見つからないのはなぜ?

まずstats設定とstatsOutboundUplink、statsOutboundDownlinkの有効状態を確認します。次に実際のoutboundタグを統計名に指定し、そのタグを通る通信を発生させてから再照会してください。

uplinkの値が送信量の感覚と合わない場合は?

カウンターが表す方向はコアとoutboundの間です。uplink・downlinkの両方を同じ時間帯で取得し、少量のテスト通信を行ってどちらが増えるか確かめてから、監視画面の表記を決めます。

HandlerServiceで別ノードを追加すれば切り替わる?

追加だけでは切替は保証されません。既存ルールがどのタグを参照しているか確認し、候補outboundを選択するルーティングやバランサー、または安全に設定を反映する別の制御手段を用意してください。

APIポートを別の端末から使ってもよい?

原則としてローカルの監視プロセスだけが接続できる構成にします。リモート公開が必要な特別な環境では、通信経路の制限や認証・暗号化を含む保護策を設計し、インターネットへ無制限に公開しないでください。

運用を始める前に、監視のみの期間を設け、累積カウンター、5秒ごとの差分、再起動時のリセット、切替判定のログを見比べます。その後、切替機能を有効にし、意図したタグの通信量が増えることと、切替失敗時に元の経路へ戻せることを検証してください。APIをローカルに限定し、統計取得と設定変更を分離しておけば、誤操作の影響を抑えながら段階的に自動化できます。

v2rayN をダウンロード