CONFIGURATION REFERENCE

V2Ray 設定ファイル:JSONフィールドとルーティングの仕組み

トップレベルの構造から始め、inbounds(受信)、outbounds(送信)、routing(ルーティング)、DNS解決、policy(ポリシー)を項目ごとに解説します。例ではXrayでよく使われるフィールドを中心に、クライアントが設定を生成する際に注意すべき上書き関係も示します。

  • JSON構造の全体像
  • Xrayコア
  • V2Ray ルーティングルール
  • DNS振り分け

目的がサブスクリプションのインポート、システムプロキシの有効化、初回接続だけなら、まずはじめにを読んでください。このページでは、クライアントが生成する設定の理解、ルールの競合箇所の特定、長期的に再利用するJSON断片の管理方法を扱います。

V2RayとXrayの設定ファイルの中心的な役割は、「アプリから送られたローカルリクエスト」を「指定した出口で処理するネットワークリクエスト」へ変換することです。設定は独立したフィールドを並べただけのものではなく、明確な順序を持つデータ経路です。アプリがまず受信リスニングポートへ接続し、コアが宛先アドレスを読み取ってトラフィックを検出します。次にルーティングモジュールがドメイン、IP、ポート、受信タグなどに基づいて送信先を選び、必要に応じてDNSモジュールが名前解決に参加し、最後に該当する送信先が接続を確立します。この経路を理解すれば、一見ランダムに見える障害も、どの段階で想定した情報が得られなかったのかに分解できます。

v2rayNはWindows、macOS、Linuxのデスクトップ向け主要GUIクライアントで、v2rayNGとv2flyNGはそれぞれAndroid向けです。GUIクライアントは通常、画面の選択内容から実行用設定を生成するため、一時設定を直接編集すると、次回起動時やサーバー切り替え時に上書きされることがあります。長期的に使う設定は、クライアントのルーティング、DNS、パラメータ設定、カスタム設定の入口から行うのが基本です。インストールパッケージを選ぶ場合はダウンロードページへ、初回接続だけならクイックスタートから始めてください。

01

JSON構造の全体像と設定の読み込み順序

トップレベルオブジェクトの連携

完全な設定は、1つのJSONオブジェクトをルートノードとします。一般的なトップレベルフィールドにはlogdnsinboundsoutboundsroutingpolicystatsがあります。受信と送信は接続経路の両端で、ルーティングが両者を結び付けます。DNSはドメインの照合と宛先解決に結果を提供し、ポリシーモジュールはタイムアウト、統計、ユーザーレベルごとの動作を制御します。ログフィールドは実行時に残す診断情報の量を決めます。任意のモジュールを省略することはできますが、リクエストを受け取る受信と処理する送信が少なくとも1つずつなければ、コアが起動しても完全なデータ経路は形成できません。

配列の順序とタグは、どちらも設定の動作に影響します。各受信または送信にはtagで安定した名前を付けられ、ルーティングルールはinboundTagoutboundTagでそれを参照します。タグは設定内部の識別子であり、サーバー名ではなく、プロトコル自体を変更するものでもありません。socks-inproxydirectblockのように、短く意味が固定された英語タグがおすすめです。同じスコープ内でタグを重複させると、ルールが最終的にどのオブジェクトを指すのか判断しにくくなり、実装によっては読み込み自体を拒否されます。

{
  "log": {
    "loglevel": "warning"
  },
  "dns": {
    "servers": [
      "1.1.1.1",
      "localhost"
    ]
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom"
    },
    {
      "tag": "block",
      "protocol": "blackhole"
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      }
    ]
  }
}

JSONの構文とデータ型

JSONは多くの設定言語より書式に厳格です。オブジェクトには波括弧、配列には角括弧を使い、キー名と文字列は半角ダブルクォートで囲みます。真偽値は小文字のtrueまたはfalseだけが使え、数値に余分なクォートを付けてはいけません。オブジェクトの最後のフィールドや配列の最後の要素の後にカンマを残すこともできません。標準JSONはコメントも受け付けないため、読み込む設定に説明文を直接書かないでください。メモを残す場合は外部ドキュメントに記録するか、クライアントが用意した専用のメモ欄を使います。コアが認識しないフィールドを独自に追加すると、無視される場合もあれば、厳格な解析モードでエラーになる場合もあります。

フィールドのデータ型は、見た目が似ているからという理由だけで置き換えられません。たとえばポートは通常、文字列"10808"ではなく数値10808です。ドメインリストは1件だけでも配列として["domain:example.com"]と記述します。一方、ルールのport"53""80,443,1000-2000"のように、範囲を文字列で表すことが一般的です。この違いは統一構文ではなく、フィールド定義によるものです。編集前に、対象が数値、文字列、真偽値、オブジェクト、配列のどれに当たるかを確認し、JSONとして解析できてもコアの読み取りで失敗する事態を避けてください。

設定の読み込みと接続処理の順序

コアは設定を読み込むと、まずJSONの解析とモジュール初期化を行い、その後に受信リスニングアドレスをバインドします。ポートが他のプログラムに使用されている、リスニングアドレスが本機に存在しない、フィールドの型が誤っているといった場合、起動段階で処理が停止します。起動に成功したことは、設定構造とローカルリソースが基本的に利用可能だという意味にすぎず、リモート側のプロトコルパラメータが正しいことを示すものではありません。実際のリモート接続は通常、アプリからリクエストが届いて初めて確立されます。そのため「コアが起動している」と「目的のサイトへアクセスできる」は別の確認段階です。

リクエストが入ると、コアはまず受信タグ、宛先アドレス、宛先ポート、ネットワーク種別を確定します。sniffingを有効にしている場合は、HTTPリクエストやTLSハンドシェイクからドメインを識別することもあります。その後、routingが上から順にルールを確認し、通常は最初に完全一致したルールで出口が決まります。どのルールにも一致しなければデフォルトの送信先が使われますが、これは一般にoutbounds配列の先頭やクライアントの生成ロジックと関係します。DNSが介入するかどうかは、宛先の解決が必要か、domainStrategyで何を選んでいるかによって決まります。最後に送信モジュールが、プロトコル、トランスポート層、セキュリティ層、サーバーパラメータに基づいて接続を確立します。トラブルシューティングでは、選択項目を何度も切り替えるより、この順序に沿って確認する方が効果的です。

設定のメンテナンスでは単一責任を保つべきです。受信はローカル接続方式、送信は出口の機能、ルーティングは選択条件、DNSは解決経路、policyは接続のライフサイクルと統計だけを記述します。複数の目的を1つのルールに混ぜると、短期的には行数を減らせても、長期的にはルールの上書きや回帰テストが難しくなります。1回の変更では1つのモジュールだけを編集し、保存前にJSON構文を確認してください。起動後はwarningまたはinfoレベルのログを確認し、明確なドメイン、IP、ポートのケースで順番にテストするのがおすすめです。

02

inbounds(受信):リスニングアドレス、ポート、トラフィック検出

受信が担う役割

inboundsは受信オブジェクトの配列で、各オブジェクトが1種類のローカル接続方式を表します。デスクトップクライアントではSOCKS受信とHTTP受信が最も一般的です。SOCKS対応アプリはSOCKSポートに接続し、HTTPプロキシのみをサポートするアプリはHTTPポートに接続します。システムプロキシモードでは通常、クライアントがOSのプロキシ設定をいずれかのローカルポートへ向けます。透過的なトラフィック取り込み、仮想NIC、リダイレクト受信には追加のプラットフォーム権限やネットワークスタック設定が必要で、通常のローカルプロキシポートと混同してはいけません。

listenは、どのローカルアドレスで待ち受けるかを決めます。127.0.0.1なら本機からの接続だけを受け付けるため、個人用デスクトップ環境で一般的です。0.0.0.0なら利用可能なすべてのIPv4インターフェースで待ち受けるため、同一LAN上の他の機器からポートへアクセスできる可能性があります。v2rayNの「LANからの接続を許可」といった設定は、基本的にリスニング範囲と関連するファイアウォール条件に影響します。同じLANの他の機器へ明確に入口を提供する必要がある場合だけ範囲を広げ、OSのファイアウォールとネットワーク環境も同時に確認してください。

portには、本機で未使用の有効なポートを指定する必要があります。ローカルSOCKSのリスニングポートとして10808がよく使われますが、プロトコル上の固定値ではなく、環境に応じて変更できます。変更後はブラウザー、開発ツール、システムプロキシ、その他の呼び出し元も同じように更新してください。コアのポートだけを変えてアプリ側を変更しないと、アプリからローカルプロキシへ接続できなくなります。複数の受信で同じアドレス上の同じポートをバインドすることはできず、プロトコルが異なっても競合します。

{
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic"],
        "routeOnly": true
      }
    },
    {
      "tag": "http-in",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ]
}

SOCKS、HTTP、UDPの動作

SOCKS受信のsettings.udpは、UDPリクエストを受け付けるかどうかを決めます。有効にしても、すべてのアプリが自動的にUDPを使うわけではなく、対応する送信やリモートプロトコルがあらゆるUDPケースを処理できる保証もありません。アプリは互換性のある方法でUDPリクエストをSOCKS受信へ渡す必要があり、ルーティングルールも不適切な出口へ送らないようにする必要があります。「Webページは表示できるが一部のリアルタイムアプリだけ不安定」という場合は、アプリの接続方式、受信側のUDP設定、ルーティングのネットワーク条件、送信プロトコルの対応能力を分けて確認してください。

HTTP受信は主にHTTPプロキシリクエストと、CONNECTメソッドで確立されるHTTPSトンネルを受け付けます。通常のWebサーバーではなく、そのポートへ送られた任意のプロトコルを自動処理するものでもありません。システムのHTTPプロキシ設定だけを読むアプリ、個別のSOCKS設定に対応するアプリ、システムプロキシを完全に無視するアプリがあります。受信を設定する前に、呼び出し元が実際にどの接続方式をサポートしているかを確認し、必要以上にリスニングポートを増やさないでください。ポートが増えるほど、ポート競合、ルールの出所、ファイアウォール動作の切り分けが複雑になります。

リスニングアドレスをLANへ広げる場合は、受信設定で認証を検討できますが、認証機能は受信プロトコルとクライアントの生成方式によって異なります。より安全なのは、まずネットワーク境界を制限し、管理下の機器だけにアクセスを許可して、信頼できないネットワークへローカルプロキシポートを公開しないことです。本機だけで使うなら、通常はループバックアドレスで十分です。Windows、macOS、Linuxではファイアウォール通知やネットワーク権限の表示が異なりますが、判断原則は共通しています。まずコアが想定したアドレスを実際にリッスンしていること、次に接続元の機器がそのアドレスとポートへ到達できることを確認してください。

sniffingがルーティングを支援する仕組み

トラフィック検出sniffingは、接続内容から宛先ドメインを識別する機能です。主な識別元にはHTTP Host、TLS Server Name、QUICで確認できる宛先情報があります。アプリが先にドメインをIPへ解決し、プロキシにはIPだけを渡す場合、ルーティングから見えるのはIPだけなので、geositeやドメインサフィックスのルールに一致できません。検出を有効にすると、識別したドメインをルーティングに利用でき、ドメインルールへより安定した入力を提供できます。

destOverrideは、どのプロトコル特性から宛先情報を上書きまたは補完できるかを指定します。一般的な値はhttptlsquicです。routeOnlytrueにすると、検出結果は主にルーティング判断に使われ、最終的な接続先を直接書き換えません。これにより、宛先置換による副作用を抑えられます。有効にするかどうかはルール設計に合わせて判断してください。IPルールだけを使うなら効果は限定的ですが、geosite、完全一致ドメイン、サフィックスルールを多用する場合は、通常より有用です。

検出は汎用的な復号機能ではなく、すべての接続を識別できるわけでもありません。暗号化されたアプリプロトコル、標準外のハンドシェイク、IPへの直接アクセス、先に確立された多重化接続では、利用可能なドメインが得られないことがあります。すべての接続で必ず検出ドメインが得られると考えず、適切なIPルールとデフォルト出口を残してください。ドメインルールに時々一致しない場合は、ログレベルを一時的にinfoへ変更し、アプリの元の宛先、検出結果、最終的な送信タグを比較します。診断後はwarningへ戻し、ログが長期的に増えすぎないようにしてください。

複数の受信は、異なるタグと組み合わせてルーティングできます。たとえばブラウザーをbrowser-in、開発ツールをdev-inへ向け、inboundTagで2種類のリクエストに異なる出口を選ばせます。プロセス名での一致よりもクロスプラットフォームで再利用しやすい方法ですが、各アプリが独立したプロキシポートを設定できることが前提です。v2rayNのシステムプロキシモードを使う場合、通常はクライアントが生成した標準受信だけで十分です。カスタム入口を追加するのは、明確な分離が必要な場合に限ってください。

03

outbounds(送信):プロトコルパラメータ、タグ、トランスポート層

送信配列とデフォルト出口

outboundsは、接続がコアから外へ出る際の処理方法を定義します。プロキシプロトコルの送信はリモートサーバーへ接続し、freedom送信は宛先へ直接アクセスし、blackhole送信は一致した接続を終了します。実運用では、proxydirectblockという意味の明確なタグを少なくとも用意し、ルーティングでプロキシ、直接接続、遮断を個別に表現できるようにします。タグ名は自由に決められますが、ルールのoutboundTagとは大文字小文字を含めて完全に一致させる必要があります。

ルーティングルールに一致しなかった場合の出口は、コアの動作とクライアントの生成方式を組み合わせて判断します。多くの設定では主要なプロキシ送信を配列の先頭に置き、未一致トラフィックのデフォルト経路にしています。一方、クライアントが追加のフォールバックルールを生成する場合もあります。実際の実行設定を読むときは、画面に表示されたサーバーだけでなく、送信の順序とルーティング末尾にcatch-allルールがあるかも確認してください。動作を明確にしたい場合は、末尾にネットワーク範囲を網羅するフォールバック条件を追加できますが、広すぎるルールがすべてのトラフィックを先取りしないよう注意が必要です。

{
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "server.example.com",
            "port": 443,
            "users": [
              {
                "id": "11111111-1111-4111-8111-111111111111",
                "encryption": "none",
                "flow": "xtls-rprx-vision"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "serverName": "www.example.com",
          "fingerprint": "chrome",
          "publicKey": "dGVzdC1wdWJsaWMta2V5LWZvci1kb2N1bWVudA",
          "shortId": "0123456789abcdef",
          "spiderX": "/"
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {
        "domainStrategy": "UseIP"
      }
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {
        "response": {
          "type": "none"
        }
      }
    }
  ]
}

上記のプロキシパラメータには、ドキュメント用の例示アドレスとサンプル認証情報を使用しています。フィールド階層を示すためだけのもので、実際の接続には使えません。実際の設定では、アドレス、ポート、ユーザー識別子、トランスポート方式、セキュリティ層のパラメータを一組として整合させる必要があります。サブスクリプションのインポートでは通常これらのフィールドが自動生成されますが、手動で調整するときにプロトコル名だけを見て1つの値だけ置き換えないでください。同じプロトコルでもTCP、WebSocket、gRPC、TLS、REALITY、異なるフロー制御方式を組み合わせる場合があります。

protocol設定とstreamSettingsの役割分担

protocolはアプリケーション層のプロキシプロトコルを決め、settingsにはそのプロトコルに必要なサーバー情報とユーザー情報を保存します。streamSettingsは下位のトランスポートネットワークとセキュリティ層を定義します。VLESSを例にすると、サーバーアドレス、ポート、ユーザー識別子はsettings.vnextに、TCP、WebSocket、gRPCはstreamSettings.networkに、TLSやREALITYはstreamSettings.securityに記述します。これらの階層は関連していますが、場所を入れ替えることはできません。

VMess、VLESS、Trojan、Shadowsocksではユーザーフィールドの構造が異なります。VMessではidやセキュリティ設定、VLESSではid、encryption、場合によってはflow、Trojanではパスワード、Shadowsocksでは暗号化方式とパスワードを使います。クライアントのサブスクリプションを利用すると手入力のミスを減らせますが、インポート後もプロトコル、トランスポート種別、TLSサーバー名、ポートが揃っているか確認してください。サブスクリプションの更新に失敗したり共有リンクの形式に問題がある場合は、サブスクリプション更新失敗のセルフチェックリストに沿って確認できます。

muxの多重化は、複数の論理接続で少数の下位接続を共有する機能です。どの環境でも有効にすべき速度向上スイッチではなく、効果はプロトコル、トランスポート、サーバー設定、通信内容によって異なります。長時間接続や時系列に敏感なリクエストには、追加の多重化が適さない場合があります。接続確立は正常なのに継続転送が不安定なら、プロトコルやセキュリティ層、ルーティングを同時に変えるのではなく、Muxだけを無効にして比較してください。

direct、blockと出口の制約

freedom送信は宛先へ直接接続し、プライベートアドレス、ローカル地域のドメイン、またはローカルネットワークで処理したいことが明確なリクエストによく使われます。ただし、本機のDNS、ネットワークルーティング、ファイアウォールの影響は受けます。そのため「direct」はプロキシプロトコルを経由しないという意味であり、宛先へ必ず到達できることを保証するものではありません。settings.domainStrategyは、freedomがドメインに遭遇した際の解決方法を制御します。トップレベルDNSやroutingのドメイン戦略と整合させ、同じドメインが段階ごとに異なる結果にならないようにしてください。

blackholeは宛先への通常の接続を確立せず、不要と判断したドメイン、IP、ポートの遮断に適しています。遮断ルールはできるだけ具体的にし、優先して実行したい位置へ置いてください。条件が広すぎると、更新、ログイン、LANサービスがタイムアウトすることがあります。デバッグ時は疑わしいルールの出口を一時的にdirectまたは専用タグへ変更し、ルールが原因か確認してから本来の動作へ戻します。

設定によってはsendThroughで送信接続の送信元ローカルアドレスを指定したり、sockoptで下位ソケットオプションを調整したりします。これらは複数NIC、特定のルーティングテーブル、高度なネットワーク環境向けの項目で、一般的な接続障害の最初の対処には向きません。指定したアドレスが本機のインターフェースに割り当てられていなければ、送信は直接失敗します。デスクトップではまずクライアントのデフォルト値を使い、対象NIC、アドレスファミリー、ルーティング要件を明確に説明できる場合だけバインドを追加してください。

送信の役割 主なprotocol 主な用途 主な確認ポイント
プロキシ出口 vless、vmess、trojan、shadowsocks リモートプロトコルで接続を確立 アドレス、ポート、ユーザーパラメータ、トランスポート、セキュリティ層が一致しているか
直接接続 freedom ローカルネットワークで宛先へアクセス 本機のDNS、デフォルトルート、ファイアウォール、アドレスファミリー
接続の遮断 blackhole 一致したルールのリクエストを終了 ルールの範囲と順序が広すぎないか

送信を管理するときは、まずタグを安定させてください。ルーティングルールが参照するのは配列位置ではなくタグなので、安定したタグを使えばサーバーパラメータの更新とルーティング方針を切り離せます。サブスクリプションのノードを切り替えると、クライアントがプロキシ送信を再構築することがありますが、directとblockの意味は通常変わりません。クライアントが変更する可能性のある内部タグをカスタム設定から参照している場合は、更新のたびに実際の生成結果を確認し、ルールが存在しない出口を指さないようにしてください。

04

routing(ルーティング)ルール:照合順序、ドメイン、IPの振り分け

ルールは順番に照合される

routing.rulesはルーティングルールの配列です。よく使われるルールタイプはfieldで、ドメイン、IP、ポート、ネットワーク種別、受信タグ、プロトコル、ユーザーなどの条件を組み合わせられます。ルールは上から下へ確認されるため、より具体的で優先度の高い条件を前に、範囲の広いルールを後ろに置きます。1つのルールに一致すると、通常は後続の代替ルールを探しません。つまり順序そのものがポリシーの一部です。

同じfieldルール内の異なる条件は、通常「すべて満たす」関係になります。たとえばdomainportを同時に指定すると、ドメイン条件とポート条件の両方を満たした場合だけその出口を使います。一方、同じ配列内に複数のドメイン値を入れた場合は、通常「いずれかに一致する」関係です。関係のない条件を1つのルールに詰め込むと、条件が独立していると誤解しやすくなります。業務上の目的ごとにルールを分け、各ルールに説明可能な一致理由を1つだけ持たせると明確です。

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "domainMatcher": "hybrid",
    "rules": [
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn",
          "domain:example.cn",
          "full:service.example.cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": ["geoip:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:category-ads-all"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

この例では、まずプライベートIP、次に指定ドメインと地域ドメイン、その後に地域IPを処理し、続いて特定カテゴリを遮断し、最後に残ったTCPとUDPのリクエストをproxyへ渡します。実際に遮断ルールを地域の直接接続より前に置くべきかは、カテゴリデータと対象ポリシーによって異なります。同じドメインが2つの集合に属する場合は、前にあるルールが制御権を持ちます。順序を変更する前に、ルール名だけで判断せず、重複する可能性のある集合を列挙してください。

domainStrategyは解決のタイミングを決める

domainStrategyは、ドメインルールで直接結果が得られない場合に、ルーティングモジュールがドメインをIPへ解決してIPルールを再試行するかどうかを制御します。AsIsは通常、現在の宛先形式だけを使い、ドメイン宛てをIPルールに一致させるために自動解決しません。IPIfNonMatchはまずドメインルールを試し、一致しなければIPを解決してIPルールを確認します。IPOnDemandはルーティング中に、より積極的にIP結果を準備します。具体的な動作はコアの実装や設定の組み合わせにも左右されますが、選択の原則は明確です。ドメイン宛てをgeoipやCIDRルールに参加させる必要がある場合だけ、ルーティング段階で解決を導入します。

解決にはコストもあります。DNSクエリが増え、解決サーバー、キャッシュ、アドレスファミリーによってルーティング結果が変わる可能性があります。重要な宛先をgeosite、完全一致ドメイン、サフィックスルールでカバーできるなら、AsIsの方が理解しやすいでしょう。geoip:cnや独自CIDRでドメイン宛てを振り分けるなら、通常はIPIfNonMatchが適しています。テンプレートが特定の値を使っているからという理由だけで流用せず、ルールにIP条件があるか、アプリがドメインを送信するかを基準に選んでください。

sniffingを有効にすると、トラフィックから識別したドメインをルーティングで利用できる場合があります。無効なら、アプリがIPを送信したときにドメインルールの照合対象がありません。逆にアプリがドメインを送信した場合、IPルールを使うかどうかはdomainStrategyに左右されます。つまり受信側の検出、ルーティングのドメイン戦略、DNSは独立した3つのスイッチではありません。ルールを調べるときは、最初のリクエストがドメインかIPか、検出でドメインが得られたか、ルーティングが解決を実行したか、最終的にどのIPを得たかを記録してください。

ドメイン、IP、ポート、タグの条件

ドメインルールでは、full:domain:regexp:geosite:がよく使われます。full:example.comは完全一致のドメインだけに一致し、domain:example.comはそのドメインとサブドメインを対象にできます。正規表現は柔軟ですが、複雑になるほど可読性が下がり、意図しない一致も起きやすくなります。geositeはカテゴリデータの集合を使うため、広い範囲を管理するのに適しています。明確な単一サイトにはfullまたはdomainを優先し、集合が大きい場合だけカテゴリデータを使うとよいでしょう。

IPルールには192.168.0.0/16のようなCIDRや、geoip:privateなどのデータ集合を指定できます。プライベートアドレスのルールは通常、早い段階で直接接続へ振り分けます。そうしないと、LANの管理画面、ファイルサービス、ローカル開発環境がプロキシ出口へ送られることがあります。ドメインがプライベートアドレスへ解決された場合にこのルールへ一致するかは、ルーティングが解決を実行したかどうかにも依存します。privateルールを追加するだけで、すべてのLANドメイン問題が解決するわけではありません。

portには単一ポート、カンマ区切りのリスト、範囲を指定でき、networkではtcpudp、または両方の組み合わせがよく使われます。ポートは接続先のポートを示すだけで、アプリの種類と同じではありません。多くのサービスが443を共有するため、ポートだけでドメインを判断することはできません。53もさまざまな形式のDNSリクエストに使われます。ポートルールは明確なネットワーク方針の表現に適しており、ドメイン識別の代わりにはなりません。

inboundTagを使うと、リクエストがどの受信から来たかで振り分けられます。複数のローカルポートを分離する際に便利です。protocol条件は、検出後に特定プロトコルとして識別された場合など、コアの認識結果に依存します。こうした高度な条件を使うときは、未識別のトラフィックに出口がなくならないよう、末尾にフォールバックルールを残してください。ルーティングを変更したら、少なくともプライベートIP、明確な直接接続ドメイン、明確なプロキシドメイン、未分類の一般ドメイン、UDPリクエストの5ケースをテストし、実際の送信タグを確認します。

v2rayNのルーティング設定画面では通常、プリセット、ルールセット、現在のプロキシモードを組み合わせて最終設定を生成します。画面で「グローバル」などのモードを選ぶと、デフォルト出口が変わったり、追加ルールが生成されたりするため、手動の設定断片とクライアントモードを一緒に確認してください。各プロトコルとルーティングシナリオの選択を理解したい場合は、VMess、VLESS、Trojan、Shadowsocksのプロトコル比較も参照してください。

05

DNS設定:解決サーバー、照合ドメイン、アドレスファミリー

内蔵DNSとシステムDNSの境界

トップレベルのdnsモジュールは、コアが実行するドメイン解決のためのサーバー、静的マッピング、クエリ方針を定義します。端末上のすべてのDNSリクエストを自動的に引き受けるわけではありません。コアの処理経路に入り、ルーティングモジュールから解決を要求されたクエリや、特定のDNS受信からコアへ渡されたクエリだけが、ここでの設定を使います。アプリが外部の解決サービスへ直接接続する場合、ブラウザーが独自のセキュアDNSを使う場合、リクエストがプロキシを完全に迂回する場合は、トップレベルのdns設定が関与しないことがあります。

この区別はトラブルシューティングで重要です。あるドメインの解決結果が設定の想定と違うときは、まず誰がクエリを発行したのかを確認します。OSのリゾルバーか、アプリ独自のリゾルバーか、それともXray内蔵DNSかを切り分けてください。システムDNS、ブラウザー設定、コアのサーバーリスト、ルーティングルールを同時に変更すると、結果が変わってもどの層が効いたのか判断できません。まずアプリ独自の解決機能を無効にして比較し、ログでコアがクエリを送信したか確認するのがおすすめです。

{
  "dns": {
    "hosts": {
      "domain:internal.example": "192.168.10.20",
      "full:router.example": "192.168.1.1"
    },
    "servers": [
      {
        "address": "1.1.1.1",
        "port": 53,
        "domains": [
          "geosite:geolocation-!cn"
        ],
        "skipFallback": true
      },
      {
        "address": "223.5.5.5",
        "port": 53,
        "domains": [
          "geosite:cn"
        ],
        "expectIPs": [
          "geoip:cn"
        ]
      },
      "localhost"
    ],
    "queryStrategy": "UseIP",
    "disableCache": false,
    "disableFallback": false,
    "disableFallbackIfMatch": true
  }
}

この例ではdomainsで各解決サーバーの適用範囲を限定し、後続の選択肢としてlocalhostを残しています。公共の解決アドレス、システムリゾルバー、その他の転送方式が必要かどうかは、利用するネットワークと対象環境に応じて判断してください。サーバーの順序、照合ドメイン、fallbackの有効化は最終的な選択に共同で影響するため、serversを単純な順番待ちリストと考えてはいけません。

servers、hosts、クエリ方針

serversには文字列形式とオブジェクト形式の両方を使えます。オブジェクト形式では、ポート、照合ドメイン、期待するIP範囲、fallback動作を追加できます。domainsは、どのドメインをそのサーバーで優先処理するかを指定し、書式はルーティングのドメインルールに似ています。expectIPsは、返されたアドレスが想定範囲に合うかを判定するもので、任意のアドレスを特定地域へ強制変換する機能ではありません。設定を誤ると、正常な結果まで拒否されて後続クエリへ回されることがあります。

hostsは静的なドメインマッピングを提供し、固定したLANサービスや明確なテスト対象に適しています。大規模なhostsファイルの代替ではなく、項目が増えすぎると保守負担も高まります。完全一致のドメインにはfull:を使い、サブドメインまで対象にする場合はdomain:を使います。プライベートアドレスへマッピングした後は、routingのprivateルールが接続をdirectへ送ることも確認してください。解決が正しくても、出口の選択が想定外になる可能性があります。

queryStrategyは、どの種類のアドレス結果を使うかを制御します。一般的にはIPv4とIPv6の両方を許可する、IPv4のみ、IPv6のみといった方針がありますが、具体的な名称は現在のコアがサポートするフィールドに従ってください。片方のアドレスファミリーだけを選ぶ前に、ローカルネットワークとリモートサービスがその経路に対応しているか確認します。本機にIPv6アドレスがあっても出口が不安定なら、ドメインがIPv6を優先して返した結果、接続に失敗することがあります。逆にIPv4を強制すると、IPv6のみを提供する宛先へ到達できません。端末に特定のアドレスが表示されるかだけでなく、解決結果と実際のルーティングを分けてテストしてください。

fallback、キャッシュ、ルーティングの循環

fallback機構は、優先した解決結果が条件を満たさない、または結果がない場合に、別のサーバーを試すためのものです。skipFallbackは特定のサーバーを通常のフォールバックから除外し、disableFallbackは全体のフォールバックを無効化し、disableFallbackIfMatchはドメインが特定サーバーに一致した場合に継続フォールバックを制限します。複数のスイッチを重ねると、「サーバーを設定したのに一度も呼ばれない」状態になりやすいため、まず単一サーバーが動くことを確認し、その後にドメイン範囲とフォールバック制限を追加してください。

キャッシュは重複クエリを減らせますが、設定を変更しても短時間は結果がすぐ変わらないことがあります。disableCacheは短期的な診断に適していますが、1度古い結果が出たからといって常時無効にするのはおすすめしません。トラブルシューティングでは、OSやアプリ自身のキャッシュも考慮してください。これらはコアのキャッシュとは独立しています。コアを再起動しても、ブラウザーやシステムのDNSキャッシュまで消えるとは限りません。

DNSとルーティングは循環的に関係します。ルーティングがIPルールに一致させるためにDNSクエリを発行する一方、DNSサーバーへの接続もルーティングを通るためです。解決サーバーのアドレスがドメインで、その接続前に同じドメインを解決する必要があると、依存関係が長くなったり循環したりします。基本の解決サーバーには明確なアドレスを使うか、そのドメインがシステムリゾルバーで安定して解決できるようにしてください。DNSクエリを特定の出口へ送る場合は、タグとルールを明確に構成し、そのルールが同じ解決経路を再び呼び出さないようにします。

典型的な問題は「ドメインルールは正しそうなのに、最終的に誤った出口へ進む」ことです。確認順序は次のとおりです。アプリはドメインとIPのどちらを送ったか、sniffingはドメインを識別したか、ドメインルールに先に一致したか、domainStrategyは解決を実行したか、DNSはどのサーバーを使ったか、IPv4・IPv6のどちらまたは両方が返ったか、IPルールはその結果を対象にしたか、最終的な送信タグは何か。この経路を1つずつ記録すれば、問題は通常、明確な1つの段階に絞り込めます。

フィールド 役割 適した用途 よくある誤解
hosts 静的なドメインマッピングを提供 LANサービスと固定したテスト対象 すべてのアプリのシステム解決を書き換えると思い込む
domains 解決サーバーの照合ドメインを限定 ドメイン集合に応じて解決経路を選択 サーバーの順序とfallback条件を無視
expectIPs 範囲に合う解決結果を選別 返されたアドレスの範囲を判定したい場合 固定アドレスのマッピングだと思い込む
queryStrategy クエリで使うアドレスファミリーを制御 IPv4とIPv6の経路差を処理 ネットワーク対応を確認せず単一アドレスファミリーを強制

v2rayNGとv2flyNGはAndroidのネットワーク環境で動作するため、システムのプライベートDNS、アプリ内の解決、クライアントのコアDNSが同時に存在する場合があります。判断方法はデスクトップと同じです。まずリクエスト経路を明確にし、次にどの層が解決を担当したかを確認してください。システム設定のDNS項目と、設定ファイルのトップレベルdnsフィールドを同じスイッチと考えないでください。

06

policy(ポリシー):接続タイムアウト、ユーザーレベル、統計

levelポリシーとユーザーの関連付け

policyは接続のライフサイクル、ユーザーレベル、システム統計の動作を設定します。サーバーの選択やルーティング出口の変更は担当しません。levelsオブジェクトでは、レベル番号をキーとして、ハンドシェイクのタイムアウト、アイドルタイムアウト、上りまたは下りの一方向だけが残った場合の接続保持時間、ユーザートラフィック統計の有効化を設定できます。プロトコルのユーザー項目にあるlevelが、ここにあるレベルキーと関連付けられます。ユーザーが明示的に指定しない場合は、通常デフォルトレベルが使われます。

レベルはサービス品質のスコアではなく、帯域幅の優先順位を自動的に提供するものでもありません。対応するユーザーへ一組のポリシーパラメータを適用するための仕組みです。デスクトップクライアントを単一ユーザーのローカルツールとして使う場合、一般的にはレベル0だけで十分です。サーバーのマルチユーザー設定ではユーザーごとに異なるレベルを割り当てることもありますが、このページの主眼はクライアントの実行設定です。「性能最適化」のためだけに多くのレベルを追加せず、実際のユーザーオブジェクトがそれらを参照しているか先に確認してください。

{
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "uplinkOnly": 2,
        "downlinkOnly": 5,
        "statsUserUplink": false,
        "statsUserDownlink": false,
        "bufferSize": 4
      }
    },
    "system": {
      "statsInboundUplink": false,
      "statsInboundDownlink": false,
      "statsOutboundUplink": false,
      "statsOutboundDownlink": false
    }
  },
  "stats": {}
}

数値の単位と許容範囲は、現在のコアにおけるフィールド定義を基準にしてください。例は一般的な構造を示すもので、すべてのネットワークに同じタイムアウトが適するわけではありません。ハンドシェイク時間が短すぎると、高遅延ネットワークで接続が完了する前に終了します。長すぎると、失敗した接続がより長くリソースを占有します。アイドルタイムアウトも「長いほど安定する」と単純に考えないでください。活動のない接続を大量に保持するとリソース消費が増えます。

ハンドシェイク、アイドル、一方向接続のタイムアウト

handshakeは接続確立段階で待機できる時間を制御します。リモートへ到達できない、ドメイン解決が遅い、セキュリティ層のパラメータが一致しないといった問題で、この時間を使い切ることがあります。ログにハンドシェイクタイムアウトが続く場合は、数値を大きくする前にアドレス、ポート、トランスポート、ネットワーク到達性を確認してください。ネットワーク経路が遅くても最終的に接続できることを確認した場合に限り、適度に延長します。

connIdleは、上り下りの通信がない接続をどれだけ保持するかを制御します。Webの短時間接続では長いアイドル時間を必要としないことが多い一方、メッセージ同期、リモートターミナル、ロングポーリングではしばらく目立った通信がない場合があります。特定のアプリが一定のアイドル時間後に切断されるなら、アプリのハートビート間隔とconnIdleを比較してください。同時に、リモートサーバー、トランスポート層、中間ネットワーク機器も確認します。どの層も接続を能動的に閉じる可能性があるためです。

uplinkOnlydownlinkOnlyは、一方向の通信だけが残った状態を処理します。一方の方向が終了した後、コアは接続全体をすぐ閉じず、もう一方の完了を待ちます。値が短すぎると送信途中のデータが切り捨てられ、長すぎるとリソース解放が遅れます。通常のクライアントではコアまたはクライアントが生成する妥当なデフォルト値を使い、ログと取得した接続状態が一方向切断を明確に示す場合だけ調整してください。

bufferSizeは接続バッファに関係します。バッファを大きくしても必ず速度が上がるわけではなく、接続ごとのメモリ使用量も増えます。低性能な機器、大量の同時接続、大容量ファイル転送では必要なバッファが異なります。最適化では一度に1つの値だけを変更し、メモリ、接続の安定性、実効スループットの変化を確認してください。サーバーの高並列環境向けパラメータを、通常のデスクトップクライアントへそのまま適用しないでください。

統計スイッチと実行コスト

statsUserUplinkstatsUserDownlinkはユーザーレベルの上り下り統計を制御し、system配下のフィールドは受信と送信方向の統計を制御します。トップレベルのstatsは統計モジュールを有効にしますが、空のオブジェクトを置くだけで全ての次元のデータが自動生成されるわけではありません。対応するpolicyスイッチと、統計を読み取るインターフェースも必要です。v2rayNの画面に統計が表示されるかどうかは、クライアントがコアをどう起動し、データをどう読み取るかにも左右されます。

統計が不要なら、関連スイッチを無効のままにして余分な状態管理を減らせます。特定の受信や送信でトラフィックが発生しているか確認したい場合は、対象の次元を短時間だけ有効にできます。ただし、トラフィックの変化を接続品質と直接同一視してはいけません。統計はデータがある方向を通過したことを示すだけで、ドメインルール、DNS結果、リモートアプリの応答が完全に正しいことまでは証明しません。診断にはログと明確なテストリクエストを組み合わせる必要があります。

policyモジュールでよくある誤解は、接続障害をタイムアウト値のせいにすることです。実際には、プロトコルパラメータの誤り、DNSが返した到達不能なアドレス、誤ったルーティング出口、ポート競合の方が一般的です。まず構造の読み込み、受信リスニング、ルール一致、送信ハンドシェイクを確認し、その後に接続がライフサイクルポリシーで早期終了したかを判断してください。接続が確立済みで、再現可能な一定時点に終了していることをログが示す場合に限り、policyを重点的に確認します。

Windows、macOS、Android、Linuxではフォアグラウンドとバックグラウンドのネットワーク動作が異なります。特にモバイル機器では、アプリがバックグラウンドに入るとネットワーク活動が制限されることがあります。こうしたシステムレベルの動作は、connIdleを延ばすだけでは解決できません。v2rayNGやv2flyNGがバックグラウンドで停止するなら、まずシステムによるアプリのネットワーク利用やバッテリー使用の制限を確認してください。v2rayNがデスクトップで起動直後に終了する場合は、ポート、設定解析、コア起動ログを先に確認します。

policyは、設定が安定した後の細かな調整に適しており、初回接続に必須のモジュールではありません。シンプルなクライアント設定なら、デフォルトポリシーだけで十分です。長時間接続、統計、リソース使用について明確な要件がある場合にだけ、明示的なpolicyを追加してください。フィールドが少ないほど、コアのアップグレードやクライアント移行時に保守すべき互換性のポイントも減ります。

07

設定の検証、ログの読み方、体系的なトラブルシューティング

まず解決・起動・接続の段階を分ける

設定の問題は、まず3つの段階に分けます。第1段階はJSON解析です。括弧の不整合、ダブルクォートの不足、末尾カンマ、フィールド型の誤りがあると、設定を読み込めません。第2段階はコアの起動です。ポート競合、無効なリスニングアドレス、未対応のモジュールフィールドがあると、プロセスは正常な実行状態へ移行できません。第3段階はリクエスト処理です。サーバーパラメータ、DNS、ルーティング、セキュリティ層、ネットワーク環境の問題は、通常アプリがリクエストを送った後に発生します。段階を分けることで、JSON構文エラーの際にサーバーを何度も変えたり、リモートハンドシェイク失敗時にローカルポートを誤って調べたりすることを防げます。

GUIクライアントで「起動中」と表示されても、プロセスが動作している可能性を示すだけです。ローカルポートがリッスンしているか、システムプロキシが正しいポートを指しているか、アプリが実際にリクエストを送っているか、最終的にどの送信を選んだかまで確認してください。v2rayNのパラメータ設定では、Coreタイプ、ローカルSOCKSリスニングポート、LAN接続許可、sniffing、Mux、ログレベル、システムプロキシモードを確認できます。v2rayNGとv2flyNGでは、現在の設定、接続モード、システムネットワーク権限を確認します。

JSONを直接編集する場合は、まずローカルのJSON解析ツールで構文を確認できます。ただし、実際のサーバーパラメータを含む完全な設定を、管理されていないオンラインツールへ送信しないでください。ローカルエディターのJSON構文サポートを使うか、コアにテスト設定としてファイルを読み込ませる方が安全です。コアやインストール方式によってコマンド引数は異なるため、実際にクライアントが呼び出す方法を基準にし、別のプログラムの引数をそのまま流用しないでください。

{
  "log": {
    "access": "",
    "error": "",
    "loglevel": "warning",
    "dnsLog": false
  }
}

warningは日常運用に適しており、出力を増やしすぎず主要な異常を残せます。ルールやDNSを追跡するときは、短時間だけinfoへ切り替え、診断後に出力の少ない設定へ戻してください。ログには宛先ドメイン、アドレス、接続時刻などの実行情報が含まれる場合があります。共有前に、問題と関係のない機密情報を削除してください。最後のエラー1行だけを切り取るのではなく、その前の解決、ルール、ハンドシェイク情報も確認しましょう。

データ経路に沿って順番に切り分ける

第1段階は受信の確認です。クライアントに表示されるSOCKSまたはHTTPポートとアプリの設定が一致し、ポートが他のプログラムに使用されておらず、リスニングアドレスが本機またはLANでの利用方法に合っていることを確認します。まずはプロキシ設定に明確に対応するアプリでテストし、システムプロキシ、ブラウザー独自の設定、アプリがプロキシを無視する可能性を同時に持ち込まないようにしてください。アプリがローカルポートへ接続できない段階では、リモートプロトコルを調べる必要はありません。

第2段階はルーティングの入力を確認します。アプリがドメインとIPのどちらを送ったか、sniffingが有効か、対象プロトコルを識別できるかを記録してください。その後、rulesの先頭から条件を確認し、期待するルールだけを見ないようにします。特に、全ポート、全ネットワーク、大きなドメイン集合を対象にする、より前方の広範囲ルールを探します。一致を確認したら、outboundTagが存在し、綴りも一致しているか確認します。

第3段階はDNSの確認です。ドメインルールに直接一致している場合、DNSは送信の接続先を決めるときだけ使われることがあります。geoipルールに依存している場合は、routingが先に宛先を解決する可能性があります。どの解決サーバーを使ったか、どの種類のアドレスが返ったか、fallbackが結果を変えたかを確認してください。完全なドメインと、解決後の単一IPを分けてテストすると切り分けやすくなります。ドメインだけ失敗してIPが成功するならDNSとドメインルールを重点的に、両方失敗するなら出口とネットワーク到達性を確認します。

第4段階は送信の確認です。プロキシプロトコルのアドレス、ポート、ユーザーパラメータ、トランスポート方式、セキュリティ層、サーバー名は一組として一致していなければなりません。サブスクリプションのインポート後にフィールドが欠けている場合は、まずサブスクリプションを更新し、クライアントがその共有形式に対応しているか確認します。REALITYとXTLS Visionなどの組み合わせは、Xrayコアと一致するリモートパラメータに依存します。詳しくはREALITYとXTLS Visionのハンドシェイクおよびフロー制御を参照してください。flow、fingerprint、serverNameを推測で1つずつ置き換えると、元の問題を再現できなくなるため避けてください。

第5段階はシステム経路の確認です。システムプロキシは、その設定に従うアプリにだけ影響し、端末上のすべての接続がローカル受信を通ることを意味しません。あるアプリは動作するのに別のアプリが直接接続する場合は、まず後者がシステムプロキシに対応しているか確認します。Windows、macOS、Linuxではプロキシ設定の入口が異なり、Androidクライアントは通常、システムが提供するネットワーク接続機能を通じてトラフィックを処理します。プラットフォーム別のインストールとクライアント選びはクライアント比較を参照してください。

症状 優先して確認する項目 次の手順
コアが起動しない JSON構文、フィールド対応、ポート競合 最小構成へ戻し、モジュールを段階的に追加
アプリがローカルプロキシへ接続できない リスニングアドレス、ポート、アプリのプロキシ種別 SOCKSとHTTPの設定を混同していないか確認
一部ドメインの出口が誤っている ルール順序、sniffing、domainStrategy ドメイン入力とIP入力で一致結果を比較
ドメインは失敗するがIPは接続できる DNSサーバー、hosts、アドレスファミリー fallbackとアプリ独自の解決を確認
接続確立後、一定時間で切断される connIdle、一方向タイムアウト、システムのバックグラウンド制限 ログの確立時刻と切断時刻を比較

最小構成と二分法による復元

設定を何度も変更して、どの部分が原因か分からなくなった場合は、最小構成へ戻すのが最も効果的です。ローカルSOCKS受信を1つ、パラメータが完全であることが分かっているプロキシ送信を1つ、direct送信、単純なフォールバックルールだけを残し、カスタムDNS、複雑なルーティング、統計、policyは一時的に削除します。最小構成で動作したら、モジュール単位で順番に戻し、関連するフィールドを1組追加するたびに固定したテストを行ってください。

ルールが多い場合は二分法を使えます。まずカスタムルールの半分を無効にしてテストし、問題が消えれば原因は無効にした側にあります。問題が残るなら、保持した側または別のモジュールにあります。範囲をさらに絞れば、ルールを無作為に1つずつ移動するより速く特定できます。DNSサーバーリストやhostsマッピングにも同じ方法を使えます。各テストではサーバー、アプリ、対象ドメイン、ネットワーク環境を変えないでください。そうしないと結果を比較できません。

安定した設定には、クライアントの種類、Coreタイプ、受信ポート、送信タグ、ルーティングルールの目的、DNSを選んだ理由、調整したpolicyフィールドを含む構造化された記録を残すことをおすすめします。設定そのものを保存するだけでなく、理由を記録することが重要です。データ集合、ネットワーク環境、クライアントの生成ロジックが変わると、古いルールが適用できなくなることがあるためです。用途を説明できなくなった例外ルールは定期的に削除し、追加するばかりで変更できない設定になるのを防いでください。

GUIクライアントでサブスクリプションを更新したりコアを切り替えたりした後は、カスタムフィールドが最終的な実行設定へ引き続き書き込まれているか再確認してください。v2rayNのAvaloniaデスクトップ版とWindows WPF版では、画面とプラットフォーム対応に違いがありますが、基本的なトラブルシューティング経路は共通しています。詳しい選択はv2rayNデスクトップ版とWPF版の違いを参照してください。macOSの初回起動やネットワーク権限に問題がある場合は、macOSのインストールとネットワーク権限の対処手順を確認できます。

エラーメッセージを分類できない場合は、トラブルシューティングで基礎知識、インストールと設定、活用方法、トラブルシューティングの分類から引き続き確認してください。質問や記録を作成するときは、「使えない」とだけ書かず、再現手順、クライアント名、OS、コアの種類、関連する設定断片、必要な情報を整理したログを含めます。実際のデータ経路に近い情報ほど、障害が受信、ルーティング、DNS、送信、システムネットワークのどこにあるか判断しやすくなります。

設定ファイルの目的は、できるだけ多くのフィールドを積み重ねることではなく、各接続の処理を予測可能にすることです。まずクライアントが生成したデフォルト構造で動作する基準を作り、明確な要件に応じてルーティング、DNS、ポリシーを追加します。変更ごとにテストケースと復元手順を残してください。これにより、v2rayN、v2rayNG、v2flyNGのGUI管理機能を活用しながら、問題発生時には実行設定を直接読んで該当モジュールを特定できます。

v2rayN をダウンロード