JSON · inbounds · outbounds · routing · dns · policy

V2Ray設定ファイルの解説

通信の入口・出口とルールの適用順に沿って項目を確認し、クライアント設定とコアの実行設定を区別します。

このページは設定を体系的に確認するためのガイドです。サブスクリプションをインポートでき、設定ファイルの内容を理解したい方向けです。初めて利用する場合は、まず使い方ガイドに沿ってインストール、インポート、接続を済ませてから、必要な項目を確認してください。デスクトップではv2rayNをおすすめします。インストーラーと対応プラットフォームはダウンロードをご覧ください。ここではV2FlyとXrayでよく使われるJSON設定構造を扱います。各コア固有の項目を共通形式として混在させることはありません。

1. JSON構造と設定の読み込み範囲

トップレベルのオブジェクトから通信の流れをつかむ

設定ファイルは、コアが接続を受け付け、転送方法を選び、補助機能を処理する方法を定義します。サブスクリプションURLを別の形式で記述したものではありません。アプリの通信はまずinboundに入り、ルーティング機能が宛先や送信元の情報を確認して、選択したoutboundへ転送します。DNS、ログ、policyはそれぞれ異なる段階で処理に関わります。この流れを把握すれば、設定を変更するときに問題の層を切り分けられ、関連して見える複数の項目を一度に変更せずに済みます。

トップレベルによく使われるオブジェクトは、log、inbounds、outbounds、routing、dns、policyです。複数の待ち受け口や出口を設定できるため、inboundsとoutboundsは通常配列で記述します。ルーティングも、適用順を持つルール配列で表します。配列の並びは動作に影響することがありますが、オブジェクト内の項目順は通常意味に影響しません。読みやすく整えることは大切ですが、見た目を整えるためだけにoutboundやルールの順序を変更しないでください。

まずローカルで動く基本設定を用意する

次の完全な設定例は、ローカルのループバックアドレスでSOCKSポートを待ち受け、outboundに直接接続を使用します。コアがファイルを読み込み、ポートをバインドし、ローカルのリクエストを処理できるか確認するためのものです。リモートプロキシのトンネルは作成しません。起動前にクライアントが同じポートを使用していないことを確認し、テストするアプリでこのSOCKS入口を明示的に指定してください。初回の検証をTCPリクエストに絞るため、サンプルではUDPを有効にしていません。ほかの機能は後の章で個別に説明します。

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": false
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    }
  ]
}

JSONの文字列には半角の二重引用符を使い、真偽値はtrueまたはfalse、数値には引用符を付けません。配列やオブジェクトの最後に余分なカンマを付けず、説明文をコード内に直接書き込まないでください。コメントを許可する拡張形式に対応したツールもありますが、エディターで開けるからといってコアが読み込めるとは限りません。ツール間で設定を受け渡す場合は、厳密なJSONを使うと構文の問題を特定しやすくなります。ファイルはUTF-8で保存してください。

項目があっても、現在のコアが対応しているとは限らない

V2FlyとXrayには共通する設定の経緯がありますが、対応プロトコル、トランスポートのオプション、項目の仕様は完全には一致しません。サンプルを参照する前に、実際に動作しているコアを確認し、そのコアの項目定義を照合してください。クライアント画面に項目があるのは、対応する設定画面が用意されているということにすぎません。どのコアでも同じJSONを受け付けるとは限りません。sing-boxは別の設定構造を使うため、このページの例をそのまま設定ファイルとして読み込むことはできません。

「編集したファイル」と「プロセスが読み込んだファイル」も区別してください。GUIクライアントは起動時に実行用の一時設定を生成することがあり、カスタム設定が独立した項目から読み込まれる場合もあります。あるフォルダー内のJSONを保存しても反映されないときは、まず起動ログや設定の詳細を確認し、実際の読み込み先と選択中の項目を特定してください。名前の似たファイルがプログラムのフォルダーにあるからといって、それが有効な設定ファイルだとは限りません。クライアントのデータベースと生成ファイルを同時に編集して、反映されることを期待するのも避けてください。

オブジェクト主な役割確認する項目
inboundsローカル接続を待ち受けて受け付けるアドレス、ポート、プロトコル
outbounds接続の転送方法を定義するプロトコル、宛先、トランスポート設定
routingoutboundを順番に選択するルール条件とタグの参照
dns内蔵の名前解決を設定するサーバーと名前解決の経路
policy接続と統計に関するpolicyを設定するユーザーレベルとシステム設定

設定ファイルを保守しやすくするには、各設定の範囲を明確にすることが大切です。まず動作する基本設定を保存し、変更は毎回1つのオブジェクトに絞ってください。有効性を確認したら、変更理由と期待する結果を記録します。設定の一部を統合するときは、特にトップレベルの同名項目に注意してください。同じオブジェクトや配列を1つだけ残し、完全な設定ファイルをそのまま2つ連結してはいけません。パーサーが重複キーを受け入れても、値が1つだけ残り、編集時の意図と異なる結果になる可能性があります。

このページでは入口、出口、ルーティング、名前解決、policyの順に説明し、最後にクライアントでの管理と検証手順を紹介します。目次から必要な箇所だけ読んでもかまいませんが、転送の問題が起きた場合は通信の流れに沿って確認してください。まず対象のプロセスに通信が入っているかを確かめてから、ルールにマッチしたかを調べます。入口に通信が届いていない状態でルーティングを変更しても、条件が正しいかどうかは判断できず、確認項目を増やすだけです。

2. inbounds:待ち受け設定と通信の入口

待ち受けアドレス、ポート、プロトコルの役割

inboundsの各オブジェクトは、1つの入口を定義します。listenはバインドするローカルアドレス、portは待ち受けポート、protocolは入口で受け付けるプロトコルを指定します。アプリ側も入口に合ったプロキシ方式を使う必要があります。SOCKS専用ポートにHTTPプロキシのアドレスを入力しても接続できません。ポート番号はローカルでの設定値であり、特定の機能を示すものではありません。設定をコピーするときは、現在のファイルとクライアントに表示されている値を確認してください。

このPCだけで使う場合は、待ち受けアドレスに127.0.0.1を指定します。これはIPv4のループバックアドレスで、ほかの端末から直接アクセスできません。0.0.0.0に変更すると、すべてのIPv4インターフェースで待ち受けることになります。ほかの端末からアクセスするための接続先アドレスではありません。LANからのアクセスを許可するには、ホストアドレス、ファイアウォール、認証なども設定する必要があります。本機の接続エラーを解決するために、待ち受け範囲をむやみに広げないでください。

SOCKSとHTTPの入口を併設する

次の設定例は、第1章のSOCKS入口にHTTP入口を追加し、アプリごとに異なるプロキシ設定を使う場合に適しています。既存の配列にトップレベルの同名項目を追加するのではなく、完全なinbounds配列として置き換えてください。各入口には異なるポートを使い、outboundは共通にできます。ここで使うタグは設定内で参照するためのものです。OSが自動的に認識したり、プロキシを有効にしたりするものではありません。

{
  "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": {}
    }
  ]
}

SOCKS入口のudpは、SOCKS UDP転送リクエストを処理できることを示します。システムプロキシを使うすべてのアプリでUDPが使えるという意味ではありません。アプリ自体が対応機能を使い、outboundのプロトコル、サーバー、ネットワーク経路も対象の通信に対応している必要があります。HTTP入口は主に、HTTPプロキシ設定に従うアプリで使用します。ブラウザーは使えてほかのアプリは使えない場合、宛先ドメインを比べるだけでなく、それぞれのアプリがどの入口を使っているかを確認してください。

tagは短く、一意で、見分けやすい名前にします。ルーティングではinboundTagを使って入口を指定し、ローカルポートごとに異なるoutboundを選択できます。タグ名を変更しても参照先は自動修正されません。名前を変えたら、参照する側も必ず更新してください。更新し忘れると、構文エラーが出ないままルールがマッチしなくなることがあります。各入口がどのアプリ向けかを設定メモに記録しておくと、長期運用後もポート番号だけを見て用途を推測せずに済みます。

スニッフィングは宛先情報を補えるが、名前解決の代わりにはならない

アプリによっては、ドメインをIPアドレスに名前解決してからプロキシリクエストを送るため、ルーティングが受け取る宛先に元のドメイン名が残らないことがあります。sniffingは、対応するアプリケーション層のハンドシェイクからドメイン名を識別し、後続の処理に利用する機能です。よく使われるdestOverrideの値はhttpとtlsです。ただし、すべての通信で有効とは限らず、任意のアプリのデータを復号する機能でもありません。接続先が変更されるかどうかは、使用中のコアの動作も確認してください。

{
  "sniffing": {
    "enabled": true,
    "destOverride": [
      "http",
      "tls"
    ]
  }
}

この設定は個別のinboundオブジェクト内に追加するもので、独立したトップレベルの機能ではありません。有効にする前に、ドメインベースのルーティングを補いたいのか、宛先アドレスの復元を行いたいのかを明確にしてください。アプリのプロトコルが対象外の場合や、識別できる情報がハンドシェイクに含まれない場合は、元の宛先情報やIPルールに頼る必要があります。スニッフィングをあらゆるドメイン振り分けの万能な解決策と考えないでください。設定変更後は、影響を受けるアプリの接続結果を改めて確認します。

ポートのバインドに失敗した場合は、まず重複起動している可能性のあるクライアントを終了し、同じアドレスとポートをほかのプロセスが使用していないか確認します。ポートを何度も変更して、アプリの設定を更新し忘れないようにしてください。待ち受けに成功してもアプリのリクエストが記録されない場合は、アプリ独自のプロキシ設定を使っていないか、ローカルアドレスを迂回していないか、システムプロキシが古いポートを参照していないかを調べます。outboundを確認する前に入口を特定すれば、「接続が届いていない」問題を「リモートが使えない」と誤認せずに済みます。

3. outbounds:プロトコルとトランスポート設定

outboundオブジェクトが実際の転送方法を定義する

outboundsには、直接接続、通信の遮断、リモートプロキシなど、異なるオブジェクトを設定できます。protocolはoutboundのプロトコル、settingsはそのプロトコルに必要なパラメーター、tagはルーティングから参照するタグです。outboundのタグはサーバーアドレスでも、クライアント画面に表示される別名でもありません。別名を変更したときに生成される設定のタグも変わるかどうかは、クライアントの実装によります。実行中の設定を確認するときは、オブジェクトに記述された実際のタグを使い、画面上の名前だけから参照関係を推測しないでください。

ルーティングルールにマッチしない場合、一般的な設定ではoutbounds配列の先頭のオブジェクトが使われます。そのため、配列の順序は単なる表示上の問題ではありません。directオブジェクトを2番目から先頭に移すと、どのルールにも該当しない通信の転送先が変わる可能性があります。挙動を明確にするには、ルーティングの最後に明示的なフォールバックルールを設定できます。その場合も、特にクライアント生成の設定と自分で管理する設定を移行するときは、先頭のoutboundが何を意味するか確認してください。

directとblockの最小設定

次の設定例では2つのoutboundを定義します。freedomはローカルネットワーク経由で宛先に直接接続し、blackholeはマッチした通信を破棄します。どちらもリモートサーバーの情報は必要ありません。この配列は第1章のinboundと組み合わせられますが、ルーティングを追加しない限り、blockオブジェクトが存在するだけで自動的に有効にはなりません。設定オブジェクトは機能を用意し、ルーティングは使う機能を選択します。それぞれの役割を分けて理解してください。

{
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ]
}

リモートプロキシのoutboundには通常、サーバーアドレス、ポート、認証情報、トランスポート設定も必要です。これらは実際のサービス設定に基づいて指定してください。クライアント名から推測することはできません。VMess、VLESS、Trojanでは認証項目が異なり、TLSやWebSocketなどのトランスポート設定も正しい階層に記述する必要があります。多層の設定を一から手作業で組み立てるより、サービス提供元の有効なサブスクリプションやリンクをインポートし、クライアントの生成結果を確認するほうが設定の整合性を保ちやすくなります。

プロトコル、トランスポート、セキュリティ層を個別に確認する

streamSettingsはトランスポートとセキュリティに関する設定を記述します。settingsに含まれるプロトコルの認証情報とは役割が異なります。サーバーが使うトランスポートに合わせて、クライアント側も対応する構造にしてください。パス、ホスト名、セキュリティ設定は一組で一致している必要があります。トランスポート名を別の方式に変更しても、サーバー側が自動的に切り替わるわけではありません。ハンドシェイクに失敗したら、選択肢を手当たり次第に試すのではなく、まずサーバーが要求する組み合わせを確認してからローカルの設定を調べてください。

階層設定する内容よくある誤り
protocoloutboundプロトコルの選択名前が似ていれば置き換えられると思い込む
settingsプロトコル固有のアドレスと認証情報異なるプロトコルの認証構造を混在させる
streamSettingsトランスポートとセキュリティ設定サーバー側を確認せず、接続方式だけ変更する
tag設定内でルールから参照するタグ画面上の別名を固定タグだと思い込む

接続先アドレスと、TLSの検証に使うサーバー名は別のものです。前者は接続先を指定し、後者は証明書の本人確認に使われます。環境によっては両者が異なる場合もありますが、サービス設定上の明確な根拠が必要です。証明書エラーが発生したら、システム時刻、サーバー名、証明書チェーンを確認してください。検証を無効にするのは避けましょう。接続のセキュリティが変わるため、恒久的な解決策にはならず、ほかの設定が正しいことの証明にもなりません。

REALITYなどの専用機能は、対応するコアと適合するサーバー側パラメーターが必要です。JSONにセキュリティ関連の項目があるからといって、別のコア向けのサンプルをそのまま流用しないでください。v2rayNでは異なるコアを使う項目を管理できますが、すべての項目で実行するコアを自由に切り替えられるわけではありません。Android版のv2rayNGとv2flyNGも、それぞれのコアの機能に合わせて選んでください。3つのクライアントの違いはクライアント比較をご覧ください。

outboundのトラブルシューティングは、1つのオブジェクトから始めます。テスト用のリクエストが目的のoutboundだけを通るよう、一時的に明示的なフォールバックルールを設定し、基本の接続を確認してから複雑な振り分けを戻してください。一部のサイトだけ失敗する場合は、宛先の名前解決とルールを確認します。すべての宛先で接続できない場合は、リモートアドレス、認証、トランスポートを確認してください。基本的な問題を覆い隠すために接続最適化を複数同時に有効にしないでください。設定を増やすと、ログの失敗箇所と元のリクエストを対応付けにくくなります。

サブスクリプションの更新により、サービス提供元が接続パラメーターを変更したり、クライアントが内部タグを再生成したりすることがあります。手動で管理しているカスタムルーティングが古いタグを参照している場合は、更新後に見直してください。リモートの接続情報はサブスクリプション項目で管理し、長期的な振り分けルールはルーティング設定で管理することをおすすめします。outboundを完全にカスタマイズする場合は、パラメーターの出所とコアの要件を記録してください。トラブルシューティング用の情報を共有する前に、認証情報と個人用のサブスクリプションURLを削除します。

4. routing:ルールと適用順

先にマッチしたルールで出口が決まる

routing.rulesは順序を持つルール配列です。一般的なフィールドルールでは、同じ配列フィールドに設定した複数の候補は、いずれか1つに一致すれば条件を満たします。一方、異なる条件フィールドを複数指定した場合は、すべてを満たす必要があります。たとえば、inboundタグとドメインを指定したルールは、指定した入口から入り、かつ宛先ドメインが条件に合う接続だけを処理します。ルールは上から順に評価されるため、個別ルールを広範囲のルールより前に置き、フォールバックルールを最後に置いてください。

次のサンプルでは、まず文書用の例示ドメインをブロックし、続いてプライベートアドレスをdirectへ、それ以外のTCPとUDP通信もdirectへ送ります。ルールの順序とタグの参照方法を示す例であり、リモートプロキシへの振り分け設定ではありません。使用前に、directとblockのタグを持つoutboundを用意し、現在のコアが読み込めるGeoIPデータファイルを配置してください。データベースがない場合は、対応するルールを削除して基本動作を確認してください。

{
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:example.org"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "direct"
      }
    ]
  }
}

意図に合ったドメインの指定方法

full:example.orgはこのドメインとの完全一致を指定し、domain:example.orgはそのドメインとサブドメインに一致します。正規表現は柔軟に指定できる一方、範囲が広がりすぎやすいため、通常は明確な完全一致やサフィックスルールを使います。Webページの完全なURLをドメイン一覧に記述しないでください。パス、クエリパラメーター、フラグメントはドメイン条件に含まれません。パス付きのURLを指定すると、ルールが存在しているのに一度もマッチしないことがあります。

IP条件には、単一アドレス、CIDR形式のネットワーク、データベースの参照を使用できます。ドメインルールとIPルールが扱う情報は異なります。あるドメインが特定のカテゴリに該当しても、名前解決されたすべてのIPアドレスが同じカテゴリに属するとは限りません。CDNでは複数のサイトが同じアドレスを共有したり、同じサイトでも地域によって異なるアドレスが返されたりします。細かく制御する必要がある通信では、まず何を基準にマッチさせるかを決め、ドメインかIPアドレスのどちらを使うか選んでください。少数の特定ドメインを対象にするために、広いネットワーク範囲を指定するのは避けましょう。

domainStrategyがルーティング時の名前解決を制御する

AsIsは、接続時点で得られている宛先情報を使ってルーティングし、IPルールとの照合のために追加の名前解決は行いません。IPIfNonMatchは、既存の条件に一致しなかった場合にドメインの名前解決を試み、その結果を使って照合します。IPOnDemandは、ルールの評価にIP情報が必要になった時点で名前解決します。後者を選ぶとDNSの応答がルーティング結果に影響します。名前解決の失敗やアドレスの変更も判定に影響するため、第5章とあわせて確認してください。

ここでいうルーティングの名前解決方針は、すべてのoutboundにおけるアドレスの扱いや、OSのDNS設定と同じではありません。名前の似た項目でも、異なるモジュールに属し、動作するタイミングや範囲が異なる場合があります。変更前に設定オブジェクトのパスを特定し、「ドメインがマッチしない場合に、名前解決したIPアドレスでルールを評価する」のように、期待する動作を具体的にしてください。アプリがすでに宛先をIPアドレスで送信している場合、ドメインの名前解決方針だけで元のドメインを復元することはできません。

GeoIPとGeoSiteのデータは、対応関係を確認して管理します。ファイルを更新したら、実際に動作しているコアが新しいファイルを読み込んでいることを確認し、クライアントの仕様に従って再起動または再読み込みしてください。別のフォルダーにあるファイルだけを置き換えても、結果は変わりません。カテゴリが見つからない、データを読み込めないといったエラーが出たら、まずファイルの入手元とパスを確認し、その後でルールの書き方を見直します。更新方法はGeoIP・GeoSiteデータベースの更新ガイドをご覧ください。

クライアントの「中国本土を迂回」などのプリセットは、単一のスイッチと同じではなく、複数のルールをまとめたものです。切り替えると、ドメイン、IP、フォールバックの出口が同時に変わることがあります。トラブルシューティングでは、生成されたルール全体を確認してください。例外を1つ追加する場合は、先にマッチする広範囲のルールより前に配置し、保存後に再読み込みします。条件が広すぎないか判断するには、マッチする対象とマッチしない対象をそれぞれテストしてください。

複数の入口を使う場合、inboundTagでアプリを分け、特定のローカルポートに固定のoutboundを割り当てる方法もあります。アプリ側でプロキシを指定できる場合は、システムプロキシを何度も変更するより便利です。ただし、アプリが実際に該当する入口へ接続していることが前提です。ルーティングが機能しない場合は、入口タグ、元の宛先、ルールの順序、outboundタグの順に確認してください。アクセス結果が想定と異なるからといって、すぐにデータベースを変更したり、リモートプロトコルを切り替えたりしないでください。

5. dns:名前解決の設定と問い合わせ経路

どの層が名前解決しているかを見極める

サイトへのアクセスでは、アプリ独自の名前解決、OSの名前解決、コア内蔵のDNS、リモートサーバーでの名前解決が関わる場合があります。トップレベルのdns設定が管理するのは、コア内蔵リゾルバーが関与する部分だけです。すべてのアプリのドメイン問い合わせを自動的に引き受けるわけではありません。ブラウザーで暗号化DNSを有効にすると、問い合わせ経路が異なることもあります。トラブルシューティングでは、まずドメイン名とIPアドレスのどちらがコアに渡されたかを記録し、問題が本当にこのオブジェクトに関係しているかを確認してください。

内蔵DNSは、ルーティングの名前解決方針や特定のoutboundの動作などから利用できます。サーバーの配列を追加しただけで、すべてのプロキシリクエストがローカルで先に名前解決されるわけではありません。リモートプロトコルによっては、接続先で名前解決することもあります。反対に、アプリがリクエスト前に名前解決してIPアドレスを送信した場合、コアがここで指定したサーバーを使う機会がないことがあります。システムで正常に名前解決できても、それはOS側の経路が使える証拠にすぎず、コア側でも同じ結果になるとは限りません。

最小限のサーバー設定と静的マッピング

次の設定例では一般的なDNSサーバーを使い、文書用の例示ドメインに静的なマッピングを追加します。マッピング先のアドレスは説明用で、実際のサイトは提供していません。検証では名前解決の結果だけを確認し、Webサイトへの接続確認には使わないでください。静的マッピングは設定構造を示すための例です。多くのサイトのアドレスを設定に長期間固定すると、サーバーの変更後に気づきにくい障害の原因になるため、避けてください。

{
  "dns": {
    "hosts": {
      "example.org": "192.0.2.10"
    },
    "servers": [
      "1.1.1.1"
    ]
  }
}

hostsは内蔵リゾルバーの静的な応答を設定し、serversは上流のDNSサーバーを定義します。サーバーのアドレスに到達できるかどうかは、利用中のネットワークによります。サンプルのアドレスがあらゆる環境で使える保証はありません。通常のDNSと暗号化DNSでは、通信方式、証明書、最初の名前解決の要件が異なります。切り替える前に対象サービスへ接続できるかを確認し、使用中のコアに対応した設定形式を調べてください。WebページのURLをそのままDNSの問い合わせ先として指定することはできません。

ドメインごとの名前解決と応答の制限

DNSサーバーはオブジェクト形式でも指定でき、domainsで優先的に適用するドメイン範囲を設定できます。次の例では、例示ドメインに専用サーバーを指定し、それ以外の問い合わせには既定の候補を使います。専用サーバーで失敗した際にフォールバックするか、どの候補を使うかは、コアの設定にも依存します。配列の前にあるだけで常に優先されるとは限りません。ドメインとのマッチ、サーバー候補の選択、失敗時のフォールバックをそれぞれ分けて理解してください。

{
  "dns": {
    "servers": [
      {
        "address": "1.1.1.1",
        "domains": [
          "domain:example.org"
        ]
      },
      "8.8.8.8"
    ]
  }
}

設定によっては、expectIPsで許容する名前解決結果を絞り込めます。これは結果をフィルタリングする条件であり、誤った応答を正しいものに自動修正する機能ではありません。条件を厳しくしすぎると、サーバーがアドレスを返していてもコアが結果を拒否し、名前解決に失敗したように見えることがあります。データベースを使った条件には、データファイルも必要です。トラブルシューティングでは、まず結果の制限を外して名前解決できるか確認し、その後に条件を1つずつ戻して影響を調べてください。

ルーティングのdomainStrategyとDNSの組み合わせは、特に誤解しやすい設定です。必要に応じて名前解決する設定では、出口を決めるまでに接続先ドメインの結果を待つことがあります。さらに上流のDNSサーバーへの通信に、まだ確立していないプロキシ経路が必要だと、依存関係が循環する可能性があります。リモートサーバー自体をドメイン名で指定する場合も、その名前を最初に解決する方法が必要です。サーバーアドレスの名前解決と、通常の通信先ドメインの名前解決は分けて検証し、テストサイト1つの結果だけで判断しないでください。

IPv4とIPv6の応答も分けて確認してください。IPv6アドレスを取得できても、使用するoutboundでIPv6通信が正常にできるとは限りません。アプリが特定のアドレス形式を優先して接続し、失敗後にもう一方へ切り替えると、接続に時間がかかることがあります。接続が遅いからといって、すぐに一方のアドレスファミリーを恒久的に無効にしないでください。同じ宛先で名前解決結果と接続経路を個別に検証し、コアが対応する問い合わせ方針を調整して、ネットワーク経路の問題をドメイン分類の問題と混同しないようにします。

TUNを使う環境では、システムDNSが仮想インターフェースにどう入るか、DNSの横取りやリダイレクトがあるかなど、さらに確認する項目があります。トップレベルのDNSオブジェクトだけでは説明できないため、クライアントが生成したTUN設定も確認してください。仕組みについてはv2rayNのTUNモード解説をご覧ください。DNSに関する設定を変更したら、アプリの接続をやり直し、キャッシュの影響も考慮して新しい設定を評価してください。

6. policy:レベル別設定、タイムアウト、統計

policyのレベルはルーティングの優先順位ではない

policyは接続動作や統計に関する設定を定義し、levelsではユーザーレベルごとに項目を管理します。ここでのレベルはサブスクリプションのグループ番号でも、ルーティングルールの優先順位でもありません。プロトコルのユーザー設定にあるlevelは、対応するpolicyに関連付けられることがあります。個別に指定しない場合は、通常、既定のレベルが使われます。どのユーザーにも割り当てられていないレベルを変更しても、現在の接続には影響しない可能性があります。まず、policyがどのユーザーに適用されているか確認してください。

次の設定例では、レベル0に接続時とアイドル時のパラメーターを指定します。数値の単位は秒です。項目の関係を示すための例であり、すべてのネットワークに適した推奨設定ではありません。設定全体にトップレベルのpolicyオブジェクトとして統合してください。ほかのレベルやシステム統計の設定がすでにある場合は、既存の項目を残したうえで調整します。サンプル全体で上書きして機能が消えた後、コアの動作が変わったと誤解しないようにしてください。

{
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "uplinkOnly": 2,
        "downlinkOnly": 5
      }
    }
  }
}

接続の各段階に関係する4つの時間項目

handshakeは、inboundの接続でハンドシェイクが完了するまでの待ち時間を制御します。リモートとの接続処理すべてに適用されるタイムアウトではありません。値を大きくしても、認証情報の誤りやトランスポートの不一致は解決しません。接続確立後に停止する場合は、アイドル時の設定、リモート側の状態、アプリの動作を確認してください。ログに「タイムアウト」と表示されても、すべてこの項目が原因とは限りません。エラーが発生した段階を確認する必要があります。

connIdleは、データを転送していない状態が続く時間を扱います。短すぎる設定は、低頻度で長時間維持するセッションに影響することがあります。長すぎる設定では、実際には不要になった接続が解放されるまで時間がかかります。インスタントメッセージ、リモート端末、一般的なWebページでは接続の特徴が異なります。1回のページ読み込みだけで適切かどうかを判断しないでください。変更後は問題のあったアプリを使い、実際に発生しうる待ち時間を含めて確認します。

uplinkOnlyとdownlinkOnlyは、それぞれ上りまたは下りの一方向だけで通信している状態の待ち時間に関わります。アップロードやダウンロードの速度制限でも、ルーティング条件でもありません。アプリによっては、データ送信後も長時間応答を待ち続けます。そのため、一方向通信の扱いによって接続が終了するタイミングが変わります。応答が途中で切れる場合は、これらの項目を変更する前に接続状態とログを確認してください。サーバー側の切断をクライアントのpolicyによるものと誤認しないようにします。

項目対象となる段階代わりにはならないもの
handshakeinboundのハンドシェイク待ち時間プロトコルや認証情報の修正
connIdleデータ転送がないアイドル時間アプリのキープアライブ機能
uplinkOnly上りのみの通信段階アップロード速度制限
downlinkOnly下りのみの通信段階ダウンロード速度制限

統計の有効化だけでは統計画面は作られない

コアの統計機能を使う場合、一般的な設定ではトップレベルのstatsオブジェクトと、policy.system内の統計設定を併用します。次の例では、inboundとoutboundの合計通信量を記録する設定だけを示します。統計用のグラフィカル画面が自動的に作られるわけではなく、クライアントがカウンターを読み取るとも限りません。読み取りにはクライアント側の実装や対応するインターフェースが関係します。参照する方法がなければ、統計項目を追加しても画面に新しい項目が現れることはありません。

{
  "stats": {},
  "policy": {
    "system": {
      "statsInboundUplink": true,
      "statsInboundDownlink": true,
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  }
}

前述のレベル別policyも使う場合は、levelsとsystemを1つのpolicyオブジェクトに統合してください。同じ名前のオブジェクトを2つ作らないようにします。ユーザー単位の統計には、プロトコルやユーザーIDなどの関連条件も必要です。システム統計の設定を、ユーザー統計の設定と混同しないでください。カウンターを比較する際は、プロセスの再起動、セッションの終了、クライアント側の集計方法も考慮します。画面で読み取った数値の差が、単に統計期間の違いによる場合もあります。

バッファーやリソース関連の設定は、さらに進んだチューニング項目です。リソース不足の根拠がない場合は、コアの既定値を使うことをおすすめします。一般向けとされる最適化設定をそのままコピーしないでください。バッファーを増やすとメモリ使用量が増え、減らすと特定の通信に影響することがあります。結果は同時接続数やアプリの読み書き方法にも左右されます。まずプロトコル、ルーティング、DNSが正しいことを確認し、その後に単一のボトルネックを比較テストするほうが、多くのpolicyを一度に追加するより原因を説明しやすくなります。

policyの問題を調べるときは、安定した観察時間を確保してください。問題が起きたアプリ、アイドル時間、接続段階を記録し、毎回1つの項目だけ変更します。影響を受ける接続を作り直してから再テストしてください。policyを変えても差がない場合は、実際の読み込みファイル、ユーザーレベル、現在動作中のコアを確認します。失敗を先延ばしにするためにタイムアウトを次々と大きくしないでください。リモート側が拒否している、またはアドレスに到達できない場合、待ち時間を延ばしても接続は回復せず、エラーの判明が遅くなるだけです。

7. v2rayNによる設定生成とカスタム設定

保存する設定と実行時に生成されるファイルを分けて管理する

v2rayNは、ノード、サブスクリプショングループ、ルーティング、各種パラメーターをクライアントで管理できるデータとして保存し、選択中のコアに合わせて実行設定を生成します。生成ファイルは実行用の成果物であり、長期的な編集元とは限りません。生成結果を直接変更しても、サーバーの切り替え、再読み込み、再起動で変更が上書きされることがあります。継続して保持する設定は、対応する画面から変更してください。JSONを完全に自分で管理したい場合は、カスタム設定項目の管理方法を確認します。

使い始める前に、現在の動作モードを確認してください。通常のノード項目では、クライアントがinbound、outbound、共通設定を組み立てます。カスタム設定項目では、ファイルの内容をそのまま多く保持する場合があります。2つのモードでは、メニュー操作が異なる階層に反映されることがあります。画面上のルーティングプリセットを切り替えれば、任意のカスタムJSONも書き換わるとは限りません。設定が有効かどうかは、画面のボタンが選択状態かではなく、再読み込み後の実際の実行設定を確認してください。

共通設定、ノード設定、サブスクリプションの管理元

ローカルの待ち受けポートやコアの選択などの共通設定は、パラメーター設定に関する画面で確認できます。具体的な項目名は、クライアントの画面変更に伴って変わる場合があります。リモートアドレス、認証、トランスポートはノード設定、サブスクリプションURLや更新間隔はサブスクリプショングループで管理します。問題の種類に合った場所で設定することが大切です。更新間隔を変更してもハンドシェイクプロトコルは変わらず、システムプロキシ設定でリモートサーバーの設定は変わりません。ルーティングプリセットを切り替えても、サブスクリプションが再取得されるわけではありません。

サブスクリプションを更新すると、配信元のノード接続情報が上書きされることがあります。サブスクリプションのノードを手動で長期的に変更する場合は、次回更新時の影響を考慮してください。一時的に試すだけなら、独立して管理できる項目にコピーし、用途を明記します。サービス提供元のパラメーターが変更された場合は、古い項目を何度も修正するのではなく、情報の取得元を更新してください。サブスクリプションを取得できない場合は、URL、ネットワーク、時刻の問題を確認します。手順はサブスクリプション更新エラーのトラブルシューティングをご覧ください。

変更したい内容優先して管理する場所確認する内容
ローカルプロキシの入口クライアントの共通設定実行ポートとアプリ側の設定が一致している
リモート接続の設定ノード項目またはサブスクリプションの取得元生成されたoutboundとサーバーの設定が一致している
Webサイトの通信振り分けルーティング設定ルールの順序とoutboundタグが正しい
JSON全体を直接管理するカスタム設定項目実際の読み込み先とコアが一致している

コアの切り替えは、実行ファイル名の変更だけでは不十分

v2rayNでは、クライアントが提供する設定画面を通じて異なるコアを管理できます。ただし、項目を切り替えて使用できるかどうかは、対応するプロトコルとトランスポート機能によります。Xray専用の設定をV2Flyに読み込ませ、JSONの構文が正しいというだけで使えると判断しないでください。sing-boxは設定オブジェクトの構造が異なるため、このページの設定例もそのまま再利用できません。切り替え前にクライアントが対応する形式を再生成するか、カスタム設定用にコアに合った別ファイルを用意してください。

WindowsのWPF画面とクロスプラットフォーム版のデスクトップ画面では、メニュー、タスクトレイ、OSとの連携方法が異なる場合があります。一方で、inbound、outbound、ルーティングの基本概念は共通です。macOSとLinuxでは、特にTUN関連でシステムプロキシや権限の違いにも注意してください。インストーラーの選び方はデスクトップ版とWPF版の違いをご覧ください。同じメニューを探すためだけに、利用中のプラットフォームに合わないパッケージをインストールしないでください。

Android版のv2rayNGとv2flyNGでは、それぞれのコアと画面に合わせて設定を管理してください。デスクトップ版のメニュー操作をそのまま当てはめることはできません。リンクやサブスクリプションをインポートするときは、クライアントが対応するプロトコルと項目を確認します。完全なJSONをインポートする場合は、クライアントがそのインポート形式に明確に対応していることも確認してください。サブスクリプションURL、単一ノードの共有リンク、完全な設定ファイルは別の種類のデータです。どれもテキストで保存できても、互いに置き換えることはできません。

カスタム設定を使う場合は、変更対象、期待する動作、元に戻す方法を記した簡単な変更履歴を残してください。記録はローカルに保存し、個人設定を公開場所へアップロードする必要はありません。トラブルシューティング情報を共有する場合は、オブジェクト構造、タグ、エラー情報を残しつつ、認証情報、個人用サーバーアドレス、サブスクリプションURLを削除してください。認証情報の一部を隠すだけでは不十分な場合があります。ほかの項目からサービス情報や利用状況が分かることもあります。

設定は、どこで管理するかを一元化します。画面で管理する内容は画面から変更し、カスタムファイルで管理する内容はファイルで変更してください。2つの設定が長期間互いに上書きし合う状態は避けましょう。変更後は、生成結果、プロセスのログ、アプリの動作の順に確認します。画面上の表示と実際の動作が異なる場合は、まず読み込み経路を確認してください。接続だけが目的なら、セットアップの手順に戻れば十分です。すべてのトップレベルオブジェクトを理解する必要はありません。

8. 設定の検証、ログの確認、変更のロールバック

構文、読み込み、入口、出口の順に確認する

設定のトラブルシューティングでは、まずどの段階で失敗したかを特定します。JSONの構文エラーがあるとファイルを正しく解析できません。未対応の項目や存在しない参照は、読み込み時のエラーになることがあります。ポートの競合は待ち受けに影響し、リモートとのハンドシェイクエラーは通常、リクエストが入ってから発生します。段階ごとに修正方法は異なります。実際の原因を示す最初のエラーを確認し、最後に表示される「起動失敗」だけに注目しないでください。後続のメッセージは、先に起きたエラーの結果であることが少なくありません。

編集前に、現在動作している設定ファイルまたはクライアント設定のバックアップを作成し、今回変更するオブジェクトを記録します。編集後は、括弧、カンマ、値の型、重複キーを確認してから、クライアントで再読み込みし、コアが正常に起動するかを確認してください。クライアントに設定の表示画面やログがある場合は、変更した項目が読み込まれていることも確認します。失敗した後にルールを次々と追加しないでください。直近の正常な状態に戻すと、どの変更で差が生じたかを特定できます。

ローカルのリクエストで入口を確認する

次の2つのコマンドは、対応するオプションが使えるcurlで、ローカルのSOCKS入口とHTTP入口をそれぞれテストします。第2章のポートを使うため、その設定が実際に動作している場合にのみ実行してください。SOCKSコマンドのsocks5-hostnameは、宛先ドメインの名前解決をプロキシ側で行います。ローカルで名前解決する方式に変更すると、テストするDNS経路も変わります。テスト先へ接続できるかは、利用中のネットワークやoutboundにも左右されるため、コマンドの実行が成功を保証するものではありません。

curl --proxy socks5h://127.0.0.1:10808 --head https://example.org/
curl --proxy http://127.0.0.1:10809 --head https://example.org/

ローカルポートに接続できない場合は、すぐにリモート設定を変更せず、プロセス、待ち受けアドレス、ポートを確認してください。ローカル接続が確立した後に失敗する場合は、宛先の名前解決、ルーティングの選択、outboundのハンドシェイクを調べます。テストでは同じ宛先と入口を使い、毎回1つの条件だけ変更してください。ブラウザーのキャッシュ、システムプロキシ、コマンドラインからの直接接続を混在させると経路が異なり、見た目は同じアクセスでも比較できません。

ログを一時的に詳細化し、詳細ログを常時保存しない

通常の利用には既定の警告レベルが適しています。ルーティングや接続を調べる場合は、一時的にinfoへ変更できます。次の例ではエラーログの詳細度だけを変え、ファイルの保存先は指定しません。まずクライアントのログ画面で確認できます。ファイルに保存する場合は、書き込み可能なフォルダーとOSに合ったパスを指定し、ファイルサイズの増加にも注意してください。ログには宛先ドメインや接続情報が含まれる場合があります。共有前に内容を確認し、機密情報を削除します。

{
  "log": {
    "loglevel": "info"
  }
}

ログは新しく作成した1つのリクエストを中心に、時系列で入口の受信、宛先の識別、outboundの選択、失敗箇所を確認します。ルールにマッチしない場合は条件と順序、タグが見つからない場合は参照先を確認します。証明書エラーでは時刻とサーバーの本人確認、データベースの読み込みエラーではファイルパスとカテゴリを調べてください。コアごとにログの表現は異なります。よく見かけるエラーメッセージだけを判断基準にせず、今回のリクエストの状況と照らし合わせます。

症状まず確認する項目次に行うこと
設定を読み込めない構文、項目の対応状況、タグの参照最小限の完全な設定にする
ローカルポートに接続できないプロセス、待ち受けアドレス、ポートの競合アプリのプロキシ入口を確認する
入口は正常だがハンドシェイクに失敗するoutboundの認証、トランスポート、セキュリティ設定対象のoutboundだけで検証する
一部の宛先で接続先が想定と異なる宛先情報、ルールの順序、データベースマッチする対象としない対象を追加でテストする
名前解決が断続的に失敗する問い合わせ経路、キャッシュ、アドレスファミリー各層の名前解決を分けてテストする

複雑な設定を安全に元へ戻すには、層ごとに復元します。まず第1章のローカル直結設定を確認し、次に対象のoutboundを追加、その後に少数のルールを戻し、最後にDNSとpolicyの変更を復元してください。GUIクライアントを使う場合は、実運用の項目を変更せず、独立したテスト用項目で検証できます。復元の各段階で新しい接続を作成し、結果を記録します。以前のoutboundを使い続ける既存セッションが、判断に影響しないようにしてください。

1回アクセスできただけでは、設定全体が正しいとは限りません。直接接続する想定の宛先、別の出口を使う想定の宛先、長時間使うアプリをそれぞれテストしてください。UDPやTUNを有効にしている場合は、それらの通信も個別に確認します。検証範囲は今回の変更内容に合わせてください。WebページをTCPで開けたからといって、すべての通信が正常だとは判断できません。特定のアプリだけ失敗する場合は、よくある質問とトラブルシューティングを参照し、入口方式から原因を絞り込んでください。

確認が終わったら、適切なログレベルに戻し、一時的なドメインマッピングとテスト用ルールを削除します。クライアントを再起動しても同じ設定を読み込めることを確認してください。最終的に有効だった変更は、生成ファイルだけに残さず、長期的に管理している設定元へ反映します。コアの位置付けはProject V、V2Fly、Xrayのエコシステムをご覧ください。設定管理では項目を増やすことではなく、それぞれの動作を説明、再検証、ロールバックできる状態にすることが大切です。