CONFIGURATION REFERENCE

V2Ray JSON設定ガイド

設定構造、項目の適用範囲、項目ごとの検証方法。

このページは、設定ファイルを確認・調整したい方や、トラブルを解決したい方向けです。初めて接続する場合は、まず入門ガイドに沿ってサブスクリプションを追加し、接続を確認してから、このページで各項目を調べてください。デスクトップではv2rayN、Androidではv2rayNGを推奨します。カーネルの要件に応じてv2flyNGも選べます。インストール先はクライアントダウンロードページにまとめています。

このページの例では、一般的な従来形式のJSON設定を使用します。各項目が利用できるかどうかは、実際に動作しているV2FlyまたはXrayカーネルと、その公式ドキュメントで確認してください。コード例は該当する階層の説明用です。異なる章のオブジェクトをそのまま連結して設定にしないでください。

1. JSON構造と設定の適用範囲

まずクライアントとカーネルを区別する

v2rayN、v2rayNG、v2flyNGは設定を管理するGUIクライアントです。実際に接続を受け付け、ルールに照らして通信を振り分けるのはカーネルです。クライアント画面のサブスクリプション、設定一覧、システムプロキシ、ルーティングプリセットが、設定ファイル内のオブジェクトと必ずしも一対一で対応するわけではありません。JSONを読む前に、クライアントの実行情報や起動ログでカーネル名を確認し、対象の設定が自動生成なのか、カスタム設定ファイルなのかを把握しましょう。

従来形式の設定では、通常、トップレベルは1つのオブジェクトで、その中を役割に応じてlog、inbounds、outbounds、routing、dns、policyに分けます。inboundsとoutboundsが配列なのは、1つのプロセスで複数のローカル接続口を提供したり、複数の転送先を使い分けたりできるためです。配列の要素が1つだけでも、角括弧を波括弧に変えないでください。

最小構成で動作の基準を作る

以下は、ローカルのSOCKS inboundsから直結outboundsへ転送する基本設定です。カーネルの起動、ローカルでの待ち受け、アプリからの接続を確認できますが、リモートプロキシには接続しません。テストするアプリにローカルのSOCKSポートを明示し、直接アクセスできる宛先を選んでください。この基本設定が動作してからリモートoutbounds、ルーティング、DNSを追加すれば、新しい項目による変化を切り分けやすくなります。

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

JSONの文字列とキー名はダブルクォーテーションで囲み、真偽値はtrueまたはfalseと記述します。ポート番号は単位を付けず、数値で指定してください。標準JSONはコメントに対応しておらず、最後の要素の後にカンマを置くこともできません。カーネルによっては拡張構文を読み込める場合がありますが、クライアントへのインポートやサブスクリプション変換、ほかのツールでの処理時に厳密なJSONとして解析される可能性があります。手書きの設定は標準形式にしておくのが安全です。

トップレベルのオブジェクトで同じキーを重複させるのも、見落としやすい問題です。最後の値だけを残すパーサーもあれば、読み込みを拒否するツールもあります。いずれにしても、重複したキーで設定を追加するのは避けてください。たとえばroutingオブジェクトを2つ書いても、ルールが自動的に統合されるわけではありません。ルールを追加する場合は、同じrules配列を編集し、新しいルールを置く位置も明確にしましょう。

編集方法によって変更の保存先が変わる

自動生成の設定は、現在のノード、ルーティングプリセット、各種設定をもとにクライアントが組み立て直すのが一般的です。実行用ディレクトリの一時ファイルを直接編集しても、現在の起動中だけ有効な場合があります。ノードの切り替えやサブスクリプションの更新、サービスの再起動で上書きされることもあります。長く使う変更は、クライアントが対応するカスタム設定の入口に書き込むか、個別の設定ファイルとして保存し、専用の読み込み機能から適用してください。

カスタム設定にも適用範囲があります。クライアント画面のローカルポート、ルーティングモード、DNSの設定が、カスタムファイル内の項目を上書きするとは限りません。逆に、画面上の機能が周辺の実行パラメーターを生成することもあります。設定画面でチェックが入っているかではなく、カーネルが最終的に読み込んだ設定とログを判断材料にしてください。設定方式を初めて切り替えるときは、既存の接続を一度停止し、設定の入口を記録してから再起動して確認しましょう。

よく使う設定オブジェクトの役割
オブジェクト主な役割対象外の役割
inboundsアプリからの接続を受け付けるブラウザーのプロキシを自動設定する
outboundsoutboundsとリモートプロトコルを定義するルーティング全体の順序を決める
routing接続に使用するoutboundsを選ぶOSのDNS設定を変更する
dnsカーネルのドメイン名解決を設定するすべてのアプリの問い合わせを自動的に取り込む

異なるカーネルで一部の項目名が共通していても、設定全体を無条件に使い回せるわけではありません。拡張プロトコル、通信方式、DNSオプション、policyの初期値はカーネルによって異なる場合があります。移行する際は、まずinbounds、直結、ブロックなどの基本設定を残し、移行先のカーネルが対応する機能を1つずつ追加してください。解析エラーは項目のパスを手がかりに解決し、起動に成功する前にサーバーやサブスクリプションまで同時に変更しないようにしましょう。

2. inbounds:ローカルでの待ち受けとアプリ接続

まず待ち受けアドレスとポートを確認する

inboundsは、カーネルがどこで接続を受け付けるかを定義します。1台の端末で使う場合、最初に確認する項目はlistenとportです。前者はバインドするローカルアドレス、後者はアプリの接続先ポートを指定します。設定が正しくても、ポートのバインドに成功するとは限りません。同じアドレスとポートを別のクライアント、古いカーネルプロセス、または別のサービスが使用していると起動に失敗します。通常、ログに待ち受けエラーが記録されます。

127.0.0.1はこの端末からのみアクセスできるため、デフォルトの設定に適しています。待ち受けアドレスを0.0.0.0にすると、すべてのIPv4ネットワークインターフェースで待ち受けますが、ほかの端末から接続できるかどうかはファイアウォールやネットワーク環境にも左右されます。待ち受け範囲の拡大は、ローカル接続の問題を解決するための一般的な手段ではありません。LANから接続する必要がある場合は、認証、接続元の制限、端末が接続しているネットワークの信頼性も考慮してください。

SOCKSとHTTPは異なる接続方式

SOCKS inboundsはSOCKSプロキシを明示的に指定できるアプリ向けです。HTTP inboundsはHTTPプロキシ設定を読み取るアプリに使用します。アプリで選んだプロトコルと接続先ポートを一致させてください。HTTPプロキシの接続先をSOCKSポートに入力すると、明確な「プロトコル不一致」のエラーが表示されず、接続直後に切断されることがあります。ポートに接続できたからといって、アプリが正しく接続できているとは限りません。

{
  "inbounds": [
    {
      "tag": "local-socks",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    },
    {
      "tag": "local-http",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ]
}

以下の例では独立した2つの接続口を設定しています。記載したポートはこの例での設定値であり、すべてのクライアントで固定されているわけではありません。実際に使う際は、現在のクライアントのローカル待ち受け設定を確認してから、アプリのプロキシ設定に入力してください。ブラウザー拡張機能、OSのプロキシ設定、ターミナルの環境変数がそれぞれ異なるポートを参照していることもあります。トラブル対処では、テスト対象のアプリがどの設定を読み込んでいるのかを記録し、使われていない接続口だけを変更しないようにしましょう。

SOCKSのudpは、対応するUDP接続を許可する設定です。すべてのアプリのUDP通信が自動的にカーネルへ送られるという意味ではありません。アプリがSOCKS UDPに対応し、実際にそれを使用する必要があります。また、後続のoutboundsやネットワーク経路もUDPに対応していなければなりません。この項目を有効にしただけでは、OSレベルでの通信取り込みが必要なケースは解決できないことがほとんどです。AndroidのVPN接続と、デスクトップアプリでローカルプロキシを手動設定する方法は、同じ接続方式ではありません。

tagとsniffingの適用範囲

tagはinboundsの識別名で、ルーティングのinboundTagから参照できます。待ち受けポートではないため、名前を変えて接続方法が変わると期待しないでください。役割がわかる名前を付け、重複を避けましょう。local-socksを別の文字列に変更した場合、その名前で接続を振り分けるすべてのルールも合わせて変更する必要があります。変更を忘れると、対象ルールに接続が一致しなくなります。

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

上記のオブジェクトは、1つのinboundsの内部に記述します。sniffingは、HTTPのホスト情報やTLSハンドシェイクのサーバー名など、対応する通信の冒頭から宛先ドメイン名を取得し、後続の振り分けを補助します。HTTPSを復号する機能ではなく、すべての接続でドメイン名を取得できるわけでもありません。通信に該当する特徴がない場合や、アプリが異なるハンドシェイク方式を使う場合、十分な情報がまだ届いていない場合には、期待する結果が得られないことがあります。

sniffingのオプションはカーネルによって異なり、宛先アドレスを置き換えるかどうかに影響するものもあります。ドメインルールを有効にするために、すべての項目を一度に有効にしないでください。まずアプリがプロキシにドメイン名を渡しているか確認し、必要な場合にだけsniffingを検討しましょう。すでにドメイン名が渡されているなら、問題はルールの順序やoutboundsの選択にある可能性が高いです。ルーティングだけに使うsniffingについては、使用中のカーネルが該当設定に対応しているか確認してください。

inboundsのトラブル対処手順
症状まず確認する項目
カーネル起動直後に終了するポートの競合、待ち受けアドレスの有無、項目の形式
カーネルは正常だがアプリの接続記録がないアプリのプロキシ設定の参照先、プロトコルとポートの組み合わせ
ウェブサイトは開けるが一部のアプリで失敗するアプリがシステムプロキシを参照するか、UDPを使用するか

inboundsを検証するときは、テスト用アプリと接続口を1つずつに絞り、アプリ独自のほかのプロキシ拡張機能を一時的に無効にしてください。ログに接続が記録されない場合は、まずリモートoutboundsの設定を変更しないでください。通信がカーネルに届いていないなら、サーバー設定を正しくしても改善しません。ブラウザーとターミナルを分けて確認する方法は、システムプロキシが機能しないときの確認リストをご覧ください。

3. outbounds:出口タグとリモートプロトコル

outboundsは動作を定義し、ルールは定義しない

outboundsは、通信がカーネルを離れる際の接続方法を定義します。よく使われる種類には、宛先へ直接接続するfreedom、接続を拒否するblackhole、リモートサーバーを利用するプロトコルoutboundsがあります。ルーティングがoutboundsを選び、outboundsが転送を実行します。互いの役割を代替することはできません。proxyという名前のoutboundsを作成しても、すべての通信が自動的にそこへ送られるわけではありません。最終的な転送先はデフォルトoutboundsとルーティングルールで決まります。

一般的な従来形式の設定では、ルーティングルールに一致しない通信は、outbounds配列の先頭要素を使用します。そのため配列の順序は表示上の並びではなく、実際の動作に影響します。設定を整理してdirectを先頭に移動すると、先頭のプロキシに依存していたデフォルトの動作が変わります。変更記録にはデフォルトoutboundsを明記し、ルールを追加するたびにどのルールにも一致しないテスト用の宛先で、デフォルト経路を確認してください。

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

このコード例に含まれるoutboundsは直結とブロックだけで、リモートサーバーはありません。outboundsの選択を理解するための例です。ブロック用outboundsは特定の通信を明示的に拒否するために使えますが、リクエストの失敗をすべてリモートネットワークの障害と考えてはいけません。ルーティングが誤って宛先をblockへ送っている場合、サーバーを変更しても解決しません。トラブル対処では、まず接続先として選ばれたタグを確認し、その後、そのoutboundsの接続やハンドシェイクの記録を調べましょう。

リモート設定の関連項目をまとめて確認する

リモートoutboundsでは、プロトコル、アドレス、ポート、認証情報、通信方式、セキュリティ層が相互に関連します。共有リンクに大半の情報を含められますが、形式の違いによってインポート時に問題が生じる場合もあります。インポート後に接続できないときは、アドレスとポートだけを見るのではなく、クライアントの編集画面と元の設定情報を項目ごとに比べてください。特に通信パス、サーバー名、フロー制御オプションが抜けていないか確認しましょう。

以下は従来形式のVLESS outboundsを説明する例です。ドメイン名example.comと全ゼロの識別子は項目の場所を示すためのもので、実際に接続できるサービスではありません。実際のリモート設定は、信頼できる提供元からインポートしてください。日常の接続に例の認証情報やサーバー名を使ったり、ほかのプロトコルのユーザー項目をこのオブジェクトへそのまま移したりしないでください。

{
  "tag": "proxy",
  "protocol": "vless",
  "settings": {
    "vnext": [
      {
        "address": "example.com",
        "port": 443,
        "users": [
          {
            "id": "00000000-0000-0000-0000-000000000000",
            "encryption": "none"
          }
        ]
      }
    ]
  },
  "streamSettings": {
    "network": "tcp",
    "security": "tls",
    "tlsSettings": {
      "serverName": "example.com"
    }
  }
}

encryptionの値は、プロトコルと合わせて解釈する必要があります。例のnoneは、このVLESS構造で使われる項目であり、外側のTLSを無効にしても同等の通信保護が得られるという意味ではありません。VMess、Trojan、VLESSは認証方法と項目の構造が異なるため、protocolだけを置き換えても変換できません。プロトコルを選ぶ際は、リモートサービスと一致することを最優先し、次にローカルのカーネルが対応しているかを確認してください。

タグ参照とクライアント更新時の注意点

outboundsのタグは、ルーティングのoutboundTagと大文字・小文字も含めて正確に一致させてください。設定一覧の表示名を「プロキシ」に変更しても、カーネルのoutboundsタグが変わるとは限りません。クライアントが固定のタグを生成する場合もあります。手書きのルーティングは最終的に実行される設定を基準にしましょう。存在しないタグを参照すると、設定エラーや転送失敗につながることがあります。カーネルが適切なoutboundsを推測してくれると期待しないでください。

サブスクリプションを更新するとノード設定が更新され、手動で変更したリモートアドレス、ユーザー識別子、通信項目などが上書きされる場合があります。独立したノードを長く使う場合は、まずクライアントでの設定複製方法とサブスクリプションとの関連を確認してから、コピーを保存してください。共有リンクとサブスクリプションURLでは更新の仕組みが異なります。どの階層を変更すべきかは、ノード共有リンクとサブスクリプションURLの違いも参考になります。

基本的な接続は確立できるのに特定の宛先だけ失敗する場合は、リモート設定をそのままにして、直結とプロキシのどちらへルーティングされるかを比較してください。接続、認証、セキュリティハンドシェイクの失敗がログに記録されているときに限り、outboundsの項目を優先して確認します。「すべてのアクセスが失敗する」と「特定の宛先だけ失敗する」を分けて記録すれば、ルーティングの局所的な問題に対してノード設定全体を何度も作り直さずに済みます。

4. streamSettings:通信方式とセキュリティ層

プロトコル、通信方式、セキュリティを分けて読む

ノード設定を読むときは、3つの層を区別してください。プロキシプロトコルは双方の認証方法と宛先の伝え方を定義し、通信方式はデータを運ぶ接続形態を決め、セキュリティ層はハンドシェイクと暗号化を処理します。protocol、streamSettings.network、streamSettings.securityは、それぞれ別の層に属します。互いに互換性のある組み合わせが必要ですが、リモートポートが443だからといって、通信方式がWebSocket、セキュリティ方式がTLSだとは限りません。

通信方式の設定はリモート側の接続方式と一致させる必要があります。TCPを使うサービスで、クライアントのnetworkをwsに変更しただけではWebSocketは使えません。リバースプロキシが該当リクエストを転送できるか、パスが一致するか、上流サービスが待ち受けているかなど、サーバー側の条件が関わります。クライアントが使えるのは既存の接続方式だけです。ローカルの項目でリモートに新しい接続口を作ることはできません。

TLSのドメイン名とサーバーアドレス

addressは接続先、serverNameはTLSハンドシェイクで使うサーバー名です。環境によっては両者が異なる場合があります。通常、証明書の検証には有効なサーバー名が一致している必要があります。アドレスに接続できてもTLSハンドシェイクに失敗する場合は、検証を無効にする前に、システム時刻、サーバー名、証明書の状態を確認してください。検証を無視すると信頼の範囲が変わり、本来修正すべき設定ミスを見逃すおそれがあります。

{
  "streamSettings": {
    "network": "ws",
    "security": "tls",
    "tlsSettings": {
      "serverName": "example.com"
    },
    "wsSettings": {
      "path": "/tunnel",
      "headers": {
        "Host": "example.com"
      }
    }
  }
}

これは通信オブジェクトの説明用コード例で、パスやドメイン名は実際のサービスを示していません。pathはサーバー側のルーティングと完全に一致させてください。先頭のスラッシュや大文字・小文字も確認しましょう。HTTPのHostとTLSのサーバー名は別の段階で使われます。前者はHTTPリクエストのルーティング、後者はセキュリティハンドシェイクに関係します。同じ値が必要な構成もありますが、一方の項目を変更しても、もう一方が自動的に同期するとは限りません。

パスにクエリパラメーターが含まれることもあります。テキストで設定をコピーする際は、元の内容をすべて保持してください。共有リンクの一部がURLエンコードされている場合、クライアントの編集画面ではデコード後の形式で表示されることがあります。トラブル対処では、エンコードされた文字列とデコード後の文字列を混同せず、意味と最終的に実行される項目を比べましょう。二重にエンコードすると、サーバーに異なるパスが渡される場合があります。

接続段階と関連項目
段階代表的な項目よくある確認事項
宛先への接続address、portアドレス解決、ネットワーク到達性
セキュリティハンドシェイクsecurity、serverNameサーバー名の一致、時刻、サーバー側の設定
通信方式での接続network、path通信方式、リバースプロキシのパス
プロトコル認証ユーザー識別子、プロトコル固有の項目認証情報、プロトコル、カーネルの対応状況

REALITYとフロー制御を混同しない

REALITYはXrayエコシステムのセキュリティハンドシェイク方式であり、任意に置き換えられるプロキシプロトコル名ではありません。一般的な組み合わせでは、プロトコルにVLESSを使い、通信のセキュリティ層に関連項目を設定します。サーバー名、公開パラメーター、ショートIDは、サーバー側で許可された値に合わせてください。項目名はカーネルの更新に伴って変わることもあるため、設定を移行する際は使用中のカーネルのドキュメントを参照してください。

XTLS Visionのフロー制御オプションはREALITYとは別の項目で、すべての通信方式と自由に組み合わせられるわけではありません。flowを設定するかどうかは、サーバー側のプロトコル構成とクライアントで実際に使用するカーネルに基づいて判断してください。認証やフロー制御に関するエラーが出た場合は、まずサービス提供元の完全な設定に戻し、組み合わせが対応しているか確認しましょう。別の通信方式向けの記事から一部の項目だけを持ち込まないでください。

それぞれの役割を確認したい場合は、REALITYとXTLS Visionの仕組みをご覧ください。実際のトラブル対処では、ログに記録された失敗段階を基準にします。接続に失敗したらアドレス、ハンドシェイクに失敗したらセキュリティ設定、接続パスが合わない場合は通信方式を確認します。通信方式、ポート、サーバー名を一度に変更するより、段階ごとに調べるほうが確実です。

5. routing:ルールの順序と振り分け範囲

デフォルトoutboundsを決めてから例外を追加する

ルーティングルールは通常、配列の先頭から順に確認され、最初に条件を満たしたルールによって接続先が決まります。文字列の長さから自動的に「より具体的なルール」を選ぶ仕組みでも、複数の結果を組み合わせて評価する仕組みでもありません。そのため、特定のドメインに対する例外は、広い範囲に適用される分類ルールより前に置くのが一般的です。振り分けを設定する前に、デフォルトの動作を一文で定め、例外を優先順に並べておくと、ルールの順序を何度も調整せずに済みます。

1つのルール内では、異なる条件項目は通常すべて満たす必要があります。同じドメインやIPのリスト内にある複数の項目は、どれか1つに一致すれば条件を満たします。たとえばinboundTagとdomainを同時に指定すると、指定したinboundsからの接続であり、かつ宛先ドメインが一致することを表します。どちらか一方だけを満たせばよいという意味ではありません。「個別に試すと一致するのに、条件を組み合わせると一致しない」という問題の原因になりやすい点です。

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": ["full:example.com"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": ["geoip:cn"],
        "outboundTag": "direct"
      }
    ]
  }
}

この例はルーティング部分のみを示しています。完全な設定でdirectとblockが定義され、読み込み可能なドメイン分類データとIP分類データがインストールされていることを前提とします。ルールに一致しない通信をプロキシへ送るには、実際のリモートプロキシをデフォルトoutboundsに設定してください。この例だけではプロキシは作成されません。最初のルールは、後続の一般的な方針より具体的な例外を優先する方法を示すため、ドキュメント用のドメインをブロック先へ送ります。

ドメインの指定形式と分類データ

full:はドメインの完全一致、domain:はドメインとそのサブドメインの範囲、regexp:は正規表現での一致に使います。接頭辞のない文字列はキーワード一致として扱われる場合があるため、完全一致だと決めつけないでください。特定のサイトに一致させたい場合は、意図のわかりやすい接頭辞を使い、実際の接続ログで確認するのが基本です。正規表現は簡潔にし、保守しにくい広範囲なパターンを避けましょう。

geositeとgeoipは異なる種類のデータを参照します。前者はドメイン分類、後者はIPアドレス範囲を提供します。どちらも接続先の地域をカーネルがその場で判定する機能ではありません。データファイルの不足、分類名の誤り、パスの間違い、古いリソースによって、読み込みやマッチングに影響が出る場合があります。ノードのサブスクリプションを更新しても、これらのリソースが同時に更新されるとは限りません。対応するリソース管理の画面から別途確認してください。

domainStrategyで名前解決のタイミングを指定する

AsIsは通常、接続時に渡された宛先の形式で照合し、ルーティングのためにドメインをIPアドレスへ追加で解決しません。IPIfNonMatchは、ドメインが該当ルールに一致しなかった場合に名前解決し、IPルールを確認します。IPOnDemandは、照合にIP条件が必要になった時点で名前解決します。詳細な動作はカーネルのドキュメントで確認してください。いずれも影響するのはルーティングの段階であり、システム内のすべてのドメイン名問い合わせではありません。

名前解決を有効にすると、一部の接続で追加の問い合わせが発生し、結果によってルーティングも変わる場合があります。広範囲に一致するIPルールを先に置くと、ドメイン分類に基づく振り分けが意図せず変わることがあります。トラブル対処では、まずカーネルに届いた宛先がドメイン名かIPアドレスかを確認し、次にルールの順序、最後に名前解決の方針を確認してください。入口の情報を調べずにdomainStrategyだけを変更しても、同じサイトがアプリによって異なるoutboundsへ送られる理由はわからないことがあります。

ルール作成時によくある誤解
誤解実際の適用範囲
ドメインルールであらゆるIP接続を判定できるinboundsからドメイン名が渡されるか、対応するsniffingで情報を取得する必要がある
ルーティングモードを変更するとアプリのプロキシ設定も変わるルールが処理するのは、すでにカーネルへ届いた接続だけ
分類データは常に完全である分類データは管理されるデータ集合であり、抜けや変更が生じることがある

既存の接続では変更前の経路が使われ続けることがあり、ブラウザーも接続を再利用します。ルールを変更したら、新しい接続でテストしてください。必要に応じてテスト対象のアプリを再起動し、ページの再読み込みだけで済ませないようにしましょう。ログの結果が想定と異なる場合は、まずドメインを1つだけ指定したルールで接続元とoutboundsを確認し、その後、分類ルールを段階的に戻してください。ルーティングの設定例は、geosite・geoipによるルーティング実践をご覧ください。

6. dns:名前解決の参照先と通信経路

まず、どの処理がドメイン名を問い合わせるか確認する

カーネルのDNSを設定しても、OS、ブラウザー、すべてのアプリが自動的にその設定を使うわけではありません。アプリがローカルで名前解決し、IPアドレスをプロキシへ渡すこともあります。SOCKSやHTTPの接続口にドメイン名を直接渡し、後続の処理で解決する場合もあります。ブラウザー独自のセキュアDNS、システムの名前解決キャッシュ、アプリ内の名前解決ライブラリによって、経路が分かれることもあります。トラブル対処では、まず宛先がドメイン名とIPアドレスのどちらの形式でカーネルへ届いているかを確認してください。

トップレベルのdnsは、ルーティング時のIP判定や、一部のoutboundsによる宛先解決など、カーネル内の機能に名前解決を提供します。この設定は、ローカルのDNSポートで自動的に待ち受けるという宣言ではありません。アプリがカーネルを介さず個別に問い合わせているなら、このオブジェクトを追加してもアプリの動作は変わりません。クライアントが対応する通信取り込み機能やアプリの設定で対処し、両者の役割を混同しないようにしましょう。

DNSサーバーと問い合わせ方針の基本

以下の例では一般的なDNSサーバーアドレスを指定し、問い合わせをIPv4に限定しています。指定したアドレスは説明用であり、すべてのネットワーク環境に適しているとは限りません。テスト時は、使用中のネットワークから接続でき、目的に合ったDNSサービスを選んでください。サーバーに到達できない場合、ドメインのルーティングを変更しても問い合わせは成功しません。根拠なくDNSサーバーを次々に追加するのも避けましょう。

{
  "dns": {
    "hosts": {
      "manual.example": "192.0.2.10"
    },
    "servers": [
      "1.1.1.1",
      "8.8.8.8"
    ],
    "queryStrategy": "UseIPv4"
  }
}

hostsの例では、説明用に予約されたアドレスを使っています。実際のサービスへのアクセスには使用しないでください。静的なマッピングは管理されたテストに役立ちますが、通常のアドレス更新を迂回します。接続先が移転した後も古いマッピングが残ると、無効なアドレスを長期間参照し続けることがあります。名前解決の問題を調べる際は、カーネル内のマッピングとシステムのhostsファイルを分けて確認してください。設定の参照元が異なります。

UseIPv4、UseIPv6、UseIPは、カーネルが問い合わせるアドレスファミリーの傾向や範囲を制御します。IPv4に限定すると、IPv6経路の問題を確認しやすくなる場合がありますが、すべての環境で常に最適な設定とは限りません。宛先がIPv6にしか対応していない場合、IPv4を強制しても利用可能なアドレスは得られません。ネットワークがデュアルスタックに対応しているなら、実際の接続状況と用途に応じて判断し、例をそのまま使い回さないでください。

ドメイン別DNSとフォールバックを合わせて設計する

従来形式の設定では、サーバーオブジェクトを使い、特定のドメインに使うDNSサーバーを選択できます。ただし、ドメインによる優先選択、条件に一致しない場合のデフォルト問い合わせ、問い合わせ失敗後のフォールバックには、複数の項目が関係することがあります。domainsの一覧を1つ書いただけでは、ほかのサーバーが使われないとは限りません。名前解決の経路を明確に制御する必要がある場合は、使用中のカーネルのフォールバック設定を確認し、問い合わせ成功時だけでなく失敗時も検証してください。

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

この例が示すのはドメインに基づくサーバー選択であり、問い合わせが必ずプロキシ経由になることを保証するものではありません。DNSリクエストがルーティングに入るか、直接接続されるか、特定のoutboundsを通るかは、サーバーアドレスの形式、カーネルの実装、関連設定によって異なります。通常のUDP問い合わせ、HTTPS経由の問い合わせ、ローカル処理を伴うアドレス表記では、経路が変わることがあります。「どのDNSサーバーを選ぶか」と「どの経路で接続するか」を分けて確認してください。

ドメイン名で指定する暗号化DNSサービスを使う場合は、最初の名前解決も考慮してください。サービスへ接続するには、そのサービス自体のアドレスを先に取得する必要があります。この処理がまだ確立していない同じ名前解決経路に依存すると、循環が起きることがあります。outboundsの接続先もドメイン名の場合、原因を見分けにくくなります。起動時に利用できる説明可能な名前解決経路を用意し、ログでサービスアドレスが先に解決されていることを確認してください。

DNSとルーティングの項目が制御する範囲
項目の場所制御する内容
dns.queryStrategyカーネルのDNS問い合わせで使うアドレスファミリー
routing.domainStrategyルーティングの照合時にドメインをIPアドレスへ解決するか
outboundsプロトコル内の名前解決方針outboundsが宛先ドメイン名を処理する方法。具体的な項目はプロトコルとカーネルによって異なる

設定を変更した後はキャッシュも考慮してください。アプリ、システム、カーネルがそれぞれ名前解決結果を保持していることがあり、どれか1つを再起動しただけでは動作がすぐに変わらない場合があります。テストでは問い合わせ先、アドレスファミリー、応答を記録し、新しい接続を作成してください。「アドレスを取得できなかった」のか、「アドレスは取得できたが接続に失敗した」のかを切り分けましょう。後者はルーティングやoutboundsも調べ、ドメイン名が関係しているというだけでDNSの問題と決めつけないでください。

7. policyとlog:接続方針とログの確認

policyのレベルは接続の優先順位ではない

policyでは、接続の処理方針や一部の統計機能を設定します。一般的な従来形式では、levelsを使ってユーザーレベルごとに項目をまとめます。ここでいうレベルは速度ランクではなく、特定の接続に高い帯域を割り当てる保証でもありません。プロトコルやユーザー設定から対応するレベルが実際に参照されている場合に限り、そのpolicyが接続に適用されます。使われていないレベルを完全に設定しても、動作中に自動的に有効になるわけではありません。

policyを「汎用の高速化設定」として一括適用しないでください。ハンドシェイクの制限時間、アイドル状態のタイムアウト、一方向のデータ待ち時間、バッファ設定は、それぞれ異なる問題に対応します。待ち時間を短くすると、不要な接続を早く終了できる一方、遅いハンドシェイクや長時間データがないアプリに悪影響が出る場合があります。値を大きくして接続状態を長く保持しても、リモート認証の失敗、DNS解決の失敗、ローカルの接続プロトコルの誤りは解決できません。

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

例では構造を示すためにレベル0を使っています。キー名は文字列で、各時間値は該当する項目の仕様に従って秒単位で指定します。説明用のパラメーター例であり、すべてのネットワークに推奨される組み合わせではありません。使用中のカーネルのデフォルト設定で要件を満たせる場合は、この部分を省略できます。測定結果に基づく理由がない場合は、出所のわからないpolicyを多数コピーするより、独自項目を減らすほうが後から管理しやすくなります。

タイムアウトは接続の状態に合わせて設定する

handshakeは該当する接続のハンドシェイク待ち時間、connIdleは接続がアイドル状態にある時間を制御します。uplinkOnlyとdownlinkOnlyは、片方向の処理が終了した後、もう一方を継続する際の待ち時間に関係します。対応するプロトコルや状態遷移は、使用中のカーネルのドキュメントで確認してください。これらを「ウェブページの読み込みが最大何秒かかるか」と単純に解釈したり、アプリ自体のリクエストタイムアウトの代わりにしたりすることはできません。

たとえば、長時間接続では、業務データがない間もアプリのハートビートによって接続を維持することがあります。アイドル時間の制限が短すぎると、接続が一定間隔で再確立される場合があります。その際はクライアントの値だけを際限なく大きくせず、アプリのハートビート、サーバー側のタイムアウト、中継するネットワーク機器も確認してください。変更前の値を記録し、変更後はアイドル時と連続通信時の両方をテストして、どの状態に影響したのかを調べましょう。

policy変更時に確認するポイント
設定確認する現象その設定だけでは判断できないこと
ハンドシェイクの待ち時間接続の確立段階で早期終了していないかリモートの認証情報が正しいこと
アイドル時の待ち時間業務データがない間に接続が再確立されないか継続通信の速度が必ず変化すること
統計機能の有効化該当する統計機能に必要な条件がそろっているかクライアント画面にすべてのカウントが必ず表示されること

ログレベルと統計機能は別々に設定する

ログは何が起きたかを示し、統計は特定の接続やユーザーのカウントを集計します。両者は同じ機能ではありません。統計機能によっては、policyの設定に加えて、トップレベルのstatsオブジェクト、対応するプロトコル識別子、読み取り用インターフェースが必要です。statsUserUplinkを有効にしただけで、GUIクライアントに対応する画面が表示されるとは限りません。クライアントが別の収集方法を使っている場合や、該当する統計を読み取らない場合もあります。

{
  "log": {
    "loglevel": "warning"
  }
}

通常は適度なログレベルにしておき、トラブル対処の際に、カーネルの対応範囲内で一時的に詳細度を上げてください。warningは警告やエラーの確認に適していますが、すべての接続先を記録するとは限りません。ルーティングを調べるには、アクセスログやクライアントが提供する接続記録も必要になることがあります。成功した接続がログにないからといって、通信がカーネルを通っていないとは限りません。まずログの記録範囲を確認しましょう。

ログファイルのパスを指定する場合は、ディレクトリが存在するか、実行ユーザーに書き込み権限があるか、クライアントがその場所を許可しているか確認してください。デスクトップOSとAndroidアプリでは書き込み可能なディレクトリが異なります。ほかのプラットフォームの絶対パスをそのまま使わないでください。トラブル対処のためにサービスへ過剰な権限を与える必要はありません。まずクライアントのログ画面を使い、必要な部分だけをエクスポートしてから、独立したファイルを設定するか判断しましょう。

ログには宛先ドメイン、リモートアドレス、認証に関する情報が含まれる場合もあります。共有する前に機密情報を項目ごとに隠し、エラーの種類、発生した段階、必要な項目のパスを残してください。テストが終わったら通常の記録範囲に戻し、ログファイルが大量に蓄積されないようにしましょう。症状をさらに確認する場合は、FAQのトラブル対処から該当する項目を探してください。警告ログの1行だけを根拠に設定全体を作り直すのは避けましょう。

8. 全体の検証、移行、トラブル対処

一度の速度テストで判断せず、階層ごとに検証する

全体を検証するには、設定ファイルを読み込めるか、カーネルが起動するか、アプリがinboundsに接続できるか、どのoutboundsが選ばれるか、リモートとのハンドシェイクが完了するか、宛先から実際に応答があるかを確認する必要があります。クライアントのテスト機能で確認できる範囲は、その一部に限られることがほとんどです。テストに一度成功しても、ブラウザーのプロキシが設定されたとは限りません。失敗した場合も、ノードがまったく使えないとは限りません。テスト対象や方法が実際の用途と異なる可能性があります。

最初に設定の構造と起動だけを確認します。ファイルを保存したら、クライアントの設定チェック機能か起動ログで解析結果を確認してください。オブジェクトの階層、項目のデータ型、カーネルが対応していない項目を重点的に調べます。エラーが出た場合は、まず最初に発生した有効なエラーを解決してください。後続のエラーは、最初の失敗から連鎖している可能性があります。起動に成功する前にDNSやルーティング分類を変更する必要はありません。それらの機能はまだ動作段階に入っていないためです。

次にinboundsを検証します。待ち受けポートとアプリの設定が一致していることを確認し、1つのアプリから新しいリクエストを送って、対応するログが残るか確認してください。接続がまったく記録されない場合は、システムプロキシ、アプリ内プロキシ、拡張機能による上書きを調べます。デスクトップのターミナルは通常、ブラウザーの設定を自動的に引き継ぎません。Androidアプリでは、アプリごとのプロキシ適用範囲が影響することもあります。この段階では接続経路を先に修正し、リモートの認証情報はまだ変更しないでください。

最小構成で接続の基本動作を確立する

3番目にoutboundsを検証します。リモートノードを1つとシンプルなルーティングだけを残し、正しいタグが選ばれているか確認してから、接続、通信ハンドシェイク、認証の各段階を調べてください。関連する項目だけをまとめて変更し、その都度新しい接続でテストします。ルーティングを追加してから使えていた設定が失敗した場合は、追加したルールを優先的に元に戻してください。カーネルを変更して初めて失敗した場合は、拡張項目とプロトコルの対応状況を先に確認し、ネットワーク条件を一度にすべて疑わないようにしましょう。

4番目にDNSとルールの適用を検証します。ドメインを指定するルール、IP判定が必要な宛先、どのルールにも一致しない宛先をそれぞれ選び、どこへ接続されるか確認してください。テスト対象には実際の用途に合うものを選び、想定するoutboundsも記録しましょう。ウェブページが開けるかどうかだけで判断しないでください。接続に成功しても設計どおりのoutboundsが選ばれなければ、ルールを調整する必要があります。放置すると、後続の通信が意図しない経路へ流れるおそれがあります。

失敗した段階に合わせて変更範囲を絞る
失敗した段階主な確認項目この段階では変更しない項目
ファイルの読み込みJSON構文、オブジェクトの階層、項目の対応状況サーバーの選択
ローカルからの接続待ち受け、ポート、アプリのプロキシ設定の参照元リモートの通信経路
outboundsへの接続アドレス解決、ポート、ネットワーク経路policyのタイムアウト設定
セキュリティまたはプロトコルのハンドシェイクサーバー名、認証情報、通信方式の組み合わせ無関係なドメイン分類
特定の宛先だけ失敗するルールの順序、名前解決結果、宛先の状態すでに検証済みの基本的な接続口

クライアント間の移行では最終的な設定を検証する

移行先の端末にファイルをコピーしただけでは完了しません。まず移行先のクライアントが実際に使用するカーネルを確認し、カスタム設定の読み込み方法、リソースデータのパス、ログのパス、ローカルの待ち受けアドレスを確認してください。デスクトップではv2rayNから始め、Androidでは用途に応じてv2rayNGまたはv2flyNGを選べます。インストール先はクライアントページ、クライアントごとの違いは選び方ガイドをご覧ください。

共有リンクやサブスクリプションをネイティブJSONに変換した場合、インポートに成功しても、すべての拡張項目が保持されたとは限りません。項目の編集画面でプロトコル、通信方式、セキュリティ層、フロー制御を確認し、最終的に実行される設定も確認してください。変換時は特にパスのエンコード、初期値の欠落、項目名の変更に注意しましょう。形式ごとの違いは、サブスクリプション形式とネイティブJSONの比較をご覧ください。

同じ端末で複数のクライアントを同時に実行すると、検証に影響することがあります。ポートを取り合ったり、システムプロキシの設定を繰り返し変更したり、カーネルプロセスが残って動作し続けたりする場合があります。テスト対象を切り替える前に、元の接続を正しく停止し、新しいクライアントが想定どおりの接続口を管理しているか確認してください。ウィンドウを閉じただけでサービスが終了したと判断したり、状況を記録せず不明なプロセスをまとめて終了したりしないでください。

テスト記録には、設定の入手元、使用中のカーネル、変更した項目、発生時刻、テストしたアプリ、失敗した段階を含めてください。認証情報の全体を記録する必要はありません。原因の層を特定できない場合は、最初の章の直結設定に戻り、リモートoutbounds、通信方式、ルーティング、DNSを順番に復元してください。各段階で動作する設定を保存しておけば、問題が起きたときに直近の正常な状態へ戻せます。設定を最初から組み直す必要はありません。