設定リファレンス · 体系的な確認マニュアル

V2Ray設定ファイル完全ガイド

JSONのトップレベル構造から始め、inbounds、outbounds、routing、dns、policyの処理関係、主要パラメータ、トラブルシューティングの範囲を順に解説します。

クライアントを初めて設定する場合は、まずはじめにに沿ってサブスクリプションのインポート、ノードの選択、接続確認を行ってください。このページでは、クライアントが生成した設定の理解、高度なパラメータの確認、ログに異常が出た際の該当設定箇所の特定を扱います。

このページの目次

01

JSONトップレベル構造と設定の読み込み順序

まずデータ型、タグ参照、処理チェーンを確認してから、個々のプロトコルパラメータを見ていきます。

トップレベルのオブジェクトは実行手順の一覧ではない

V2Rayの設定ファイルは、1つのJSONオブジェクトをルートとして構成されます。一般的なトップレベルフィールドにはlogdnsinboundsoutboundsroutingpolicystatsがあります。ファイル内での記述順は処理順序を変えません。カーネルは設定を読み込む際にオブジェクト全体を解析してから、リスニング入口、アウトバウンド、ルーター、名前解決器を構築します。routinginboundsより前に書いても、ルーティングがインバウンドより先に実行されるわけではありません。関連付けを決めるのはタグとルールの参照です。

inboundsoutboundsが配列なのは、1つのプロセスで複数のローカルポートを同時に待ち受けたり、複数の出口を保持したりできるためです。配列内の各オブジェクトには通常tagがあります。ルーティングルールはinboundTagoutboundTagbalancerTagを使ってこれらのタグを参照します。タグは同じ設定内で一意にし、socks-inproxydirectblockのように短く安定した名前を使うとよいでしょう。タグを変更したら、すべての参照先も確認してください。設定を解析できても、ルーティングの構築時に対象が存在しないと報告されることがあります。

読みやすい最小構成

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

この例では、ローカルのSOCKS入口と2つの基本的な出口だけを構成し、リモートプロキシへの接続は設定していません。構造の階層を確認するのに適しています。プロトコル固有のパラメータは対応するオブジェクトのsettingsに、トランスポート層のパラメータは通常streamSettingsに配置し、接続の多重化などの拡張機能は専用の子オブジェクトに入れます。別の階層のフィールドをsettingsへ移さないでください。JSON構文が正しくても、カーネルが対象外のフィールドを無視したり、デシリアライズエラーを報告したりする場合があります。

オブジェクト、配列、データ型

設定エラーはプロトコルではなく、JSONのデータ型が一致していないことが原因の場合も少なくありません。ポートは通常数値なので10808と記述し、文字列の"10808"にはしません。ブール値にはtrueまたはfalseを使い、引用符付きの文字列は使えません。ルール内のドメインやIP条件は多くの場合配列で指定するため、1項目だけでも角括弧を残します。オブジェクトのプロパティ間にはカンマが必要ですが、最後のプロパティの後に余分なカンマは置けません。全角引用符、不可視スペース、リッチテキストからコピーした曲線引用符も、正常に見える位置でパーサーエラーを引き起こします。

クライアントが設定を生成する際、サブスクリプションのノード、ルーティングプリセット、ローカルポートを最終ファイルに統合することがあります。v2rayNはWindows、macOS、Linuxでこのようなデスクトップ設定を確認・調整するのに適しています。Androidのv2rayNGとv2flyNGでは通常、画面で保存した設定を起動時に実行用設定へ変換します。画面上の名称は基底フィールドと完全に一致するとは限りません。たとえば「LANをバイパス」は最終的にgeoip:privateの直結ルールとして表現される場合があります。確認時は、画面のスクリーンショットではなく、クライアントが実際にエクスポートした実行設定とログを基準にしてください。

保守しやすい読み方を身につける

長い設定を読むときは、まずすべてのインバウンドとアウトバウンドのタグを書き出し、次にルーティングルールを1つずつたどって対象タグを確認し、最後にDNSとトランスポートパラメータを確認します。深い階層のフィールドから接続全体の挙動を推測しないでください。リクエストはまずインバウンドに入り、対象ドメイン、対象IP、ポート、場合によってはプロトコル識別結果を伴います。ルーターが条件に基づいてアウトバウンドを選び、アウトバウンドがプロトコルとトランスポート設定に従って接続します。DNSはルール照合時またはアウトバウンド接続時に関与することがあり、policyは接続統計、アイドルタイムアウト、セッション動作に影響します。この流れで読むと、「設定を読み込めること」と「接続を完了できること」を区別できます。

02

inbounds(インバウンド):ローカル待受と通信の入口

インバウンドは、どのアプリが接続できるか、どのローカルプロトコルを使うか、どの識別情報を伴ってルーターへ入るかを決めます。

listen、port、公開範囲

インバウンドオブジェクトで最初に確認するのはlistenportです。デスクトップクライアントが端末上のアプリにプロキシを提供する場合、通常は127.0.0.1で待ち受けます。これは現在の端末からのみ接続できることを意味します。外部ネットワークインターフェースから到達できるアドレスに変更すると、入口の公開範囲が変わるため、ローカルネットワークの境界、システムファイアウォール、認証も同時に検討する必要があります。ブラウザー、ターミナル、端末上のソフトだけにプロキシを提供するなら、待受範囲を広げる必要はありません。

ポートが他のプロセスに使用されていないことを確認してください。同じ設定内の2つのインバウンドも、同じアドレスで同じポートを待ち受けることはできません。一般的なクライアントはSOCKSとHTTPのインバウンドを別々に作成するか、混在型の入口を提供します。システムプロキシは通常HTTP入口を使用し、SOCKSに対応したアプリはSOCKSポートを直接指定できます。HTTPリクエストをSOCKSポートへ送ると、ログにハンドシェイクを認識できない、接続が閉じられた、リクエスト形式が不正といったエラーが出ることがあります。これはリモートノードの障害ではなく、ローカル入口のプロトコルを間違えている状態です。

SOCKSインバウンドとUDP

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

authはSOCKS入口の認証方式を制御します。ループバックアドレスだけで待ち受ける場合は、noauthを使うことがよくあります。udpはSOCKS UDPリクエストを受け付けるかどうかを決めます。この設定を有効にしても、すべてのアプリが自動的にUDPをプロキシへ渡すわけではありません。アプリ自体がSOCKS UDPに対応し、リモートプロトコルとトランスポート経路もその通信を処理できる必要があります。ipはUDPの関連付けで返すアドレスを指定するため、実際の到達方法と一致させてください。端末内の入口ではループバックアドレスが分かりやすく、他の端末から接続させる場合は、そのアドレスへリクエスト元が到達できるか再確認する必要があります。

HTTPインバウンドとシステムプロキシ

{
  "tag": "http-in",
  "listen": "127.0.0.1",
  "port": 10809,
  "protocol": "http",
  "settings": {
    "allowTransparent": false
  },
  "sniffing": {
    "enabled": true,
    "destOverride": ["http", "tls"],
    "routeOnly": true
  }
}

HTTPインバウンドは通常のプロキシリクエストとCONNECTトンネルリクエストを処理し、ブラウザーやシステムプロキシ設定に従うソフトに適しています。これはWebサイトのHTTPサーバーとは別物であり、アプリ側でプロキシポートとして指定する必要があります。ターミナルコマンド、開発ツール、バックグラウンドサービスはデスクトップのシステムプロキシを読み取らないことがあります。ブラウザーが接続できても、すべてのプログラムがこのインバウンドを通るとは限りません。「Webページは開くのにコマンドラインは直接接続する」場合は、まず対象プログラムのプロキシ設定または環境変数を確認し、その後V2Ray設定を確認してください。

sniffingの役割と限界

トラフィック検知は、一部の接続から対象ドメインを復元し、ドメインベースのルーティングルールを適用できるようにします。TLS接続を例にすると、アプリがローカルでドメインを解決してからIPアドレスへ接続する場合、インバウンドがIPしか見られず、ドメインルールだけでは一致しないことがあります。sniffingを有効にすると、カーネルはハンドシェイク情報から対象ドメインを識別できます。destOverrideは識別を許可するプロトコル種別を指定し、routeOnlyは識別結果を主にルーティング判定へ使い、最終接続先を強制的に置き換えないことを示します。

検知は汎用的な復号機能ではなく、すべての接続で識別可能なドメインが得られるとは限りません。非標準プロトコル、暗号化ハンドシェイクの変化、アプリ独自のカプセル化、IPへの直接アクセスでは、IP条件しか残らない場合があります。ルーティングではドメインルールとIPルールの両方を考慮し、検知結果だけに頼らないでください。特定のアプリで検知を有効にすると異常が出る場合は、そのインバウンドだけ検知を無効にするか、入口を独立したタグに分けてルールを個別に適用します。

複数のインバウンドを連携させる方法

複数のインバウンドは、通信元を区別する用途で特に役立ちます。たとえばブラウザー用にhttp-in、開発ツール用にsocks-inを用意し、inboundTagで異なるルーティングを設定できます。ドメインだけでアプリの種類を推測するより安定します。各入口には分かりやすいタグを付け、クライアント画面、システムプロキシ、アプリ設定の間でポートを一致させてください。v2rayNのローカルポートを変更しても、古いシステムプロキシ設定やターミナルの環境変数が必ず同期されるわけではありません。確認時は待受ログとアプリ側設定を同時に確認します。

入口の種類 主な用途 優先して確認する項目
SOCKS SOCKS対応のブラウザー、ターミナル、開発ツール プロトコル種別、ポート、UDP対応
HTTP システムプロキシとHTTPプロキシ対応ソフト CONNECT対応、システムプロキシのポート
独立した入口 アプリの種類ごとに異なるルーティングを適用 タグの一意性とinboundTagルール
03

outbounds(アウトバウンド):プロトコル、サーバー、トランスポート層

アウトバウンドは、リクエストが最終的にどこから出ていくか、リモート接続でどのプロトコル、認証パラメータ、トランスポート方式を使うかを定義します。

アウトバウンドタグと3種類の基本的な行き先

実用的な設定には通常、プロキシ、直結、ブロックの3種類のアウトバウンドを用意します。プロキシアウトバウンドはサブスクリプションまたは手動設定のリモートサーバーへ接続し、freedomアウトバウンドは対象へ直接アクセスし、blackholeアウトバウンドは一致した通信を終了します。タグにはそれぞれproxydirectblockなどを使用できます。タグ自体に特別な意味はなく、実際の動作はprotocolが決めます。ただし、安定した命名はルーティングルールを読みやすくします。

ルーティングルールに一致しない場合、配列の順序がデフォルトの出口に影響することがあります。曖昧なデフォルト値に依存しないよう、主要なプロキシアウトバウンドを分かりやすい位置に置き、LAN、ブロックリスト、直結対象には明示的なルールを記述してください。クライアントは設定生成時に、DNS専用出口やチェーンプロキシの中間出口などを追加することがあります。手動編集の前に、これらのタグが他のオブジェクトから参照されていないか確認し、名前だけで削除しないでください。

VLESSアウトバウンドの例

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

addressはリモートサーバーのアドレスで、ドメインまたはIPを指定できます。portはリモートの待受ポートです。users内のidは認証識別子で、サーバー側の設定と一致させる必要があります。VLESSのencryptionはプロトコルの要件に従って指定値を入力することが多く、トランスポート層のTLSとは別物です。flowはサーバー側で対応するフロー制御が明示的に有効な場合だけ設定し、別ノードの設定を考えずにコピーしないでください。

streamSettingsは、プロトコルデータをどのように運ぶかを定義します。networkはサーバー側と一致させる必要があります。securityはTLSなどのセキュリティ層を有効にするかどうかを決め、serverNameは証明書名とハンドシェイク先に使用します。リモートアドレス、ハンドシェイク名、実際の証明書名は異なる役割を持つ場合があります。頻繁に同じ値になるからといって、常に置き換えられるとは限りません。allowInsecureは証明書検証の動作を制御します。通常の設定では検証を有効にしてください。証明書名が一致しない場合は、検証を無効にして問題を隠すのではなく、ノードパラメータ、システム時刻、サーバー名、中間ネットワークを確認します。

REALITY接続パラメータの対応関係

{
  "streamSettings": {
    "network": "tcp",
    "security": "reality",
    "realitySettings": {
      "serverName": "www.example.com",
      "fingerprint": "chrome",
      "publicKey": "example-public-key",
      "shortId": "0123456789abcdef",
      "spiderX": "/"
    }
  }
}

REALITYの設定は通常realitySettingsに置かれます。serverNamepublicKeyshortIdとサーバー側設定には厳密な対応関係があり、どれか1つを間違えてもハンドシェイクに失敗することがあります。fingerprintはクライアントのハンドシェイクフィンガープリント設定で、カーネルとサーバー構成が対応する値を使用してください。例の公開鍵はフィールド形式を示すだけで、実際の接続には使用できません。

REALITYノードに接続できない場合は、ネットワーク到達性、時刻異常、パラメータ不一致、誤ったルーティングを切り分けます。まずリモートアドレスとポートに到達できることを確認し、次にサーバー名、公開鍵、短い識別子、フロー制御パラメータを確認します。最後に、対象サーバーのアドレスが直結またはブロックルールで誤処理されていないか確認してください。プロトコル名だけを見て設定を何度も切り替えても、根本原因は特定できません。

直結、ブロック、DNS専用アウトバウンド

[
  {
    "tag": "direct",
    "protocol": "freedom",
    "settings": {
      "domainStrategy": "UseIP"
    }
  },
  {
    "tag": "block",
    "protocol": "blackhole",
    "settings": {
      "response": {
        "type": "none"
      }
    }
  }
]

freedomは、現在の端末から対象へ直接接続することを示します。そのdomainStrategyは、ドメインを受け取ったアウトバウンドが解決するか、どのように解決するかを決めますが、トップレベルのrouting.domainStrategyとは別の制御点です。前者は直結アウトバウンドが接続を確立する段階で作用し、後者はルーティング照合段階で作用します。blackholeは一致した接続を終了するために使い、明確なブロックルールに適しています。ブロック後は通常アプリに接続失敗だけが返るため、blockに一致したかをルーティングログで確認してください。

サブスクリプションノードと手動設定の境界

v2rayN、v2rayNG、v2flyNGは、サブスクリプションの内容をそれぞれが対応するノードモデルへ変換し、基底のアウトバウンド設定を生成します。サブスクリプション更新でノードのプロトコルパラメータが上書きされることがあるため、自動生成ファイル内でサーバーフィールドを長期的に直接管理するのは避けてください。ローカルのルーティング、DNS、インバウンドを調整する場合は、クライアントが提供するカスタム設定、ルーティングプリセット、上書き機能を優先します。クライアントが対応しないフィールドは、使用中のカーネル系列がそのフィールドを認識するか確認してから、完全カスタム設定を使うか判断してください。

デスクトップでは、ノード管理、ルーティング設定、実行ログをまとめて確認できるv2rayNをまず選ぶと便利です。インストーラーはインストーラーページからプラットフォームに合うものを選んでください。Androidではカーネル要件に応じてv2rayNGまたはv2flyNGを選択できます。両者は設定生成の細部が異なる場合があるため、同じサブスクリプションを読み込んだ後も、それぞれの実行ログを基準にしてください。

04

routing(ルーティング):ルール照合と振り分け順序

ルーティングはプロトコルそのものを変更せず、リクエストの特徴に基づいて、定義済みのアウトバウンドへ通信を渡します。

ルールは上から順に照合される

routing.rulesは順序を持つ配列です。リクエストがルーターへ届くと、通常は上から順にルールを確認し、最初に一致したルールが対象アウトバウンドを決めます。そのため、範囲が狭く意図が明確なルールを前に、範囲の広いルールを後ろに置きます。たとえばLANの直結は広範なプロキシルールより前に、特定ドメインのブロックは一般的なドメインプロキシルールより前に置きます。すべてのポートを対象にしたプロキシルールを先頭に置くと、後ろのLAN直結ルールは適用されません。

ルールのtypeには通常fieldを使い、domainipportnetworkprotocolinboundTagなどの条件で対象を定義します。1つのルールに複数の条件を含めた場合、それらの条件を組み合わせて満たしたときに一致します。同じフィールド内の複数の値は通常、いずれか1つに一致すれば該当します。関係のない条件を同じルールに詰め込むと、想定より狭いルールになりがちです。分かりやすくするには、複数のルールに分け、それぞれに1つの目的を持たせます。

よく使う基本的な振り分け構成

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "domainMatcher": "hybrid",
    "rules": [
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "protocol": ["bittorrent"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "domain:example.net",
          "full:status.example.org"
        ],
        "outboundTag": "proxy"
      }
    ]
  }
}

geoip:privateは一般的なプライベートアドレス範囲に一致し、ルーター、プリンター、LANサービスへのアクセスがリモート経由になるのを防ぐのに適しています。geosite:privateは対応するプライベートドメインの集合を処理します。GeoIPとGeoSiteは異なるデータソースです。前者はIP範囲、後者はドメイン集合で分類します。データファイルが古いと分類結果も古くなるため、更新方法はGeoIPとGeoSiteデータファイルの更新方法を参照してください。

domain:は指定したドメインとそのサブドメインに一致し、full:は完全なホスト名だけに一致し、keyword:はキーワードで一致します。特定のサービスにはfull:を、サイト全体とサブドメインにはdomain:を優先します。キーワードは範囲が広く、無関係な似た名前のドメインまで誤って一致することがあるため、ログで確認した明確な用途に適しています。ルール内の通常の文字列は、カーネルや設定の文脈によって解釈が異なる場合があります。手動設定ではプレフィックスを使うと曖昧さを減らせます。

domainStrategyがドメインルールとIPルールに与える影響

AsIsは、ルーティング段階で元の対象をできるだけそのまま扱います。ドメインでリクエストが入ればドメインルールを照合できますが、IPしかないリクエストから名前を自動的に復元することは通常できません。IPIfNonMatchは、ドメインルールに一致しなかった場合にドメインを解決してIPルールを試します。IPOnDemandは、IPが必要なルールに遭遇した時点で、より早く解決を開始する場合があります。各戦略はDNS照会のタイミング、ルール一致、接続時間に影響するため、名前だけで選ばないでください。

ドメイン集合を優先し、IPの地理ルールを補助として使いたい場合は、IPIfNonMatchの方が理解しやすいことが多いでしょう。まずドメインを確認し、一致しなければ解決してIPを確認します。大量のIPルールがあり、早期にアドレスを取得したい場合はIPOnDemandを検討できます。ルーターがルール照合のために自動解決することを完全に避けたい場合はAsIsを使い、インバウンドの検知やアプリのリクエストから十分な対象情報が得られるようにしてください。

ポート、ネットワーク、インバウンドタグで振り分ける

{
  "type": "field",
  "inboundTag": ["socks-in"],
  "network": "tcp",
  "port": "443",
  "outboundTag": "proxy"
}

ポートには単一の値または範囲を指定でき、例として80,44310000-20000があります。ポートは対象サービスのポートを示すだけで、特定のWebサイトやアプリを表しません。多くのサービスが443を共有するため、ポートだけの振り分けは範囲が広くなりがちです。networkでTCPとUDPを区別でき、inboundTagではリクエストが入ったローカル入口に応じて振り分けられます。ソフトごとに独立した入口を用意し、インバウンドタグで処理する方が、プロセス名を推測するより汎用的です。

ルールに一致しない場合と誤って一致する場合

どのルールにも一致しない場合、リクエストはデフォルトのアウトバウンドへ進みます。デフォルト動作は設定構造とカーネル実装で確認し、必ず直結またはプロキシになると決めつけないでください。トラブルシューティングでは適切なレベルの実行ログを有効にし、リクエスト対象、インバウンドタグ、最終アウトバウンドタグを記録します。一致しない場合は、リクエストがドメインかIPか、ドメイン検知が機能しているか、Geoデータが存在するか、ルールのプレフィックスが正しいかを確認します。誤って一致した場合は、配列の先頭から対象をカバーする最初のルールを探します。

ルーティングを調整した後は、LANアドレス、直結予定のドメイン、プロキシ予定のドメイン、ブロック対象を1つずつ使って確認します。「ほとんどのWebページが開く」ことを振り分けの正しさの根拠にしないでください。デフォルト出口がルールの誤りを隠すことがあります。ノードの速度テストも、特定のテストリクエストが接続できたことを示すだけで、個別検証の代わりにはなりません。システムプロキシとターミナルで経路が異なる問題は、ブラウザーとコマンドラインを分けて確認する方法を参照してください。

05

dns設定:解決経路、サーバー選択、ルーティング連携

DNSはサーバーアドレスの一覧にとどまらず、ドメインルール、IPルール、最終的なアウトバウンド接続にも関係します。

システム解決と内蔵解決を区別する

アプリが接続を開始すると、ドメインはアプリまたはOSが先に解決する場合もあれば、ドメインのままローカルプロキシへ渡される場合もあります。前者ではインバウンドがすでにIPを受け取ることがあり、後者ではV2Rayの内蔵DNSとルーティング戦略が直接解決に関与できます。TUNモードを有効にすると、より多くのシステム通信がクライアントの処理チェーンに入る可能性がありますが、実際に内蔵DNSが処理するかは、クライアントが生成する入口、DNSリダイレクト、ルーティング設定によって決まります。

そのため、dns.serversを設定しただけで、端末上のすべての名前解決が自動的にそこを使うわけではありません。ブラウザー独自のセキュアDNS、アプリ内蔵のリゾルバー、システムキャッシュ、ターミナルツールが独立した経路を形成することがあります。解決の異常を調べるときは、まず3点を確認してください。誰が照会を開始したのか、どのサーバーへ送ったのか、返されたアドレスが最終的にルーティングルールで採用されたのか。経路を確認せずDNSサーバーだけを変更すると、設定を変えても現象が変わらないことがあります。

基本的なDNSオブジェクトの例

{
  "dns": {
    "hosts": {
      "domain:internal.example": "192.0.2.10"
    },
    "servers": [
      {
        "address": "1.1.1.1",
        "domains": ["geosite:geolocation-!cn"],
        "skipFallback": true
      },
      {
        "address": "223.5.5.5",
        "domains": ["geosite:cn"],
        "expectIPs": ["geoip:cn"]
      },
      "localhost"
    ],
    "queryStrategy": "UseIP"
  }
}

hostsは静的なドメインマッピングを提供し、管理下のテストや固定された内部アドレスに適しています。変化し続けるパブリックDNSの代用にはなりません。例のアドレスは構造の説明用です。serversには単純なアドレスだけでなく、ドメイン範囲、期待するIP範囲、フォールバック制御を追加したオブジェクト形式も指定できます。リストの順序と一致条件が、問い合わせ先を決めます。複数のサーバーを指定しても、すべてが単純に同時競争するわけではありません。ドメイン条件、フォールバックロジック、カーネル実装によって動作は変わります。

domainsは、特定のサーバーが優先的に処理するドメイン集合を指定し、構文はルーティングのドメインルールに似ています。expectIPsは返されたアドレスが想定する分類に一致するか確認するためのもので、汎用的なアドレスフィルターの代わりではありません。結果が条件を満たさない場合、リゾルバーは別のサーバーを試すことがあります。データファイルがない、または古い場合、Geo分類に基づく判定の精度も低下します。skipFallbackはそのサーバーがフォールバックに参加するかどうかに影響するため、各項目を一律に有効にせず、現在のサーバーグループを理解してから設定してください。

queryStrategyとアドレスファミリーの選択

queryStrategyは問い合わせに使用するアドレスファミリーの戦略を制御します。一般的には、利用可能なアドレスを同時に考慮する、IPv4のみを使う、IPv6のみを使うといった意味があります。利用できる値は現在のカーネルの対応状況に合わせてください。アドレスファミリーの選択は端末のネットワーク条件に適合させる必要があります。ローカルネットワークに利用可能なIPv6経路がないのにIPv6だけを強制すると、ドメインの解決には成功しても接続は失敗します。逆に、特定のアドレスファミリーだけ到達可能なネットワークで、デフォルトの結果に任せることもできません。

デュアルスタック環境での失敗は、「複数のアドレスが解決されたものの、アプリやアウトバウンドが到達不能なアドレスを優先して試した」ことが原因の場合もあります。その場合はDNSの応答、アウトバウンドの選択、接続ログを同時に確認してください。毎回のタイムアウトをDNSのせいにしないでください。解決ログにアドレスが出ていて接続段階でタイムアウトしているなら、問題はすでにアウトバウンドのネットワークまたはリモートサービスの段階にあります。反対に、ドメイン照会の失敗、利用可能なレコードがない、期待条件をすべて満たさないとログに出ている場合に、DNSを重点的に調べます。

DNSの問い合わせはどのアウトバウンドを通るか

DNSサーバー自体も接続先であり、ルーティングルールによって直結またはプロキシのアウトバウンドへ渡されます。DNSサーバーをドメインで指定すると、「DNSサーバーのドメインを解決するための前段解決」が必要になることもあります。循環依存を減らすため、基本DNSサーバーには直接接続できるIPを使うか、専用アウトバウンドと明示的なルーティングルールで処理することが多いでしょう。HTTPSベースの解決エンドポイントを使う場合は、エンドポイントのドメイン、証明書名、それ自体の解決経路も考慮します。

DNS問い合わせ用に独立したアウトバウンドタグを設定し、プロトコル条件やインバウンドタグでルーティングできます。ただし経路は明確に保ってください。リクエストが内蔵DNSに入り、DNS問い合わせが指定アウトバウンド経由でサーバーへ送られ、結果がルーターに返って照合に使われ、最終的な通信が業務用アウトバウンドを通る、という流れです。DNS問い合わせを、同じDNS結果がないと接続できないプロキシアウトバウンドへ誤って送ると、起動時に循環待ちが発生する可能性があります。クライアントのプリセットは通常、基本的な依存関係を処理します。手動で上書きするときは、不慣れなDNSルーティングを削除しないでください。

キャッシュ、Fake DNS、TUNの場面

システムキャッシュ、アプリキャッシュ、内蔵リゾルバーのキャッシュが同時に存在することがあります。DNSを変更してすぐ同じドメインへ再アクセスしても、古い結果が直ちに消えるとは限りません。確認時は対象アプリとクライアントを再起動するか、まだ問い合わせていない新しいドメインで一連の流れを観察してください。TUNモードでは、Fake DNSがドメインを予約アドレスにマッピングし、通信が入った時点でドメインへ戻してドメインルーティングを可能にすることがあります。このような予約アドレスを実際のリモートIPとみなしたり、GeoIP分類の判定に直接使ったりしないでください。

Fake DNSは、システムへIP通信だけを渡すためドメイン情報が不足する問題の解決に適していますが、DNSの引き継ぎ、マッピングテーブル、TUNインバウンドの整合性が必要です。アプリがアドレスを取得しても接続できない場合は、同じ実行インスタンスがマッピングを認識しているか、リクエストがTUNを迂回していないか、予約アドレスが他のルールによって先に直結されていないかを確認します。TUNによるシステム全体の通信取り込みとクライアント入口については、TUNモードで全通信を取り込む仕組みを参照してください。

06

policy(ポリシー):セッションタイムアウト、統計、システム制御

policyはノードを選択するものではなく、接続のライフサイクルと統計情報に実行上の境界を設定します。

levelsとユーザーレベルの参照

policy.levelsはユーザーレベルをキーとして、該当レベルの接続にポリシーを設定します。一部のインバウンドまたはアウトバウンドプロトコルでは、ユーザーオブジェクトにlevelを持たせ、実行時に同じ名前のポリシーを参照できます。レベルは速度の評価でも権限の高低でもなく、ポリシー集合を参照するための数値キーです。ユーザーにレベルを明示しない場合は通常デフォルトレベルが使われますが、具体的な動作は現在の設定とカーネル実装で確認してください。

同じレベルで、ハンドシェイク時間、接続アイドル時間、上り下りの統計などを統一的に制御できます。「完全に見えるようにする」ためだけに、参照されないレベルを大量に作らないでください。クライアントが生成する単一ユーザーのアウトバウンドでは、通常、デフォルトレベルで統計が有効か、タイムアウトが変更されているかを理解すれば十分です。サーバーで複数ユーザーを扱う場合はレベルを使い分ける機会が増えますが、このページではクライアント設定の読み方を重視するため、正常な接続を意図せず短縮していないかに注目してください。

ポリシーオブジェクトの例

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

handshakeは接続確立段階で待機できる時間を制限します。短すぎると、ネットワークの揺らぎ、名前解決、リモートハンドシェイクのわずかな遅延で途中終了することがあります。長すぎると、到達不能な接続の失敗通知が遅れます。connIdleはデータ転送がない状態で接続を維持できる時間を示します。長時間接続、メッセージプッシュ、リモートターミナル、継続的な転送ツールはアイドル時間の影響を受けやすく、Web閲覧だけを基準に調整しないでください。

uplinkOnlydownlinkOnlyは、一方向のデータだけが残った後に接続を維持する時間を処理します。接続のライフサイクルを管理するもので、帯域幅の制限ではありません。bufferSizeは接続ごとのデータバッファ戦略に影響します。むやみに大きくするとメモリ使用量が増え、むやみに小さくするとスループットに影響することがあります。多くのクライアント利用者はカーネルまたはクライアントのデフォルト値を維持し、ログと再現可能なテストで接続ライフサイクルが原因と確認できた場合だけ調整してください。

統計スイッチは対で理解する

statsUserUplinkstatsUserDownlinkはユーザー単位の統計を制御し、policy.system内の項目はインバウンドとアウトバウンド単位の統計を制御します。"stats": {}と書くだけで、すべての指標が自動収集されるとは限りません。対応するpolicyのスイッチも有効にする必要があります。反対に、統計を有効にしても、それを読む画面やAPIがなければ余分な記録処理が発生するだけです。デスクトップクライアントが通信量を表示するかどうかは、カーネルの起動方法と統計インターフェースの読み取り方法にも左右されます。

統計値は現在の実行インスタンスにおける通信方向の確認に適しており、サブスクリプションの上限、請求記録、リモートサーバー通信量の公式な情報源ではありません。クライアントの再起動、設定の再読み込み、カーネルの切り替えによって、ローカル統計が最初から始まることがあります。「画面に通信量が表示されない」場合は、まずクライアントが基底の統計を読み取る設計か確認し、次にstatsオブジェクトとsystemスイッチを確認してください。いきなりプロトコルパラメータを変更しないでください。

policyとタイムアウトエラーの関係

ログのtimeoutは、名前解決、TCP接続、TLSまたはREALITYハンドシェイク、プロキシプロトコルのハンドシェイク、アプリケーションの読み書きなど、さまざまな段階で発生します。policyで説明できるのは、そのうち一部のセッションタイムアウトだけです。接続が毎回ほぼ同じ短時間で切れるならhandshakeconnIdleを確認します。リモートアドレスへの接続タイムアウトが明示されているなら、まずネットワークとアウトバウンドを確認します。特定のアプリの長時間接続だけが定期的に切れるなら、そのアイドル周期とポリシー値を比較してください。

タイムアウトを変更する前に、エラーが発生した段階と時間的なパターンを記録してください。すべての値を単純に大きくすると、障害の通知が遅れ、失敗した接続が長時間リソースを占有します。逆に一律に小さくすると、低速ネットワークや長時間接続に悪影響が出ます。デフォルトポリシーを基準として保ち、再現できる状況で1項目だけ調整し、クライアント再起動後に同じ対象を再テストするのが適切です。

システムポリシーと設定の移植性

クライアントやカーネル系列が異なると、対応するポリシーフィールドやデフォルト値も異なる場合があります。v2rayNの実行カーネル、v2rayNGで一般的なXrayカーネル、v2flyNGに対応するv2flyカーネルは、共通フィールド以外にも動作差が存在する可能性があります。完全な設定を別のクライアントへコピーする前に、対象クライアントが完全カスタム設定を許可するか、起動時にpolicyを書き換えないか確認してください。

設定の移植性で重要なのは、フィールドを減らすことではなく、標準構造、カーネル拡張、クライアント生成内容を明確に区別することです。インバウンドポート、ログパス、TUNパラメータなどはプラットフォーム環境に依存しやすく、サーバーのプロトコルパラメータは移行できることが多い一方、クライアント画面の状態と実行設定は必ずしも一致しません。プラットフォーム間で移行するときは、まずサブスクリプションを読み込んで動作する基準を作り、その後ルーティング、DNS、ポリシーを項目ごとに移行する方が、ファイル全体を直接上書きするより不互換なフィールドを見つけやすくなります。

07

設定の読み込み、クライアントによる上書き、検証の流れ

構文検証、構造検証、実際の接続検証を分けると、問題の範囲をすばやく絞り込めます。

第1段階:JSONを解析できることを確認する

構文検証で分かるのは、設定が有効なJSONかどうかだけです。二重引用符、カンマ、角括弧、波括弧が対応しているか、数値、ブール値、文字列の型が正しいかを重点的に確認します。JSONはコメントとオブジェクト末尾の余分なカンマを許可しません。Webページ、チャット、文書から設定をコピーするときは、曲線引用符や不可視の制御文字を避けるため、まずUTF-8のプレーンテキストファイルとして保存してください。

構文エラーには通常、行番号と列番号が示されますが、実際の原因は前の行にあることがあります。新しいプロパティの先頭でパーサーがエラーを報告する場合、前の項目末尾のカンマ抜けがよくある原因です。ファイル末尾のエラーなら、オブジェクトや配列が閉じられていない可能性を優先して確認します。エディターの括弧対応機能は役立ちますが、データ型とフィールド階層の確認に代わるものではありません。

第2段階:タグとフィールドが正しい位置にあることを確認する

有効なJSONでも、正しいV2Ray設定とは限りません。第2段階では、トップレベルのフィールド名、プロトコル固有のsettings、トランスポート層のstreamSettings、ルーティング参照を確認します。よくある構造エラーには、tlsSettingsをアウトバウンドのルートに置く、単一のアウトバウンドを配列ではなくオブジェクトで記述する、存在しないoutboundTagをルールで参照する、文字列の配列を単一の文字列として記述するといったものがあります。

未知のフィールドの扱いはカーネルによって異なります。読み込みを拒否する場合もあれば、フィールドを無視する場合もあります。すぐにエラーにならず無視される方が、設定は起動したように見えるのに期待した機能が動かず、調査が難しくなります。ログにunknown field、failed to parse、failed to build、タグが見つからないなどの表示が出たら、ネットワーク接続のテストを続けるのではなく、該当オブジェクトの階層に戻って確認してください。

第3段階:クライアントが実際に読み込んだ設定を確認する

v2rayN、v2rayNG、v2flyNGは、画面の設定に基づいて起動時に実行用設定を生成することがあります。特にサブスクリプションノード、ルーティングプリセット、システムプロキシ、TUNモードを併用している場合、ユーザーが編集したファイルがカーネルの最終的な読み込み対象とは限りません。検証前に、クライアントログで設定生成とカーネル起動が成功したかを確認し、クライアントが提供するエクスポート、プレビュー、実行ディレクトリの入口を確認してください。

サブスクリプション更新では通常ノードパラメータが置き換わりますが、ローカルルーティングまで置き換わるとは限りません。完全カスタム設定では、一部の画面設定が反映されないこともあります。現在の方式が「サブスクリプションノードとクライアントテンプレート」なのか、「完全カスタム設定」なのかを明確にしてください。2つの方式が混在すると、画面でポートを変更しても実行ファイルが変わらない、手動ルーティングがプリセットで再生成される、といった問題が起こりがちです。サブスクリプション更新失敗の個別の確認方法は、サブスクリプション更新失敗と自動更新の設定を参照してください。

段階的に接続の基準を作る

  1. 起動を確認:カーネルの起動が完了し、ローカルのSOCKSまたはHTTPポートが待ち受けており、ポート競合や設定解析エラーがないことを確認します。
  2. ローカル入口を確認:プロキシに対応したアプリからローカルポートへ接続し、アクセスログに該当するインバウンドタグが現れるか確認します。
  3. 単一アウトバウンドを確認:一時的に単純なルーティングを使い、複雑なルールに邪魔されず、対象リクエストがプロキシアウトバウンド経由で接続できることを確認します。
  4. DNSとルーティングを戻す:LAN、ドメイン、GeoIP、ブロックルールをグループごとに追加し、毎回リクエストが最終的にどのアウトバウンドを使ったか記録します。
  5. システム取り込みを戻す:最後にシステムプロキシまたはTUNを有効にして、より多くのアプリを処理チェーンへ入れ、ブラウザーとターミナルを個別に確認します。

この順序により、問題を起動、ローカル入口、リモートアウトバウンド、振り分け、システム取り込みの5層に分けられます。第1層が完了していないならリモートプロトコルを分析する必要はありません。ローカル入口がリクエストを受けていないならアプリのプロキシ設定を確認します。単純なアウトバウンドが使えてルーティングを戻すと失敗するなら、問題はDNSまたはルールに絞られます。手動プロキシは使えるのにシステム取り込み後に異常が出るなら、システムプロキシの状態、TUN権限、ルーティングの競合を重点的に確認します。

ログレベルと読みやすい情報

log.loglevelは、トラブルシューティング中により詳しいレベルへ変更できます。詳細なログほどインバウンド、ルーティング、アウトバウンドを観察しやすくなりますが、出力量も増えます。通常利用で高い詳細度を長期間維持する必要はありません。調査ログは明確な1回のテストを中心に、カーネル起動から対象リクエストの成功または失敗までを切り出してください。大量の過去ログの中で異なる設定を混同しないようにします。

{
  "log": {
    "access": "",
    "error": "",
    "loglevel": "info",
    "dnsLog": true
  }
}

ログ設定の具体的なパスと出力方法は、クライアントが管理する場合があります。空文字列がコンソール出力を意味するかどうかも、現在のカーネルとクライアントの動作で確認してください。dnsLogは内蔵DNSの解決過程を観察するのに役立ちますが、内蔵DNSを通った問い合わせだけが表示されます。ログの詳しい読み方はV2Ray実行ログのよくあるエラーと原因の特定を参照してください。

変更履歴を残す方が試行錯誤を繰り返すより効果的

各テストでは1つのフィールドグループだけを変更し、変更前の値、変更後の値、テスト対象、ログ結果を記録します。たとえばdomainStrategyAsIsからIPIfNonMatchへ変更したら、IPルールが必要なドメインだけを確認します。ノード、DNSサーバー、TUNモードを同時に変更しないでください。結果が悪化しても正確に元へ戻せ、改善した場合もどの変更が効いたか分かります。

クライアントをアップグレードしたりカーネルを切り替えたりした後は、古い設定がすべて互換だと決めつけず、最小検証手順をもう一度実行してください。固定のバージョン番号を根拠にフィールドの対応可否を推測したり、依存したりしないでください。現在のクライアントが選択しているカーネル種別、起動ログ、設定エラーを確認します。クライアントを再インストールする場合は、インストーラーページからWindows、macOS、Android、Linuxに対応する入口を選んでください。

08

よくあるエラーの特定と長期保守の方法

設定全体でランダムにスイッチを切り替えるのではなく、エラーが発生した階層から対処します。

起動に失敗する:まず構文、ポート、参照を確認する

カーネル起動直後に終了する場合は、まず3種類の問題を確認します。1つ目は、カンマ抜け、括弧の不一致、データ型の誤りなどのJSON構文エラーです。2つ目は、別プロセスによる待受ポートの占有、書き込み不可のログディレクトリ、作成できないTUNデバイスなど、ローカルリソースの競合です。3つ目は、ルーティング先タグが存在しない、プロトコル設定に必須フィールドがない、現在のカーネルが拡張項目を認識しないなど、設定オブジェクトの参照エラーです。

処理の順序はログに合わせます。解析エラーが読み込み段階で発生したなら、まずファイルを修正します。アドレス使用中のエラーが待受段階で発生したなら、重複クライアントとローカルポートを確認します。アウトバウンドが見つからないエラーがルーティング構築段階で発生したなら、タグを確認します。カーネルが明確に実行状態へ入ってから、リモート接続の調査に進んでください。クライアント画面に「未接続」と表示されるだけでは層を判断できないため、最後のエラーログを確認する必要があります。

ローカルポートは存在するのにアプリの通信がない

まず、アプリに正しいプロキシ種別とポートが入力されているか確認します。HTTPプロキシとSOCKSプロキシは別の入口であり、システムプロキシを設定してもターミナルやバックグラウンドサービスが自動的に使うとは限りません。次に、アプリがローカルアドレスをバイパスしていないか、独自の解決やプロキシ設定を有効にしていないか、リクエストが実際にaccessログへ到達しているかを確認します。今回のリクエストがログにまったくないなら問題はアプリとインバウンドの間にあり、インバウンド記録が出て初めて通信がV2Rayへ入ったと判断できます。

一部のアプリだけ動作しない場合は、問題のアプリに明示的なSOCKSまたはHTTP入口を設定して比較します。手動入口は使えるのにシステムプロキシが使えない場合は、OSのプロキシ状態と除外リストを確認します。システムプロキシではブラウザーが使えるのにターミナルが使えない場合は、ターミナルツールが対応するプロキシ設定を指定してください。1つのアプリがシステムプロキシを回避するからといって、リモートノードのプロトコルを変更しないでください。

ドメインは失敗するがIPは使える

この現象では、まず解決経路を確認します。アプリがドメインを送っているのか、すでに解決済みのIPを送っているのか、内蔵DNSが問い合わせを受けているのか、サーバーが利用可能なアドレスを返しているのか、queryStrategyが現在のネットワークで到達可能なアドレスファミリーを選んでいるのかを確認してください。ドメインルールが検知に依存する場合は、インバウンドが対象名を識別できるかも確認します。Fake DNSを使っているなら、予約アドレスが同じ実行インスタンスで復元されているか確認してください。

DNSがすでにアドレスを返しているのにアウトバウンド段階で接続がタイムアウトするなら、問題は「解決結果がない」ことではなく、そのアドレスへの接続経路、ルーティング、リモートサービスにあります。返されたアドレスがexpectIPsで期待外れと判定された場合は、Geoデータとサーバーグループを確認します。変更したばかりのドメインだけが古いアドレスを使うなら、アプリ、システム、内蔵キャッシュを考慮し、関連プロセスを再起動するか新しいドメインでテストしてキャッシュの影響を切り分けてください。

ルールは正しそうなのに一致しない

まずリクエストの実際の形を確認します。ルーターが受け取ったのは完全なドメイン、サブドメイン、IPのどれか。ルールはfull:domain:、キーワードのどれを使っているか。前に範囲の広いルールがあり、先に一致していないか。Geoデータファイルが利用可能か。ルールの文字列と対象が似ていても、照合の意味が同じとは限りません。full:example.comは他のサブドメインには一致せず、広すぎるキーワードは無関係な対象にも一致することがあります。

問題のルールを一時的に配列の前方へ移動すると、他のルールに隠されているかを判断できます。ただしテスト後は全体の順序を改めて確認してください。より確実なのは、ルーティング関連のログを有効にし、リクエストが最終的に選択したアウトバウンドタグを記録することです。リクエストがIPしか持たないなら、ドメインルールに一致しないのは自然です。その場合はsniffing、アプリの解決方式、適切なIPルールの追加を確認し、同じドメイン文字列だけを書き換え続けないでください。

ノードパラメータは正しいのにハンドシェイクに失敗する

まずサーバーアドレスとポートに到達できることを確認し、次にプロトコルの認証パラメータ、トランスポート方式、セキュリティ層を確認します。TLSではサーバー名、システム時刻、証明書エラーを確認します。REALITYではサーバー名、公開鍵、短い識別子、フィンガープリント、フロー制御パラメータを確認します。他のプロトコルでも、クライアントとサーバーのパラメータを項目ごとに一致させてください。異なるノードのトランスポートフィールドを組み合わせて1つの設定を作らないでください。各層に依存関係がある可能性があります。

サブスクリプション更新後に突然失敗した場合は、古いノードを比較用に残し、更新でアドレス、ポート、トランスポート方式、認証パラメータが変わっていないか確認します。不足しているフィールドを推測して手入力しないでください。すべてのノードが同時に失敗するなら、まずローカルネットワーク、システム時刻、カーネル起動、ルーティングを確認します。単一ノードだけの失敗なら、そのノードのパラメータまたはリモート側の状態である可能性が高くなります。

設定が肥大化した後の整理原則

長期間使うと、無効になったタグ、重複したドメインルール、互いに上書きするGeoルール、使わなくなったインバウンドが設定に蓄積します。整理するときは、まず現在の処理チェーンを図にします。すべてのインバウンドタグ、アウトバウンドタグ、各ルールの対象、DNSサーバーの用途を書き出してください。参照されていないことを確認してからオブジェクトを削除します。同じ対象と同じ出口のルールは統合できますが、行数を減らすために異なる目的の条件を1つの説明しにくいルールへ詰め込まないでください。

タグには安定した命名規則を設け、ルーティングは「特別なブロック、LAN直結、特定プロキシ、デフォルト処理」の順に並べることを推奨します。DNSサーバーオブジェクトは適用するドメイン範囲ごとにまとめ、policyには実際に使うレベルだけを残します。設定ファイル自体がコメントに対応していない場合は、独立した保守記録に各タグの用途、最後に確認した状況、クライアントによる生成方法を記録しておくと、後からフィールドを変更しやすくなります。

クライアントの更新と設定移行

クライアントを更新する前に、現在動作している設定、ルーティングプリセット、サブスクリプション設定を保存します。更新後はまず既存ノードで最小限の接続テストを行い、その後に高度な機能を確認します。クライアントが実行カーネルを切り替えた場合は、起動ログの未知フィールドや非推奨の警告に注目してください。画面の項目名が変わったからといって、すぐに基底設定を削除しないでください。新しく生成された実行ファイルをエクスポートし、旧設定とトップレベルの各セクションを比較します。

デスクトップから別のデスクトッププラットフォームへ移行する場合、サーバーのプロトコルパラメータは通常サブスクリプションから復元できますが、ローカル待受ポート、システムプロキシ、TUN権限、ログパスは新しいプラットフォームで再設定が必要です。Androidでv2rayNGまたはv2flyNGへ移行する場合も、まずサブスクリプションを読み込み、対象カーネルに合わせてルーティングとDNSを復元します。プラットフォーム差は主にシステム取り込みとファイルの場所に現れるため、サーバーアウトバウンドへプラットフォームと無関係な推測フィールドを追加しないでください。

固定のトラブルシューティングチェックリストを作る

起動層

JSON、フィールド階層、ポート競合、タグ参照、実行権限。

入口層

アプリのプロキシ種別、ローカルポート、システムプロキシ、TUNによる取り込み、アクセスログ。

解決・ルーティング層

ドメインまたはIP、DNSの応答、ルールの順序、Geoデータ、最終アウトバウンドタグ。

アウトバウンド層

サーバーへの到達性、認証パラメータ、トランスポート方式、セキュリティ層、ハンドシェイクログ。

すべての障害をこの4層の順に記録すると、同じ調査を繰り返さずに済みます。ログにrejectedが出たら、拒否がローカル入口、ルーティングブロック、リモートのどこで起きたかを確認します。timeoutならタイムアウトの段階を確認し、認証やハンドシェイクのエラーなら該当するアウトバウンドパラメータに戻ります。それでも判断できない場合は、トラブルシューティングで基礎知識、インストールと設定、活用テクニック、トラブルシューティングの分類から探してください。

設定保守の目的は、オプションのフィールドを詰め込むことではなく、各部分の役割を明確にし、ログで処理結果を証明できるようにすることです。まず簡単で再現性のある基準設定を保ち、その後ルーティング、DNS、TUN、ポリシーを追加します。問題が起きたら基準へ戻って段階的に復元する方が、複雑な設定からランダムにフィールドを削除するより確実です。