設定項目 / JSON リファレンス

V2Ray 設定ファイル
構造と項目のリファレンス

接続の流れに沿って項目を確認します。入口、出口の順に調べ、最後にルーティング、名前解決、policyを確認します。

リクエスト処理の流れ
  1. inboundsアプリからの接続を受け付ける
  2. routingルールに従って出口を選ぶ
  3. outbounds直接接続・プロキシ・遮断

dnsは名前解決を担い、policyは接続の動作を制御します。必ずしも決まった順に処理されるわけではありません。

クライアントを初めて使う場合は、導入ガイドに沿ってインストール、サブスクリプションのインポート、接続確認を行ってください。このページでは接続後の設定を確認し、各項目を読み込むコンポーネントや配置する階層、変更の反映確認方法を解説します。デスクトップでは、まずv2rayNのGUI設定を確認してください。Androidではv2rayNGまたはv2flyNGの設定表示も参考になります。クライアントをインストールする場合は、クライアントのダウンロードからプラットフォームを選択してください。

このページでは、V2RayとXrayで一般的なJSON設定を共通の土台として扱います。両カーネルですべての項目が共通とは限らず、クライアントの画面上の名称も異なる場合があります。まず実際に使用中のカーネルを確認し、対応する項目を調べてください。最初の章にある本機用の完全な例を除き、コード例には適用範囲を記載しています。部分的な設定オブジェクトを、そのまま完全な設定として実行しないでください。

01 / JSONの構造と設定の管理元

クライアント設定とカーネル設定を見分ける

まず、現在の設定がどこから読み込まれているかを確認してから、変更する場所を決めましょう。v2rayN、v2rayNG、v2flyNGはGUIクライアントで、サブスクリプションの管理、設定の選択、カーネルの起動を担当します。接続の受け付け、ルーティングの判定、データの転送を実行するのはカーネルです。画面に保存されたサブスクリプションURLやウィンドウ設定、自動更新のスケジュールが、カーネルのJSON設定に含まれるとは限りません。クライアントの設定ファイルをカーネル設定として編集すると、項目が存在するのに実行結果が変わらないことがあります。

次に、設定がクライアントによって自動生成されていないか確認してください。ノードの切り替え、ルーティングの変更、再起動などを機に、クライアントが実行用設定を書き換えることがあります。一時ファイルを直接編集しても、次回の生成時に変更が失われがちです。長期的に使う設定は、まずGUIから行ってください。JSONをカスタマイズする必要がある場合は、クライアントが明示的に対応しているカスタム設定の入口を使い、元のファイルも保存しておきましょう。エクスポート、表示、編集は別々の操作です。JSONが表示されていても、その場所で変更を永続化できるとは限りません。

オブジェクトと配列で階層を把握する

最上位は、役割の異なるオブジェクトの集まりとして捉えます。複数の入口や出口を設定できるため、inboundsとoutboundsは配列です。一方、routing、dns、policyは通常、それぞれの詳細設定を収めるオブジェクトです。オブジェクトは波括弧、配列は角括弧で囲みます。項目名と文字列には半角の二重引用符を使い、数値と真偽値には引用符を付けません。ポートは数値、スイッチはtrueまたはfalseで記述し、すべて文字列に変換しないでください。

以下は、本機で単独実行できる直接接続の例です。構造を理解するためのもので、本機にSOCKSの入口を用意し、受け取った接続をシステムのネットワークへ直接渡します。リモートプロキシへの接続は行いません。テストするアプリを本機のポートに接続してから、カーネルがリクエストを受け取るか確認してください。リモートサーバーの設定は含まれていないため、サブスクリプションの接続設定の代わりにはなりません。クライアントで使う場合は、既存の待ち受けポートと競合しないようにしてください。

{
  "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の構文を確認しましょう。よくあるミスは、最後の項目の後に余分なカンマがある、全角の引用符をコピーしている、オブジェクトを削除する際に括弧を一段分しか削除していない、といったものです。このページの例は標準JSONを使用しており、コメントは含みません。エディターでファイルを開けるのは、テキストが読み取れるというだけです。構文チェックに通っても、確認できるのは構造が正しいことだけです。項目がカーネルに認識されるか、プロトコルが対応しているか、接続先に到達できるかは、それぞれ別に検証してください。これらをまとめて「設定は正常」と判断しないようにしましょう。

変更のたびに、どのオブジェクトを変更したか、どの接続が変わる想定か、元に戻すにはどうするかを簡潔に記録してください。一度に変更するのは一つの役割に絞り、DNS、ルーティング、通信方式を同時に切り替えないようにしましょう。重複して見える項目がある場合は、まずそれぞれの配置パスを確認してください。routing内の名前解決方針とoutbounds内の名前解決方針は、異なる段階で使われることがあります。項目名が同じでも役割が同じとは限りません。親オブジェクトを含めて確認してください。

02 / inboundsと待ち受け範囲

アプリからカーネルへの接続方法を確認する

inboundsは、カーネルが接続を受け付ける入口です。アプリがシステムプロキシを使うのか、個別にSOCKSを設定しているのか、クライアントの仮想ネットワークインターフェースで通信を処理しているのかを確認してから、対応する設定を調べましょう。デスクトップアプリは、本機のHTTPまたはSOCKSポートを経由してカーネルに接続することがよくあります。AndroidのVPNモードでは、クライアントがシステムインターフェースと連携して通信を処理します。JSONにSOCKSポートがあるだけで、すべてのアプリがその入口を通るとは限りません。入口に接続が届いていない場合、outboundsを変更しても解決しません。

listen、port、protocolを一つずつ確認してください。待ち受けアドレスはどのネットワークインターフェースからの接続を受け付けるか、ポートは入口の番号、プロトコルはどの形式のデータを受け付けるかを指定します。ブラウザーのHTTPプロキシ設定を、SOCKS専用のポートにそのまま指定することはできません。クライアント画面に「混合ポート」と表示される場合は、クライアント独自の複合機能なのか、カーネル設定の独立した入口なのか確認してください。画面上の用語を、汎用プロトコル名としてJSONに入力しないようにしましょう。

項目確認ポイントよくある誤解
tagルーティングから参照できるよう、入口に一意の名前を付ける。名前を付けただけで、特定のモードが自動的に有効になるわけではない。
listen本機で接続を受け付けるアドレスを指定する。すべてのインターフェースにバインドすると、接続可能な範囲が広がる。
port未使用の本機ポートを指定する。アプリの設定と待ち受けポートが一致していない。
settings現在のinboundプロトコルに合った内容を指定する。別のプロトコル用の項目をそのまま転記する。

本機からのアクセスとLANからのアクセスを分けて考える

この端末だけで使う場合は、127.0.0.1へのバインドを優先してください。このアドレスはIPv4のループバックインターフェースで、他の端末から現在の端末のプロキシに接続することはできません。LAN内で共有する場合は、待ち受けアドレス、OSのファイアウォール、inboundの認証、端末間のネットワーク到達性も関係します。「LANからの接続を許可」を有効にしただけでは、他の端末にアクセス権が与えられるとは限りません。また、接続が自動的に認証されるわけでもありません。

以下はHTTP inboundオブジェクト一つだけを示した例です。inbounds配列の要素として使用してください。前述のSOCKS入口とはポートを分け、アプリ側の設定で区別しやすくしています。ポート番号は本機での取り決めであり、リモートサーバーのポートではありません。アプリからリクエストが送信されない場合は、まずシステムプロキシが古い値を参照していないか確認し、次にクライアントがこのオブジェクトを実際に読み込んでいるか調べてください。よく見かけるポート番号だからといって、対応するサービスがシステム上で動作しているとは限りません。

{
  "tag": "local-http",
  "listen": "127.0.0.1",
  "port": 10809,
  "protocol": "http",
  "settings": {}
}

UDPとスニッフィングの適用範囲を理解する

SOCKS inboundのudpスイッチは、その入口でSOCKS UDPリクエストを処理できることを示します。すべてのアプリのUDP通信が自動的にカーネルへ送られるという意味ではありません。アプリが対応するプロキシ方式を使い、後続のoutboundとネットワーク経路も転送を許可している必要があります。システムのHTTPプロキシだけを設定した場合、一部のリアルタイム通信やゲームの通信は従来の経路を通ることがあります。その場合は、まずアプリが対応するプロキシ方式を確認し、TUNモードの解説を参照してください。待ち受けポートを何度も変更する必要はありません。

スニッフィングは、接続の先頭にあるデータから接続先情報を識別する機能で、ドメインに基づくルーティングを補助するためによく使われます。すべてのアプリの通信を復号する機能でも、DNS名前解決の代替でもありません。スニッフィングの項目や対応する対象プロトコル、ルーティング専用のオプションは、カーネルによって異なる場合があります。追加する前に、現在の実装を確認してください。有効にした後、一部アプリの動作に問題が出た場合は、ほかの設定を変えずにスニッフィングだけを無効にして比較しましょう。判断材料は個々の接続であり、全体の速度測定だけではありません。

最後にログを確認し、入口のバインドが成功しているか確かめます。アドレスが使用中の場合は、クライアントが複数起動していないか、古いプロセスが残っていないか、クライアントが同じ名前の入口をすでに自動作成していないか確認してください。競合を避けるために、すぐに全インターフェース待ち受けへ変更しないでください。ポートを変更する場合は、アプリ側のプロキシアドレスも合わせて更新します。ループバックアドレスを使うアプリではIPv4とIPv6の違いにも注意してください。localhostがどちらを優先して解決するかは、OSによって異なる場合があります。

03 / outboundsとデフォルトの出口

最終的に選択されるoutboundを特定する

outboundsは、カーネルが受け取ったリクエストを次の接続先へどう送るかを決めます。一般的な種類には、接続先へ直接つなぐもの、リモートプロキシサーバーへ接続するもの、リクエストを遮断するものがあります。まずroutingが通信を特定のタグへ振り分けているか確認し、次に対応するoutboundオブジェクトを調べましょう。リモートプロキシのoutboundが一覧にあっても、すべての接続がそれを使うとは限りません。ルールが先に直結outboundへ一致していたり、タグの誤記によって設定の読み込みに失敗したりする場合があります。調査では「オブジェクトが存在すること」と「実際に使われていること」を分けて考えてください。

ルーティングルールに一致しない場合、よくある動作はoutbounds配列の先頭の項目を使うことです。そのため、配列の順番を変えるだけで、ルールに一致しない通信の行き先が変わることがあります。見やすくするためだけに、直結オブジェクトを末尾から先頭へ移動しないでください。クライアントは通常、独自のモードに応じて順序を生成します。カスタム設定では、デフォルトの出口を明確に設計する必要があります。タグ名から推測するより、デフォルトの動作を記録しておく方が確実です。「proxy」という名前のタグが直結オブジェクトを指すこともあります。

直結、遮断、リモートプロトコルを区別する

freedomは一般的な直結outboundプロトコル、blackholeは接続の遮断に使われます。どちらもリモートのアカウントは不要ですが、選択された場合にのみ動作します。接続を遮断したときの挙動も一様ではありません。アプリに接続失敗と表示されたり、再試行を待ったり、別のアドレスへリクエストを送ったりすることがあります。ページが最終的に開いたからといって、遮断ルールが機能していないとは限りません。どの接続が遮断され、アプリがその後に別のリクエストを送ったかも確認してください。

以下は、ローカルでのルーティング検証に使えるoutbounds配列全体の例です。含まれるのは直結と遮断のみで、リモートプロキシ機能はありません。ルーティングルールから参照するのがtag、カーネルが実装を選択するための指定がプロトコル名です。両者は置き換えられません。後の章でoutboundTagを使う場合は、ここで指定したタグと一字一句同じにしてください。大文字・小文字、ハイフン、余分な空白があると参照が一致しないことがあります。名前を変更するときは、すべての参照箇所も検索して更新してください。

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

リモートプロキシのoutboundには、プロトコルに応じたサーバーアドレス、ポート、認証情報を指定します。VMess、VLESS、Trojanでは認証の構造が異なるため、一方のユーザーオブジェクトを別のプロトコルへ転用しないでください。サブスクリプションから生成された設定には、フロー制御、暗号化、セキュリティ層などの関連項目が含まれることもあります。まずクライアントで元の接続情報に不足がないか確認し、次に生成されたオブジェクトを調べましょう。元データに項目がなければ、ルーティングを変更してもサーバー認証に必要な情報は補えません。

プロトコル名だけで接続条件を判断しない

同じプロキシプロトコルでも、異なる通信方式やセキュリティ層を組み合わせることがあります。どちらもVLESSを指定していても、通信経路、サービス名、TLSサーバー名、セキュリティ設定が違えば、設定を流用できない場合があります。サーバーアドレスは接続を確立するために使い、証明書の検証名はリモート側の本人確認に使います。同じ値の場合も、異なる値の場合もあります。サービス提供元の指定に従って個別に設定し、似た項目を一つのドメインで統一しないでください。サブスクリプションのグループ名をネットワークアドレスの欄に入力することもできません。

複数の出口を設計する場合は、接続のループにも注意してください。プロキシoutboundからリモートサーバーへ接続した通信が、クライアントの全体トラフィック捕捉機能によって同じ入口へ戻されると、ループが発生することがあります。GUIクライアントは、クライアント自身のプロセス、サーバーアドレス、バインドインターフェースなどを考慮していることが一般的です。カスタム設定でこれらの仕組みをむやみに削除しないでください。接続数が増え続けたり、同じアドレスへのアクセスがログに繰り返し記録されたりする場合は、追加したチェーン転送と全体トラフィック捕捉を一度無効にし、単一outboundで検証してください。

リモートに接続できない場合は、アドレス、ポート、認証、通信方式、セキュリティ層の順に切り分けます。TCP接続が確立しても、基本経路に到達できたというだけで、プロキシプロトコルのハンドシェイク成功を意味しません。遅延測定と実際のWebリクエストで、測定対象が異なることもあります。指標を比較する場合は、ノード速度測定値の解説を参照し、数値を判断する前に測定対象を確認してください。低遅延が一度記録されただけで、outbound設定全体が正しいとは限りません。

04 / 通信方式の設定とセキュリティ層

プロトコル、通信方式、暗号化接続を分けて確認する

まず、次の3つを切り分けて考えます。プロキシプロトコルは認証とリクエストをどう構成するか、通信方式はそのデータをどう運ぶか、セキュリティ層は外側の接続をどう検証・保護するかを決めます。クライアントの編集画面では一緒に表示されることがありますが、それぞれ別の設定階層です。プロキシプロトコルが正しくても通信方式が違えば接続できません。通信経路が確立しても認証が誤っていれば、その後の段階で拒否されます。トラブルシューティングでは、どの階層で失敗したかを具体的に確認し、すべてを「ノードが使えない」と一括りにしないようにしましょう。

一般的な設定では、streamSettingsが通信方式とセキュリティ関連の項目をまとめます。対応するinboundまたはoutboundオブジェクトの内側に配置できるもので、最上位に置けば全体に適用される汎用スイッチではありません。通信方式の名称や専用項目は、カーネルによって対応範囲が異なります。同じ技術でも、バージョンによって設定方法が異なることがあります。クライアントが現在生成している構造を保ったうえで、使用中のカーネルの説明を参照して調整する方が、古い記事のオブジェクト全体を上書きするより安全です。

TLSの名称と検証を一つずつ確認する

TLSは、暗号化接続を確立し、リモート側の本人確認を行う仕組みです。まずセキュリティの種類を確認し、次にserverNameがサービス提供元の指定と一致しているか調べます。この名称は通常、SNIや証明書の検証に使われ、任意のメモ欄ではありません。接続先にIPアドレスを使うからといって、検証名も同じIPアドレスに変える必要はありません。リモートの証明書がドメイン名に対して発行されている場合、名前を適当に変更すると、到達可能だったサービスでもハンドシェイクに失敗することがあります。

以下は、項目の階層を示す一般的なTLS設定オブジェクトの例です。example.comは説明用のドメインで、実際のサービスパラメーターに置き換える必要があります。この値でプロキシ接続を確立することはできません。通信方式は、実際のサービスに合わせて設定するため、ここでは指定していません。allowInsecureを無効にすると、証明書検証を意図的に省略しません。検証の無効化を通常の対処法にしないでください。名前、証明書チェーン、端末の時刻に関する問題が隠れてしまいます。

{
  "streamSettings": {
    "security": "tls",
    "tlsSettings": {
      "serverName": "example.com",
      "allowInsecure": false
    }
  }
}

証明書関連のエラーが出た場合は、まず端末の日付とタイムゾーンを確認し、次に検証名、サーバーアドレス、ネットワーク環境を調べてください。システム時刻がずれていると、証明書がまだ有効でない、または期限切れのように見えることがあります。ネットワークによっては、ポータルへのログインを先に済ませる必要があり、リクエストが接続先ではなくログイン画面に届いている場合もあります。こうした基本条件を確認してから、カーネルログの具体的なハンドシェイクエラーを確認しましょう。ブラウザーでサイトが開けても、プロキシサービスのTLS設定が正しいとは限りません。

通信方式に合ったパスとサービス名を指定する

WebSocketでは、パスや関連するリクエストヘッダーがサーバー側の振り分けに使われることがあります。gRPCでは、別のサービス名を指定します。これらは相互に置き換えられず、画面上の「ホスト」という表示だけから意味を推測することもできません。設定値をコピーする際は、パスの先頭のスラッシュと大文字・小文字を維持し、空文字と項目の省略が異なる意味を持つかにも注意してください。サーバーアドレス、HTTPのホスト項目、TLS名はそれぞれ別の役割を持つ場合があります。見た目を統一するために、同じ値へ無理に揃えないでください。

REALITYは、対応する特定のカーネルで利用できるセキュリティ方式です。別のカーネルがVLESSに対応しているからといって、関連するすべての項目が共通とは限りません。公開鍵、短いID、フロー制御などの設定は、サーバー側の指定と現在のカーネルの実装に一つずつ合わせてください。接続情報が異なる複数の例を組み合わせて、一見完全でも実際には動かない設定を作らないよう、ここではリモート接続用の寄せ集め例を掲載していません。クライアントにインポートした後は、まず設定を変えずにテストし、その後で項目を一つずつ調整してください。

通信方式の設定と接続の多重化も区別してください。多重化は、複数のアプリ接続で下位の通信路をどう共有するかを変えるもので、誤った証明書名、通信パス、認証情報を自動的に修正する機能ではありません。変数を減らすため、まず元の接続条件で検証してから、互換性のある多重化方式を有効にするか判断しましょう。プロトコル、フロー制御、通信方式によっては、多重化に追加の制約があります。別の設定からスイッチ一つだけをコピーしないでください。有効にした後に断続的な切断が起きた場合は、多重化だけを個別に無効にして比較します。

05 / routingのルールと適用順序

最初のルールから順に確認する

routingは、接続ごとに使用するoutboundを選びます。rulesを配列の先頭から読み、最初に条件へ一致したルールと、そのルールが指す出口を確認してください。ルール一覧は、すべての条件を順に実行するチェックリストではありません。広い範囲を対象とするルールを先頭に置くと、後の細かいルールに一致しなくなる場合があります。ルールを追加する際は、まず対象にしたい接続を明確にし、そのうえで挿入位置を決めましょう。慣例で末尾に追加するのは避けてください。

一つのルール内にある異なる条件は、通常、すべて一致した場合に対象となります。たとえば、入口タグと接続先ドメインの両方が条件を満たす必要があります。同じ条件配列に複数の候補がある場合は、通常はいずれか一つに一致すれば対象です。具体的な組み合わせは、使用中のカーネルの実装を確認してください。初めて調整する際は、一つの条件で対象を確認してから、制限を段階的に追加します。入口、ポート、プロトコル、ドメインを一度にすべて指定すると、厳密に見える反面、一致しなかった理由を特定しにくくなります。

まず追加リソース不要のルールを使う

以下は、最初の章にある本機用の例へ追加できるroutingオブジェクトです。第3章のblockoutboundも合わせて追加する必要があります。説明用ドメインへの通信を遮断outboundに、指定したプライベートアドレス範囲への通信を直結outboundに振り分けます。それ以外の通信は、元の設定のデフォルトoutboundで処理します。外部のドメイン分類ファイルを使わないため、参照関係とルール順序を理解するのに適しています。ただし、LANアドレス全体を網羅しているわけではなく、本番用の振り分け設定としてそのまま使うことはできません。

{
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": ["full:example.com"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "10.0.0.0/8",
          "172.16.0.0/12",
          "192.168.0.0/16"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

ドメインの一致方法は、意図に合わせて選択してください。full:は完全一致、domain:は通常、そのドメインとサブドメインの一致に使います。正規表現は、より特殊なパターンを指定する場合に適しています。通常の文字列は、これらのプレフィックス付き形式とは一致条件が異なるため、ルールを書く前に挙動を確認しましょう。サイト単位で制御する場合は、静的リソース、ログイン、APIが別のドメインにある可能性も考慮してください。トップページのドメインだけでは、そのアプリが実際に行うすべての接続をカバーできないことがあります。

ルーティング時の名前解決と接続先の名前解決を区別する

domainStrategyは、ルーティング段階で接続先のドメインをどう扱うかを指定します。一般的なAsIsは、IPルールに一致させるための名前解決を積極的に行いません。IPIfNonMatchは、ドメインルールに一致しない場合に名前解決を試み、IP条件との照合を行います。IPOnDemandは、照合中にIPを必要とするルールが出た時点で名前解決を試みます。これらはルーティング判定を制御するもので、全体のDNS出口を切り替えるスイッチでも、各アプリが最終的に使う名前解決方法を直接決めるものでもありません。

より積極的な名前解決方針を選ぶ前に、接続先IPによる振り分けが本当に必要か確認してください。追加の名前解決には、待ち時間、キャッシュ、応答アドレスの変化などが影響します。同じドメインから複数のアドレスが返る場合もあり、それらをカーネルがどう判定するかは実際の動作を確認する必要があります。接続先がもともとIPアドレスの場合、ドメインルールだけで元のドメイン名を復元することはできません。スニッフィングによって一部のプロトコルで情報を補える場合もありますが、すべての接続に有効なわけではなく、暗号化されたアプリ通信を必ず識別できるものでもありません。

geositeとgeoipは分類データを参照する方法であり、文字列を記述すればオンライン照会が自動的に行われるわけではありません。ルールが使えるかどうかは、カーネルの対応、リソースファイルの有無、分類名の正しさ、クライアントによるリソース管理方法に左右されます。分類の読み込みに失敗した場合は、まず明示的なドメインルールやアドレスルールに戻して検証してください。ある環境の分類タグを別の環境へ転記する際は、依存するデータの入手元やファイルの場所も確認しましょう。

ルーティングを変更したら、接続先を絞ったリクエストを一つ使って検証します。既存の接続を切り、新しい接続がどのoutboundを使うか確認してから、関連アプリのほかのドメインもテストしてください。既存の長時間接続は変更前の経路を使い続けることがあり、設定を変更しても一時的に挙動が変わらない場合があります。迂回や誤遮断が起きた場合は、「入口タグ、接続先情報、最初に一致したルール、outboundタグ」の順で確認しましょう。一般的な使い方の疑問は、まずよくある質問で調べられます。すべての設定をリセットする必要はありません。

06 / dnsと名前解決の適用範囲

ドメインをどのコンポーネントが解決しているか確認する

DNSは、ドメイン名をネットワークアドレスに変換する仕組みです。まず、アプリがドメイン名と解決済みのIPアドレスのどちらをプロキシへ渡しているか確認してから、カーネルのDNS設定を調べましょう。名前解決には、ブラウザー、OS、カーネル、リモートサーバーが関わる場合があります。設定にdnsオブジェクトが存在しても、端末上のすべての問い合わせがそこを経由するとは限りません。アプリが独自の暗号化DNSを使うと、システムのデフォルト経路を迂回することもあります。アプリ側の設定とカーネル設定を併せて確認してください。

カーネル内蔵のリゾルバーは、IPルーティングや直結outboundの一部の処理など、内部機能で必要な名前解決に使われることがあります。リモートプロキシがドメインを受け取り、最終的な名前解決をリモート側で行う場合もあります。そのため、2回の名前解決で同じサーバーが使われるとは限らず、結果も異なることがあります。調査時は、どこで、どのドメインが問い合わせられ、どのアドレスが返されたかを記録してください。OS標準の名前解決ツールの結果だけから、カーネルも同じ結果を得ていると判断しないでください。

問い合わせの目的に応じてサーバーを選ぶ

以下はDNSオブジェクトの一部を示す例です。説明用のドメインには指定したリゾルバーを優先し、それ以外の問い合わせには別のリゾルバーを使います。例にあるのは公開DNSサービスのアドレスです。使用前に現在のネットワークから接続できるか確認し、これらのサービスに問い合わせ内容が送られることを理解してください。この例は、serversのオブジェクト形式と文字列形式を説明するものです。すべての地域・ネットワークに適しているとは限らず、問い合わせがプロキシoutboundを経由することも保証しません。

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

domainsは、サーバーに優先処理させるドメイン範囲を指定するもので、そのサーバーだけを常に使うという意味ではありません。失敗時のフォールバック動作は、全体のフォールバック設定とサーバー個別のオプションにも左右されます。skipFallbackは通常、そのサーバーが無関係なドメインのフォールバック問い合わせに使われるのを避けるための設定であり、一致するドメインを必ずそのサーバーだけで処理する保証ではありません。名前解決の経路を厳密に分離する場合は、使用中のカーネルのフォールバック動作も確認し、ログや観測可能な問い合わせ記録で検証してください。

返されるアドレスのフィルタリングとアドレスファミリーを理解する

expectIPsは、応答として期待するアドレス範囲を指定します。これは名前解決の結果を絞り込むもので、接続を特定のoutboundへ自動的に送る設定ではありません。範囲を狭くしすぎると、正常なコンテンツ配信アドレスまで拒否する可能性があります。分類リソースに依存する形式を使う場合は、必要なリソースが実際に存在することも確認してください。応答がないのではなく、応答がフィルター条件に合わないために名前解決が失敗している場合もあります。まずフィルターを外して比較し、範囲を厳密にする必要があるか判断してください。接続先のドメインが無効だとすぐに決めつけないようにしましょう。

queryStrategyは問い合わせるアドレスファミリーの方針を指定します。IPv4とIPv6の両方を使う形式や、どちらか一方のみを使う形式が一般的です。端末にIPv6アドレスが割り当てられていても、すべての接続先へのIPv6経路が利用できるとは限りません。逆にIPv4だけを問い合わせると、特定のネットワーク環境で実際に利用できる機能が見えなくなる場合があります。選択前に現在の接続経路を調べ、outboundの対応状況も確認してください。一度のタイムアウトを解消するためだけに、理由を記録せずアドレスファミリー全体を無効にしないようにしましょう。

hostsは、カーネルのリゾルバーに静的な名前解決を設定できますが、システム上のすべてのアプリに適用されるグローバルなhostsファイルではありません。静的な割り当ては通常のDNS更新を迂回するため、管理されたテストや明確なローカル要件には向いていますが、頻繁に変わる公開サービスのアドレスを長期間固定する用途には適しません。設定後は、TLSがどの名前で検証されるか、割り当て後のアドレスに対してルーティングが再判定されるかも確認してください。静的アドレスで接続できても、元の名前解決サービスが復旧した証拠にはなりません。

暗号化DNSでは、名前解決の初期処理と接続経路を併せて考える必要があります。DNSサービス自体がドメイン名を使う場合、まずそのサービスのアドレスをどう取得するかを解決しなければなりません。同じサービスに依存すると、起動時に循環することがあります。問い合わせプロトコル、直接送信の方法、ルーティングとの連携はカーネルごとに構文が異なります。アドレスのプレフィックスを置き換えただけで振り分けが完了したと思わないでください。まずシンプルな名前解決で基準を作り、その後、DNSサービスへの到達性と接続先ドメインの結果をそれぞれ検証しましょう。

最後にキャッシュを消去して変更を比較します。アプリ、システム、カーネルのキャッシュや、使用中の接続に古い結果が残っている場合があります。一つのコンポーネントを再起動しても、ほかのコンポーネントの状態まで消去されるとは限りません。テストするドメインを一つ決め、変更前後のアドレスファミリー、応答アドレス、実際のoutboundを記録しましょう。日本国内外のドメインで名前解決を分ける方法については、DNS振り分け設定の解説を参照してください。名前解決の振り分けと接続のルーティングは、同じものではありません。

07 / policyと実行状態

まずデフォルト値を維持し、タイムアウトの原因を確認する

policyは、一部の接続のライフサイクルや統計動作を制御するもので、自動的に速度を上げる機能ではありません。ログや再現手順から特定の時間条件が原因だと判断できる場合に限り、変更を検討してください。ネットワークが遅い、サーバーの応答が遅い、アプリが送信を一時停止しているなど、待機状態に見える原因はさまざまです。すべてのタイムアウトをまとめて延長すると、失敗が遅れて現れるだけの場合があります。すべてを短くすると、本来維持できるアイドル接続まで早く終了することがあります。

policyはユーザーのレベルごとに設定することがよくあります。levelsオブジェクトのキーはレベル番号で、プロトコルユーザーに設定されたレベルに対応します。ノードの並び順でも、クライアント画面のグループ番号でもありません。明示的な指定がない場合、一般的なケースではデフォルトレベルが使われます。複数のユーザーや入口がある場合は、実際の接続がどのレベルに属するかを確認してから、カスタムpolicyが適用されるか判断してください。参照されていないレベルオブジェクトを追加しても、通常、確認中の接続には影響しません。

接続の段階に沿って時間項目を理解する

以下はpolicyオブジェクトの設定例です。時間の単位は秒、バッファの単位はキロバイトです。各項目の関係を示すための値であり、すべての端末に推奨する最適化設定ではありません。項目の適用範囲はカーネルの実装に左右されます。特にプロトコルやバッファ管理が異なる場合は、使用中のカーネルの動作を確認してください。設定を取り込んだ後は、まず正常に起動するか確認し、同じアプリと操作で比較します。outboundを同時に変更しないでください。

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

handshakeは、対象接続のハンドシェイク段階で待機できる時間を制限します。Webページ全体の読み込み時間を制限する設定でも、ファイルのダウンロード時間を制限する設定でもありません。接続確立前に毎回失敗する場合は、待ち時間を延ばす前に、アドレス、ポート、通信方式のネゴシエーションを確認してください。基本設定が誤っている場合、待ち時間を延ばすと失敗の表示が遅くなるだけです。不一致のプロトコルが使えるようになるわけではありません。

connIdleは、接続がアイドル状態にある時間の制限を表します。プッシュ通知、チャット、リモートセッションなどは、長時間データをやり取りしないことがあります。アイドル制限が短すぎると、アプリが何度も再接続することがあります。反対に長すぎると、不要になった接続が長く残ります。アプリ層のハートビート、下位ネットワークのキープアライブ、カーネルのpolicyを区別してください。これらは異なる階層にあり、一つの階層でキープアライブを設定しても、ほかの階層が接続中と判断するとは限りません。

uplinkOnlyとdownlinkOnlyは、接続の一方向が終了した後、反対方向をどれだけ維持するかに関係します。アップロード速度やダウンロード速度を制限する項目ではありません。リクエスト送信を終えた後、長時間レスポンスを待つアプリもあります。一方向の待機を短くしすぎると、レスポンスが途中で切れる可能性があります。「リクエストは送信されたが結果が中断した」という場合は、ログの時系列を確認してください。項目名に上り・下りとあっても、帯域幅の値と解釈しないようにしましょう。

バッファと統計は連携する仕組みも含めて確認する

bufferSizeは、関連する接続のバッファ設定に影響します。バッファを大きくしても回線の帯域幅が直接増えるわけではなく、複数接続ではメモリー負荷が高まることもあります。特にAndroid端末では、OSによるプロセス終了、バックグラウンド実行の制限、過大なバッファ設定が、見かけ上似た症状を引き起こす場合があります。最後の切断だけを見て判断しないでください。調整の前にシステムリソースとクライアントの状態を確認し、すべての端末に共通する固定値として不確かな性能情報を使わないようにしましょう。

統計のスイッチを有効にしても、目に見えるレポートが自動生成されるわけではありません。カーネルの統計機能には、統計モジュール、照会用インターフェース、クライアント側の読み取り処理が必要な場合があります。クライアント画面の通信量が別の方法で計測されていることもあります。有効にする前に、統計データを実際に利用するコンポーネントがあるか確認してください。設定を完全に見せるためだけに、不要なインターフェースを追加しないでください。統計値が示すのは、その計測方法に基づくデータ量です。実際のスループット、応答時間、リモートサービスの品質を推測することはできません。

policyを変更したら、起動ログ、アプリの挙動、発生時刻を合わせて記録してください。クライアントのプロセス全体が終了する場合は、接続タイムアウトをさらに緩めるのではなく、プロセスの終了理由やシステムの制限を優先して確認しましょう。デスクトップでは実行環境、展開先、設定の読み込みエラー、Androidでは権限やバックグラウンド制限など、別の原因経路もあります。起動時のクラッシュ対処法も参考にしてください。接続policyが作用するのは実行中の接続です。正常に起動していないカーネルを修復することはできません。

08 / 設定の検証とトラブルの切り分け順

起動成功と接続成功を分けて確認する

まず変更を保存し、クライアントに該当設定を再読み込みさせてください。想定した設定が画面上で選択されているか、ログ上の実行カーネルが計画どおりか確認します。クライアントの接続ボタンが起動状態になっていても、起動処理が実行されたことを示すだけで、待ち受け、ルーティング、リモートへの接続を検証したことにはなりません。カスタムファイルがディスク上に存在しても、実行中に読み込まれているとは限りません。設定内容と挙動がまったく一致しない場合は、読み込まれている設定の管理元を調べ、参照されていないファイルを編集し続けないようにしましょう。

最初に読み込みを確認します。構文エラー、項目の型の誤り、未対応プロトコル、分類リソースの不足は、通常、通信処理が始まる前に発生します。最後に表示されたプロセス終了のメッセージだけでなく、ログの最初の関連エラーと直近の変更を照らし合わせてください。構造上のエラーを一つ修正すると、次のエラーが現れることがありますが、修正が無効だったという意味ではありません。その時点で明確な問題だけを一つずつ直し、起動段階を通過したことを確認してから接続をテストしましょう。

リクエストの経路に沿って原因を絞り込む

次に入口を確認します。プロキシ設定に対応していることが明確なアプリからリクエストを送り、アドレス、ポート、プロトコルを確認し、カーネルが接続を受け取ったか観察してください。入口の記録がない場合は、まずアプリ独自のプロキシ設定とシステムプロキシの適用範囲を調べます。システム設定を起動時にしか読み込まないアプリもあるため、既存の接続を閉じるか、アプリを再起動してください。システムプロキシをまったく使わないアプリもあります。リクエストがカーネルに届いたことを確認する前に、失敗の原因をoutboundの認証に求めないでください。

3番目にルーティングと名前解決を確認します。接続先がドメインとIPのどちらで渡されたかを確かめ、ルールを順に確認して、最後にoutboundタグを調べてください。ログに表示される接続先情報が足りない場合は、管理されたテスト中に限ってログの詳細度を一時的に上げます。テスト後は元に戻してください。詳細ログにはアクセス先ドメイン、接続アドレス、本機のパスが含まれることがあり、共有前に問題と無関係な情報を削除する必要があります。ログレベルを変えると観察できる情報は増えますが、ルーティング結果は変わりません。

確認できる現象最初に確認する項目次に行うこと
カーネルが起動直後に終了するJSONの構文、項目の型、リソース、ポート。直近の変更を元に戻し、最初のエラーを再確認する。
アプリのリクエストが入口に記録されないアプリのプロキシ設定範囲、アドレス、プロトコル、ポート。プロキシ対応が明確なアプリ一つでテストする。
リクエストが想定外のoutboundを使うルールの順序、条件、タグの参照。既存の接続を切り、新しいリクエストを確認する。
基本接続は到達するが、ハンドシェイクに失敗する認証、通信パス、セキュリティ設定。サブスクリプションの元の設定に戻し、項目ごとに比較する。
一部のドメインだけ接続できない名前解決の結果、リソースのドメイン、振り分け範囲。対象を一つに固定し、アドレスファミリーとoutboundを比較する。

4番目にoutboundのハンドシェイクを確認します。接続拒否、待ち時間超過、証明書検証失敗、ユーザー認証失敗を区別してください。それぞれ原因となる段階が異なります。接続拒否では接続先ポートとサービスの状態を、タイムアウトでは経路とファイアウォールをまず確認します。証明書エラーでは名前と時刻、認証エラーでは接続情報を確認してください。すべてのエラーをDNSの変更で解決しようとしないでください。個別のエラーについては、実行ログの読み解き方を参照してください。

変更を次々に重ねず、切り戻しながら検証する

内容を明確に記録した設定を2つ用意してください。一方は正常に動作する基準設定として保存し、もう一方には今回検証する変更だけを加えます。テストでは同じアプリ、接続先、接続方法を使い、サーバーとルーティングを同時に変えて、どの変更が影響したか分からなくならないようにしましょう。新しいルールの追加で一部の接続に問題が出た場合は、そのルールをいったん元に戻し、復旧するか確認してください。原因を確かめてから条件を絞り込む方が、例外ルールを増やし続けるより特定しやすくなります。

オブジェクトを統合する際は、配列を通常の文章のように扱わないでください。完全なroutingオブジェクトを2つ並べて貼り付けると、キーが重複したり構造エラーになったりします。2つ目のoutboundsで1つ目を上書きすると、ルーティングから参照されているoutboundが消えるおそれがあります。まずどちらの親オブジェクトを残すか決め、必要な配列項目を一つずつ統合し、タグの一意性、参照関係、デフォルトoutboundの順序を確認してください。一部のパーサーが重複キーを受け入れる場合でも、上書きの挙動に依存しないでください。

検証後は、安定した設定を永続保存できる場所へ移し、クライアントの再起動、設定の切り替え、サブスクリプションの更新後にも再テストしてください。再起動すると以前の値に戻る場合は、変更が自動生成ファイルに残っている可能性があります。クライアントが対応する設定画面から変更してください。最終設定を保存する際は、使用するカーネル、変更した階層、依存する分類リソース、復元方法を簡潔に記録しましょう。問題と関係のない端末情報まで記録する必要はありません。認証情報を公開メモに書かないでください。