Xrayの設定ファイル構成を解説|inbounds・outbounds・routingの読み方

log、inbounds、outbounds、routing、dnsの順にXrayの設定JSONを解説。各項目の役割と、通信が各セクションをどう流れるかを確認できます。

この記事の概要

ノードのインポート方法は分かり、Xrayのネイティブ設定を読み始めたい方に向けた記事です。ローカルの入口、直結、遮断用の出口だけを含むJSONを例に、ログ、ポート、タグ、ルーティングの順序、DNSの関係を解説します。読み終えると、通信がどこで止まったかを特定しやすくなり、クライアント設定、共有リンク、コアの実行設定それぞれの役割も整理できます。

設定オブジェクトと通信経路

Xrayは接続を処理するコアで、v2rayNはノードを管理し、設定を生成してコアを起動するデスクトップクライアントです。ノード共有リンクに記載されるのは通常、1つのリモート接続情報です。一方、ネイティブJSONではローカルの待ち受け、複数の出口、ルーティング、DNSをまとめて設定できます。共有リンクをconfig.jsonとして保存しても、そのまま実行可能なコア設定にはなりません。

アプリのリクエスト inboundで受信 ルールに基づく振り分け outboundで接続 接続先サービス

この流れが設定を読む際の基本です。logは状態を記録し、dnsは名前解決が必要な場合に処理に関わります。どちらも、すべてのリクエストが順に通過する独立した中継地点ではありません。JSONでのトップレベル項目の記述順も、通信の順序を決めるものではありません。

設定JSONの全体例:ローカル入口と直結の基本構成

以下は構成を理解するための単体設定例です。SOCKS入口は127.0.0.1:10808、HTTP入口は127.0.0.1:10809で待ち受けます。リモートプロキシノードは含まれていません。通常のリクエストは直結し、予約済みのテスト用ドメインblocked.test宛てのリクエストは遮断します。リモートプロキシの動作確認には使えません。

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    },
    {
      "tag": "http-in",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {
        "domainStrategy": "UseIP"
      }
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:blocked.test"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "127.0.0.0/8",
          "10.0.0.0/8",
          "172.16.0.0/12",
          "192.168.0.0/16"
        ],
        "outboundTag": "direct"
      }
    ]
  },
  "dns": {
    "servers": [
      "localhost"
    ]
  }
}

この例は厳密なJSONです。キー名と文字列はダブルクォートで囲み、コメントは付けず、配列の最後の要素の後にカンマを置きません。後述する各項目の説明はこの設定を解説するもので、項目ごとに組み合わせて別の設定を作る必要はありません。

log:エラーの発生箇所を特定する

loglevelでエラーログの詳細度を設定します。よく使われる値はdebug、info、warning、error、noneです。トラブルシューティング中は、例のwarningを一時的にinfoへ変更できます。確認後は元に戻し、接続の詳細を過剰に記録しないようにしましょう。

項目役割確認するログ
loglevelエラーログの詳細度を設定設定の読み込み、待ち受け、接続に失敗した際の具体的なメッセージ
accessアクセスログの出力先を指定リクエストの宛先と実際に使用されたoutboundの情報
errorエラーログの出力先を指定起動時や実行中のエラーに関する情報

この例ではログファイルのパスを指定していません。コマンドラインから実行する場合は、まずコンソールを確認してください。accessやerrorを追加する場合は、実行中のプロセスが書き込めるパスを選び、相対パスと起動時の作業ディレクトリの関係にも注意します。ログにアクセス先が記録されることがあるため、トラブルシューティングの内容を共有する前に機密情報を削除してください。

inbounds:待ち受けアドレス、ポート、入口タグ

各inboundオブジェクトは、通信を受け付ける入口です。listenはバインドするアドレス、portは待ち受けポート、protocolはアプリが接続に使うプロトコルを指定します。tagは設定内で使う識別子であり、パスワードでもブラウザーに入力するホスト名でもありません。

SOCKS入口

タグ
socks-in
アドレス
127.0.0.1
ポート
10808
プロトコル
socks
UDP
true

アプリ側でSOCKSプロトコルを使って接続します。UDPを使うには、アプリとその先の通信経路の両方が対応している必要があります。

HTTP入口

タグ
http-in
アドレス
127.0.0.1
ポート
10809
プロトコル
http
プロトコル設定
{}

HTTPSサイトでは通常、HTTP CONNECTでトンネルを確立します。入口のプロトコルをHTTPSに変更するわけではありません。

127.0.0.1はローカルマシンからの接続のみを受け付けます。0.0.0.0に変更すると、IPv4の待ち受け範囲が広がります。他の端末からアクセスできるかどうかは、ファイアウォールやネットワーク環境にも左右されます。この例のSOCKSはnoauthを使用するため、LANで共有しようとして安易に待ち受け範囲を広げないでください。

outbounds:出口プロトコルとデフォルトの出口

outboundsは、ルーティングで選択できる出口の配列です。この例ではfreedomが宛先へ直接接続し、blackholeが接続を遮断します。directとblockは任意に付けたタグです。動作を決めるのはタグの英語の意味ではなく、protocolです。

設定レイヤー設定例の項目役割
出口の識別子tagルーティングからoutboundTagで参照
プロキシプロトコルprotocolfreedom、blackhole、VMess、VLESS、Trojan、Shadowsocksなどに対応するプロトコル実装
プロトコル設定settings出口プロトコルに応じて、宛先、ユーザー情報、その他の設定を指定
トランスポート設定streamSettings対応するプロキシ出口のトランスポート方式とセキュリティを設定

リモートプロキシの出口を追加する場合は、プロトコル、サーバーアドレス、ポート、認証情報、トランスポート設定を整合させる必要があります。freedomをvlessに変更するだけでは、ノードの設定は完了しません。TLSやREALITYの項目は該当するトランスポートのセキュリティ設定に含めます。inbound SOCKSのsettingsに適当に追加しないでください。

要点:出口の順序を変える前にフォールバックルールを用意する

どのルーティングルールにも一致しない場合、通常は最初のoutboundが使われます。この例ではdirectが先頭にあるため、未一致のリクエストは直結します。デフォルトでプロキシを使いたい場合は、フォールバックとなる出口を明示的に設計してください。特定のルールにプロキシタグが書かれているかだけを確認しても不十分です。

routing:ルールの順序、タグ参照、名前解決の方針

routing.rulesは配列の順に照合され、最初に一致したルールで出口が決まります。この例では、1つ目のルールで完全一致するドメインblocked.testをblockへ送り、2つ目のルールで指定したIPv4ネットワークをdirectへ送ります。これらのネットワークは例示用であり、特殊用途アドレス全体を網羅するものではなく、IPv6も含みません。

  1. リクエストを受け取ると、コアは入口タグ、宛先のドメイン名やIPアドレス、ポートなど、利用可能な情報を取得します。
  2. 先頭のルールから順に確認します。同じルール内で異なる種類の条件が指定されている場合、通常はすべての条件を満たす必要があります。
  3. 同じ種類のリスト内にある候補は、通常はいずれかに一致すれば条件を満たします。たとえば、ip配列内のいずれかのネットワークに一致する場合です。
  4. 一致するルールが見つかったら、そのoutboundTagを使います。一致しない場合はデフォルトの出口を使います。

full:はドメイン名の完全一致、domain:はドメイン名とそのサブドメインへの一致に使います。特定の入口に適用対象を限定するには、ルールにinboundTag配列を追加できます。参照するタグは、対応するオブジェクトのtagと一致させてください。入口タグと出口タグは用途が異なるため、socks-inをoutboundとして参照することはできません。

routing.domainStrategyドメイン名を解決するタイミングルールを読む際の注意点
AsIsルーティング照合のためにドメイン名を解決しないドメイン宛ての通信は、IPルールだけで振り分けられるとは限らない
IPIfNonMatchドメイン名がルールに一致しない場合、名前解決してから再照合する広すぎるルールに早い段階で一致すると、後続の名前解決を伴う照合が行われない
IPOnDemandIPが必要なルールに照合が進むと、名前解決が実行されるIPルールの位置によって、名前解決のタイミングが変わる

この例ではAsIsを指定しているため、ドメイン名で送られたリクエストは、2つ目のIPルールとの照合だけを目的に名前解決されません。ただし、デフォルトの出口は直結です。そのため、リクエストが直結したからといって、プライベートネットワークのルールに一致したとは限りません。ルールを調べる際は、最終的にページを開けるかどうかだけでなく、実際に一致したルールと出口を確認してください。

dns:ルーティング時の名前解決と接続時の名前解決

dnsを設定しても、すべてのアプリのDNSを引き受けるわけではありません。アプリが先に名前解決してIPアドレスをプロキシへ渡す場合もあれば、ドメイン名をSOCKSやHTTP入口へ渡す場合もあります。ルーティングで利用できる情報は、まず入口が実際に何を受け取ったかによって決まります。

この例ではdns.serversに特殊値localhostを指定しています。これはローカルシステムのリゾルバーを使って名前解決するという意味で、ローカルマシン上で動作するDNSサーバーを指定するものではありません。また、UDP 53番ポートで待ち受ける設定も作成されません。アプリにDNSサービスを提供するには、DNSリクエストを受け取る入口と処理経路を別途設計する必要があります。

この例では、freedom outboundにUseIPを設定し、直結時に内蔵DNSの名前解決を使います。これはルーティングのAsIsと矛盾しません。前者はoutboundが接続を準備する段階で適用され、後者はルール照合の段階を制御します。outboundで後からIPアドレスを取得しても、すでに終了したルーティング判定が自動でやり直されることはありません。

要点:アプリがドメイン名とIPアドレスのどちらを送っているか確認する

ドメインルールに一致しない場合は、まずアプリ側ですでに名前解決されていないか確認します。ルーティング方針、DNSサーバー、outboundプロトコルを同時に変更しないでください。一度に一つのレイヤーだけ変更すれば、どの手順が結果に影響したか判断できます。

検証とトラブルシューティング:設定確認から実際の接続まで

まずコア付属のチェックコマンドで設定を検証し、次に待ち受けを起動して、最後にアプリを接続します。以下のコマンドは、実行ファイルxrayを見つけられるターミナルで実行してください。コマンド検索パスにない場合は、実際のファイルパスを指定します。先にバージョンとヘルプを確認すると、現在のバイナリで使えるオプションを把握できます。

xray version
xray run -help
xray run -test -config ./config.json
xray run -config ./config.json

設定チェックに合格しても、コアが設定を受け付けたことを示すだけです。リモートサービスへの接続や、アプリがプロキシを使っていることまでは保証されません。再現可能なローカルテストを行う場合は、別のターミナルでテスト用サーバーを起動し、2つの入口からそれぞれアクセスします。

python -m http.server 8000 --bind 127.0.0.1
curl --noproxy "" --proxy socks5h://127.0.0.1:10808 http://127.0.0.1:8000/
curl --noproxy "" --proxy http://127.0.0.1:10809 http://127.0.0.1:8000/

テストにはPythonとcurlがローカルにインストールされている必要があります。応答はローカルのテスト用ディレクトリから返されます。検証するのは「アプリから入口へ接続し、ルールで振り分け、直結outboundで接続する」という経路です。--noproxy ""は、既存のプロキシ除外設定によって今回の入口テストがスキップされるのを防ぎます。テスト後は一時サーバーを停止してください。ターミナルに表示されるディレクトリ一覧を、プロキシノードの速度測定結果と見なさないでください。

設定チェックに合格したのに、起動するとすぐ終了するのはなぜですか?

コンソールに待ち受け失敗のメッセージがないか確認します。10808と10809が使用中でないことを確認し、必要なら11808と11809に変更して、アプリ側のプロキシポートも合わせて変更してください。

ドメインルールを追加したのに、なぜデフォルトの出口が使われるのですか?

まず、リクエストにドメイン名が含まれていることを確認します。次に、先行する汎用ルールに先に一致していないか確認してください。full:が完全一致する範囲と、outboundTagが正しい出口を参照していることも確認します。

v2rayNで実行用ファイルを変更したのに、再起動すると元に戻るのはなぜですか?

クライアントが実行用設定を再生成している可能性があります。まず独立したコピーを保存し、使用中のバージョンが提供するカスタム設定の読み込み機能を使うか、クライアントのルーティングやDNS設定から変更してください。一時的な実行ファイルを長期的な設定の保存先にしないようにしましょう。

このJSONをすべてのクライアントにそのままインポートできますか?

インポート画面がネイティブ設定とノード共有情報のどちらを受け付けるか、まず確認してください。v2rayNGはXrayコアを、v2flyNGはv2flyコアを使用します。完全な設定の互換性は、コアのバージョン、各項目の対応状況、クライアントの読み込み方式によって異なります。

基本構成の検証が済んだら、リモートプロキシのoutboundを追加し、明確なルールを設定します。一度に変更するのは1か所だけにし、動作する直前の設定も残しておきましょう。問題が起きたとき、入口、ルール、名前解決、リモート接続のどこに原因があるか絞り込みやすくなり、関係のない設定を何度も切り替えずに済みます。

v2rayNをダウンロード