V2Ray設定ファイルリファレンス
接続処理の流れに沿って、JSON、inbounds、outbounds、ルーティング、DNS、policyを解説します。初回セットアップやサブスクリプションの取り込みはクイックスタートをご覧ください。このページでは設定項目やエクスポートした設定の確認、設定レイヤーの問題の切り分けを行います。
1. JSON構造とクライアントとの境界
GUI設定からコア設定まで
デスクトップではv2rayNが有力な選択肢です。サーバー、サブスクリプショングループ、システムプロキシ、コアの起動パラメーターを管理します。実際に接続を処理するのは、選択したコアです。Android版のv2rayNGはXrayコア、v2flyNGはV2Flyコアを使用します。3つのクライアントでは設定画面が異なり、生成されるJSONも完全には一致しない場合があります。設定ファイルを読む前に、クライアントで使用中のコアを確認し、ファイルが実行用の完全な設定なのか、単一サーバーの共有情報なのかを確かめてください。サブスクリプションURL、共有リンク、クライアントのデータベース、コア設定はそれぞれ異なる入力元です。いずれもサーバー情報を含むからといって、相互に置き換えられるわけではありません。
一般的な接続は、「端末上のアプリからinboundsに入り、ルーティングでoutboundを選び、outboundがリモート接続を確立する」という流れで理解できます。inboundsは受信方法、outboundsは送信方法、routingは接続を指定の出口に振り分けます。dnsはドメイン名の解決が必要な段階で使うDNS設定、policyは接続タイマーや統計の設定、logは記録する診断情報を指定します。すべてのトップレベルオブジェクトを設定に記述する必要はありません。項目を省略するとコアのデフォルト動作が使われるだけで、接続全体からその機能がなくなるわけではありません。
まずは動作する最小構成を確認
次の完全な設定例では、ローカルのループバックアドレスにSOCKSの入口を用意し、すべての接続を宛先へ直接送ります。設定構造と待ち受け動作を確認するための例で、リモートのプロキシサーバーは含まないため、暗号化トンネルは確立されません。実行前にポートがほかのクライアントに使用されていないことを確認してください。ルーティングと出口タグを明記しているのは、参照関係を見やすくするためです。出口が1つだけなら、コアのデフォルト出口の仕組みでも動作します。後続の章にある設定例は、対応する階層に追加してください。複数のトップレベルオブジェクトをファイル末尾にそのまま連結しないでください。
{
"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": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"inboundTag": ["local-socks"],
"outboundTag": "direct"
}
]
}
}
オブジェクト、配列、タグの読み方
波括弧はオブジェクト、角括弧は配列を表します。inboundsとoutboundsは通常、配列です。1つのプロセスで複数の入口を待ち受けたり、複数の出口を持ったりできるためです。ポートは数値、スイッチは真偽値で記述し、trueを文字列にしてはいけません。JSONのキー名と文字列には二重引用符を使います。行末の余分なカンマや通常のコメントは使用できません。画面上で入力できるコメントやメモが、必ずしもコア設定の項目とは限りません。起動に失敗したら、まず構文エラーを取り除いてからプロトコルのパラメーターを確認すると、不要な変更を減らせます。
tagは設定内で使う識別子であり、サーバーアドレスや画面表示名ではありません。ルーティングのoutboundTagは、outboundのタグと完全に一致させる必要があります。大文字・小文字、空白、ハイフンが違うだけでも参照先が変わります。短く変更しにくいタグを付け、変更後はすべての参照箇所を確認しましょう。トップレベルオブジェクトの記述順は通常、実行順を表しませんが、配列の順序は重要な場合があります。特にルーティングルールとデフォルト出口では注意してください。トップレベルキーの順番を入れ替えても、ルーティングの問題は解決しません。
設定をエクスポートする前に、現在のプロキシモードと使用中のサーバーを記録します。エクスポート後は別の場所にコピーを保存し、変更は1項目ずつ行いましょう。ファイルにはサブスクリプションURL、ユーザーID、認証情報が含まれる場合があります。問題を相談するときは、関係する項目だけを残し、ログの機密情報を伏せてください。インストーラーとプラットフォームの選び方はダウンロードページをご覧ください。接続に成功したことがない場合は、先にクイックスタートの手順で基本設定を済ませてから、このページを読み進めてください。
2. inbounds:待ち受けとトラフィック検出
待ち受けアドレスで接続元の範囲が決まる
inboundはコアが接続を受け付ける入口であり、リモートサーバーではありません。listenはバインドするアドレス、portはポート、protocolは入口のプロトコルを指定します。通常の単一端末で使う場合は、127.0.0.1で待ち受けるのが基本です。端末内のループバック接続だけを受け付けます。0.0.0.0に変更すると、すべてのIPv4インターフェースで待ち受けるため、LAN上のほかの端末から接続できる可能性があります。実際に接続できるかどうかは、ファイアウォール、ネットワーク分離、ルーティングにも左右されます。LANで共有する場合は、クライアントの「LANからの接続を許可」をオンにするだけでなく、認証とアクセス範囲も検討してください。
ポートが一致することは、接続成功の条件の1つにすぎません。アプリでHTTPプロキシを指定する場合は、HTTP inboundに接続する必要があります。SOCKSプロキシを指定する場合は、SOCKS inboundに接続します。クライアントによっては、画面上で異なるプロキシプロトコルを1つの入口にまとめる混合ポートを提供しています。このページでは、クライアント固有のポート設定をすべてのコア共通のデフォルトと誤解しないよう、inboundを個別に紹介します。パラメーター設定で実際の待ち受けポートを確認してから、アプリのプロキシアドレスを指定してください。同じアドレスとポートを複数の設定で同時に使用しないでください。
SOCKSとHTTPを個別に設定する例
次の断片は、トップレベルのinbounds配列と置き換えて、SOCKSとHTTPの入口を個別に用意します。SOCKSのudpを有効にすると、対応するUDP転送リクエストを処理できます。ただし、アプリが実際にSOCKSのUDP機能を使い、後続のoutboundもそのトラフィックに対応している必要があります。この項目を有効にしただけで、すべてのシステムアプリが自動的にUDPプロキシを使うようになるわけではありません。HTTP inboundは、HTTPプロキシを明示的に設定するアプリに適しています。アプリがシステムプロキシ設定に従うかどうかは、アプリ側の仕様によります。
{
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": true
}
},
{
"tag": "local-http",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
]
}
sniffingで識別できるのは接続情報の一部
トラフィック検出では、プロトコルのハンドシェイクからドメイン名などの情報を取得します。たとえばアプリが宛先IPだけを渡した場合でも、識別可能なHTTPのHostフィールドやTLSハンドシェイクからコアがドメイン名を取得し、ドメインルールで判定できることがあります。destOverrideは検出を許可するプロトコルの種類を指定するもので、任意の通信内容を復号する機能ではありません。暗号化されたハンドシェイクやアプリのプロトコル、コアの実装によって、識別できる情報は限られます。ドメイン名を検出できない場合は、アプリが渡した元の宛先とIPルールを確認してください。すべての接続でドメイン名が取得できるとは限りません。
routeOnlyは、検出した情報を主にルーティングの判定に使い、それを接続先の置き換えに直接使わないようにします。「ルール判定に使う名前」と「実際に接続する宛先」を分けられます。この項目やトラフィック検出の対応範囲は、使用中のコアで確認してください。認識されない項目がある場合、似た名前のキーを推測して作らないでください。検出をオフにしてドメインによる振り分けが変わるなら、ルールが検出情報に依存している可能性があります。次にDNSの受け渡し方や、アプリが宛先ドメイン名を保持しているかを確認しましょう。すぐにサーバー側の問題だと判断しないでください。
| 項目 | 確認するポイント |
|---|---|
listen | 端末内だけで使うか、LANで共有するか。指定したインターフェースが存在するか。 |
port | アプリの設定値と実際の待ち受け値が一致しているか。ポートがほかのプロセスに使用されていないか。 |
protocol | アプリのプロキシプロトコルと入口のプロトコルが一致しているか。 |
sniffing | ドメイン名の識別が必要か。使用中のコアが設定項目に対応しているか。 |
システムプロキシのスイッチは、クライアントがOSに設定する項目であり、ここで説明しているinboundの設定ではありません。システムプロキシをオフにしても、SOCKSアドレスを手動で指定したアプリはinboundに接続し続ける場合があります。オンにしても、その設定に従わないアプリは直接ネットワークに接続することがあります。TUNは仮想ネットワークアダプター、ルーティングの引き継ぎ、権限に関わる機能で、通常のSOCKS inboundを追加しても代用できません。トラブルシューティングでは、まずアプリがどの方法で接続するのかを明確にし、対応する入口を確認してください。互いに異なる3つのスイッチを同時に変更するのは避けましょう。
3. outbounds:プロトコルとタグの関連付け
出口の定義とルーティングの選択を分けて確認
outboundは、接続を次のホップへ送ります。protocolは直接接続、遮断、プロキシプロトコルのいずれを使うかを決め、settingsはプロトコル固有のパラメーターを保持し、streamSettingsはリモートとのトランスポートとセキュリティ層を記述します。ルーティングは出口を選ぶだけで、認証情報を自動で補うことはありません。ログでプロキシのタグが選ばれていても、サーバーアドレス、ポート、セキュリティパラメーターが誤っていれば接続は失敗します。「正しい出口が選ばれたか」と「出口が接続を確立できたか」は、別々に確認してください。
freedomは現在の端末から宛先へ直接接続し、blackholeは対象のトラフィックを遮断します。どちらもローカルで処理されるため、サブスクリプションからリモートアドレスを取得する必要はありません。次の設定例は、1章のinboundと組み合わせて使える2種類のoutboundです。タグ名に特別な意味はありません。直接接続用のタグを別の名前に変えても、プロトコルの動作は変わりません。動作を決めるのはprotocolです。ただし、タグを変更したら、ルーティング、プロキシチェーンなどすべての参照先も更新してください。更新しないと設定の起動に失敗したり、意図しない転送が行われたりします。
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
]
}
リモートoutboundは関連する項目をまとめて確認
実際のプロキシoutboundは、入手済みのサーバー情報をもとに作成してください。プロトコルごとにsettingsの構造が異なるため、あるプロトコルのユーザー項目を別のプロトコルの下に移してはいけません。VLESSのoutboundでは、通常、サーバーリスト、アドレス、ポート、ユーザーID、暗号化の指定などを確認します。Trojanでは認証の構造が異なります。サーバーアドレスは接続先、ユーザーIDやパスワードは認証情報、TLSやREALITYのパラメーターはセキュアなハンドシェイクを決めます。これらは連携して動作するため、1つだけ変更すると組み合わせ全体が合わなくなることがあります。
関連するパラメーターの管理には、GUIクライアントのサーバー編集画面が便利です。信頼できる配布元から入手した共有情報全体を先に取り込み、エクスポートしたoutboundオブジェクトと照らし合わせると、空のファイルから手作業で作るより整合性を保ちやすくなります。実在するサーバー情報と誤解されかねないアカウント例は掲載していません。サポートに相談するときは、プロトコル名、トランスポートの種類、セキュリティ層の有無、エラーが発生した段階を伝え、認証情報は削除してください。ユーザー情報を含むoutboundオブジェクト全体を公開の場に貼り付けないでください。
デフォルト出口と配列の順序
一般的な単一路線のルーティング設定では、どのルールにも一致しない接続に、outbound配列の先頭が使われます。したがって、先頭を直接接続にするかプロキシにするかで、フォールバック動作が変わります。画面上の「グローバル」「LANをバイパス」などのモードは、ルールを再生成したり出口の並び順を変更したりする場合があります。モード名だけで最終的な設定を判断しないでください。エクスポートしたファイルで先頭の項目を確認し、すべての接続に一致する末尾ルールがないかも確認します。ロードバランサーやアウトバウンドチェーンを使う場合は、その参照先も確認してください。単一出口の設定と同じようには扱えません。
outboundが複数あっても、すべてのサーバーに同時接続するわけではありません。通常のルーティングでは、ルールに一致した1つのoutboundタグに接続が渡されます。サーバーの速度測定、自動選択、フェイルオーバーには、クライアントまたはコアの対応機能が必要です。2つのプロキシオブジェクトを配列に並べても、速度に応じた自動選択は行われません。同じタグを使い回すと、参照が曖昧になったり設定エラーの原因になったりします。論理的な出口ごとに一意のタグを付けてください。複数端末間の同期については、サブスクリプション、QRコード、設定エクスポートによる同期方法を参考に、サーバー情報とルーティング設定を分けて考えましょう。
直接接続できる最小構成から拡張する場合は、動作確認済みの入口を1つ残し、リモートoutboundを1つだけ追加します。次に、その入口を指定するルールを1つ追加してください。接続できることを確認してから、振り分けルールを追加します。こうすると、入口、プロトコルのパラメーター、ルールの問題を切り分けられます。クライアントがカスタム設定と内蔵サーバーモードで異なる起動方法を使う場合は、現在のモードでこのファイルが実際に使われていることを確認してください。読み込まれていない設定を編集しても、実行中の接続には反映されません。
4. routing:ルールの順序とマッチ条件
ルールは配列の順に判定される
ルーティングは、コアに入った接続を指定の出口に送ります。一般的なフィールドルールではtype: "field"を使い、宛先ドメイン、宛先IP、ポート、ネットワーク種別、inboundタグなどで絞り込みます。通常、ルールは上から順に評価され、有効なルールに一致すると出口が決まります。範囲が明確な例外を先に置き、対象範囲の広いフォールバックは後に配置してください。広い条件のルールを先頭に置くと、その後の細かいルールが評価されない場合があります。ルーティングを調べるときは、対象ドメインが設定内にあるかだけでなく、それ以前のルールで接続が振り分けられていないかも確認しましょう。
1つのルールに異なる条件を複数指定すると、通常はすべての条件を満たす必要があります。たとえばinboundTagとdomainを同時に指定した場合、指定したinboundから入り、かつ指定したドメインに一致する接続が対象です。一方、ドメイン配列の複数項目は、いずれかに一致すればよい値を表します。異なるフィールド間の関係を、どれか1つに一致すればよいと読み違えないでください。互いに無関係な2つの条件を設定する場合は、ルールを分けると分かりやすくなります。ルール内で使うinboundタグとoutboundタグは、実際に定義されている必要があります。コメントとして書いた説明文をタグの参照先として使うことはできません。
ドメインの完全一致・サフィックス一致とアドレス範囲
full:はドメイン名の完全一致に使います。特定のホスト名だけを対象にする場合に適しています。domain:は指定したドメインとそのサブドメインに一致し、同じドメイン配下の複数サービスを対象にできます。regexp:は正規表現を表し、パターンによる判定が本当に必要な場合に使います。通常の文字列の一致範囲はコアのドキュメントで確認してください。完全一致と同じだとは限りません。正規表現をJSONに記述するときは、バックスラッシュをさらにエスケープする必要があります。構文は正しくても、パターンが一致しない場合があります。明確なドメイン名で表せるルールには、通常、複雑な正規表現は不要です。
{
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": ["full:blocked.example"],
"outboundTag": "block"
},
{
"type": "field",
"ip": [
"127.0.0.0/8",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"::1/128",
"fc00::/7"
],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": ["local-socks", "local-http"],
"network": "tcp,udp",
"outboundTag": "direct"
}
]
}
}
この設定例は、前述の直接接続用と遮断用のoutboundと組み合わせて使います。ドメインの記述は完全一致を示すための例です。プライベートアドレス範囲のルールはIP条件を説明しています。末尾のルールは、2つのローカルinboundからのその他の接続を直接接続に送ります。プロキシを使う振り分け設定の例ではありません。プロキシをフォールバックにするには、実際に使用できるoutboundを追加してから、末尾のタグを変更してください。ドメインがプライベートアドレスに解決される場合、IPルールで判定されるかどうかは、その時点で宛先IPが取得されているか、ドメインのルーティング方針で名前解決が行われるかによって変わります。
domainStrategyとルールデータファイル
AsIsは、接続から得られる情報での判定を優先し、ドメインによるルーティングのための追加の名前解決は行いません。IPIfNonMatchはドメインが一致しなかった場合に名前解決を試し、IP条件で判定します。IPOnDemandは、IPが必要なルールに遭遇したときに名前解決を行う場合があります。後者を選ぶとDNSへの依存が増え、ルールの判定結果も変わる可能性があります。ここでの方針はルーティングの判定に関するもので、outbound接続時の名前解決方針とは異なります。OSのDNS設定を置き換えるものでもありません。
geoip:とgeosite:の形式は、利用可能なルールデータファイルと、その中に定義されたカテゴリに依存します。設定文字列が正しくても、クライアントに必要なデータが含まれているとは限りません。起動時にファイルやカテゴリが見つからないというエラーが出た場合は、コアのリソースディレクトリとクライアントのルールデータ管理画面を確認してください。似た名前の単語にカテゴリ名を置き換えるのは避けましょう。カスタム設定を別の端末に移すときは、こうした外部依存も引き継ぐ必要があります。JSONファイルだけをコピーして環境が同じだと判断しないでください。
ルールの問題を調べるときは、まずアプリからinboundに渡された宛先がドメイン名かIPアドレスかを記録します。次にトラフィック検出でドメイン名が補われているかを確認し、最後に条件をルール順に沿って1つずつ確認してください。ドメインルールを一時的に前に移動すると、先行ルールに遮られているかを調べられます。テスト後は適切な順序に戻しましょう。ルールの変更が影響するのは、多くの場合、新しい接続だけです。ブラウザーやアプリが既存の接続を再利用すると、変化が遅れて見えることがあります。設定を何度も変更する前に、新しい接続を作って確認してください。
5. dns:名前解決の経路と振り分けの範囲
まず、どこで名前解決しているかを確認
1回のアクセスには、OSのリゾルバー、アプリ独自のリゾルバー、コア内蔵DNS、リモートサーバー側の名前解決が関わる場合があります。トップレベルのdnsは、コアが名前解決するときの問い合わせ方法を定義するだけで、システム内のすべてのDNSリクエストを自動的に引き受けるわけではありません。アプリが先にドメイン名をIPアドレスに変換し、そのIPをSOCKS inboundに渡すと、コアが受け取る宛先はドメイン名ではなくIPアドレスです。アプリからドメイン名をプロキシに渡す場合は、その後の名前解決場所が異なる可能性があります。設定にDNSオブジェクトがあるだけで、すべての問い合わせがそこを通ると判断せず、まずアプリから渡される宛先の形式を確認してください。
次の例では通常のDNSアドレスを使い、項目の階層を示します。特定のネットワーク環境に最適な設定を推奨するものではありません。serversは名前解決サーバーのリストで、単純なアドレスのほか、条件付きのオブジェクトも指定できます。hostsは指定した名前をアドレスに静的に割り当てる項目で、一時的な調査や固定の内部サービスに使えます。サービスのアドレスが変わっても、割り当ては自動更新されません。例のテスト用ドメインとドキュメント用アドレスは書式を説明するためのものです。実際のサイトの設定としてそのまま使わないでください。
{
"dns": {
"hosts": {
"full:service.example": "192.0.2.10"
},
"servers": [
"1.1.1.1",
"8.8.8.8"
],
"queryStrategy": "UseIP"
}
}
DNSの問い合わせ方針と接続方針は別
queryStrategyは、コアのDNS問い合わせで使うアドレスファミリーを指定します。UseIPはIPv4とIPv6の結果を利用し、UseIPv4とUseIPv6は問い合わせ対象を限定します。対応状況は使用中のコアで確認してください。IPv4に限定すると、一部のIPv6経路の問題を切り分けやすくなる場合がありますが、サーバーのハンドシェイクパラメーターの誤りは解決しません。逆に、端末のネットワークから特定のアドレスファミリーでしかサービスに接続できない場合、名前解決を過度に制限すると、本来使える宛先アドレスが得られなくなることがあります。
ルーティングのドメイン方針、DNSの問い合わせ方針、outbound独自の名前解決設定は、それぞれ異なる段階で使われます。ルーティングがIPルールとの照合のために先に名前解決し、outboundの接続時に別の方法で宛先を処理することがあります。2か所の方針が違えば、参照されるアドレスも異なる可能性があります。まず「ドメイン名で出口を選ぶ」のか「名前解決後のアドレスで出口を選ぶ」のかを明確にしてから、どの段階で名前解決するかを決めてください。項目名をそろえるためだけに、複数箇所の方針を似た名前の値に設定しないでください。
DNSサーバーへの接続経路も必要
通常のDNS問い合わせも暗号化DNSリクエストも、DNSサーバーに到達する必要があります。DNSアドレスの書式、直接接続の動作、問い合わせのルーティング方法はコアによって異なります。あるコアで使える書き方を、別のコアにそのまま流用しないでください。ドメイン名でDNSサービスを指定する場合は、そのサービスへの初回接続に必要な名前解決も考慮します。これがブートストラップDNSの問題です。DNSサービスへの接続にプロキシが必要で、そのプロキシサーバーのアドレス解決にも同じDNSサービスが必要だと、依存関係が循環する可能性があります。そのうち1つの経路は、独立して到達できるようにしてください。
DNSサーバーのリストを、順番に必ずフェイルオーバーする一覧とみなしてはいけません。並行して問い合わせるか、いつ代替サーバーを使うか、ドメインに一致するサーバーがデフォルトのフォールバックを除外するかは、コアの実装やオブジェクトの項目によって異なります。ドメインごとにDNSサーバーを選ぶ場合は、まず単純な設定で各サーバーに接続できることを確認してから、ドメイン条件とフォールバック制御を追加してください。サーバーを複数追加し、同時にルーティングも変更すると、タイムアウトの原因を切り分けにくくなります。テストでは問い合わせ対象、宛先のアドレスファミリー、エラー発生時刻を記録し、DNSのタイムアウトと接続のタイムアウトを区別しましょう。
キャッシュも確認結果に影響します。アプリが独自にドメイン名の結果を保持したり、OSがレコードをキャッシュしたり、コア内部で名前解決の情報を再利用したりすることがあります。DNSを変更しても、既存の接続がすぐに再作成されるとは限らず、古いアドレスが使われ続ける場合もあります。テスト用アプリの古いセッションを終了してから、新しいリクエストを作成してください。必要に応じて、クライアントで利用できるコアの再起動操作で実行状態をクリアします。Webページを1回再読み込みしただけで新しいDNS方針が完全に反映されたと判断しないでください。キャッシュによる一時的な違いを、ルーティングルールの不具合と誤解しないようにしましょう。
ドメインではアクセスできず、既知のアドレスには到達できる場合でも、証明書やサーバー名の問題が考えられます。サイトのURLをIPアドレスに変えても、同等のテストにはなりません。正しい切り分け手順は、名前解決の結果、選択された出口、出口から宛先への到達性、最後にハンドシェイクを確認することです。問題をこの段階ごとに記録すると、DNSエラーとセキュリティ層のエラーを、どちらも「開かない」という説明に混在させずに済みます。
6. policy:接続タイマーと統計の設定
policyはユーザーレベルで選択され、画面上のグループでは選ばれない
policyは接続のライフサイクルと一部の統計動作を管理します。出口の選択やプロトコル認証の変更には使いません。levelsのキーは、"0"のようなユーザーレベルを表す文字列です。プロトコル側で対応するユーザーレベルの項目を使い、該当する方針を関連付けます。このレベルはサブスクリプショングループ、サーバーの優先度、ルーティング一覧の番号ではありません。レベルのオブジェクトを1つ定義しただけで、すべてのプロトコルオブジェクトが自動的にそのレベルに移るわけでもありません。エクスポートした設定を読むときは、ユーザーオブジェクトのレベルと、コアがそのプロトコルに対応しているかの両方を確認してください。
次の例は、レベル別のpolicyとシステム統計のスイッチの構造を示しています。数値は項目の説明用で、すべての端末に適した性能設定ではありません。一般的な用途では、まずクライアントのデフォルト値を使い、ログや接続状況からタイマーの問題が疑われるときに調整します。デフォルト値、バッファーの割り当て、統計APIの動作はコアによって異なるため、設定を移行するときは、まず項目が対応しているかを確認し、その後で実際の動作を比較してください。ネットワークパラメーターを複数の端末にそのままコピーしても、同じ結果が得られるとは限りません。
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5,
"statsUserUplink": false,
"statsUserDownlink": false
}
},
"system": {
"statsInboundUplink": false,
"statsInboundDownlink": false,
"statsOutboundUplink": false,
"statsOutboundDownlink": false
}
}
}
4つのタイマー項目はそれぞれ異なる段階を制御
handshakeはinboundプロトコルのハンドシェイク段階に設ける制限時間で、単位は秒です。Webページ全体の読み込み時間とは異なり、リモート側のTLSハンドシェイクすべてを制御する共通スイッチでもありません。ローカルのポートに到達できず、ハンドシェイク前に失敗している場合、値を大きくしても解決しません。リモートoutboundが認証エラーで失敗した場合も、inboundのハンドシェイク時間を延ばして修復することはできません。ログで停止している段階を確認してから、時間に余裕を持たせる必要があるか判断してください。
connIdleは、データの送受信がない状態で接続を維持する時間を制限します。短すぎると、断続的にデータを送る長時間接続に影響する場合があります。非常に長く設定すると、アイドル状態の接続がより長時間リソースを占有します。アプリのハートビート、サーバーのアイドル時の動作、中継ネットワーク機器のタイムアウトも接続の維持に影響します。クライアント側のタイマーだけを延ばしても、ほかの段階を制御することはできません。一定間隔で切断される場合は、切断前にデータの送受信があったか、クライアントとサーバーで異なるタイムアウトが設定されていないかを記録してください。
uplinkOnlyとdownlinkOnlyは、接続の片方向が終了した後、もう一方の方向で転送が続く場合の待機時間を処理します。この半閉鎖状態は、接続全体がアイドル状態になるのとは異なります。アップロードが終わってもダウンロードが終わるとは限らず、ダウンロード側が終了してもアプリの送信が完了したとは限りません。値を短くしすぎると転送の最後が途切れることがあり、むやみに延ばすと不要なセッションが長く残る場合があります。大きなファイルやリクエスト末尾の異常を調べるときは、アプリのプロトコルとログを確認してください。この2項目は上り・下りの速度制限ではありません。
統計を有効にしても画面にすぐ表示されるわけではない
ユーザー統計には対応するユーザー識別情報とコアの対応が必要です。システム統計はinboundとoutboundのオブジェクトごとに計測します。trueにすると該当する統計の収集を許可しますが、読み取り用のインターフェースが自動で作成されたり、クライアントにパネルが追加されたりするわけではありません。環境によっては、トップレベルの統計モジュール、APIサービス、呼び出し側の設定も必要です。GUIクライアントがすでに関連設定を管理している場合があります。手動でAPI inboundや統計サービスを重複して追加すると、ポートが競合することがあります。日常的な接続情報を確認するだけなら、まずクライアントに用意されているログやステータス画面を使ってください。
policyのバッファー関連項目も、汎用の高速化スイッチとして扱わないでください。バッファーサイズ、同時接続数、端末のメモリー、プロトコルの動作がリソース消費に影響します。バッファーを大きくするとメモリー負荷が増える可能性がありますが、リモート回線の帯域は変わりません。具体的なボトルネックを再現でき、コアのドキュメントで根拠を確認できる場合を除き、まずデフォルト値を使ってください。特にモバイル端末では、バックグラウンド制限や省電力機能が中断の原因となることがあります。コアのpolicyで、バックグラウンド実行の許可を代替することはできません。
policyを変更するときは、一度に1項目だけ変更し、現在有効な設定を残しておきましょう。短いリクエスト、継続的な転送、アイドル後の再開という3種類の動作をテストし、それぞれ異常がないか確認します。クライアントが設定ファイルを再生成する場合は、実行中の一時ファイルを繰り返し編集せず、対応する詳細設定画面から保存してください。設定の起動に成功したことは、構文と一部の意味が受け入れられたことを示すだけです。タイマー設定がアプリに適しているとは限らないため、実際の操作で動作を確認する必要があります。
7. トランスポート、セキュリティ層、コアの違い
プロキシプロトコルだけでなく、トランスポートとの組み合わせも確認
サーバー設定には通常、プロキシプロトコル、トランスポート方式、セキュリティ層が含まれます。プロキシプロトコルは認証とプロキシとしての動作、トランスポート方式はデータの運び方、セキュリティ層は該当するハンドシェイクの保護を担います。画面上で並んでいても、それぞれ別の項目です。outboundのprotocolとstreamSettings.networkは役割が異なります。画面上のトランスポート種別をプロキシプロトコルの位置に入力すると、誤った構造になります。特定のクライアントだけで動作する設定を調べる場合は、この3つの階層を比較した後、コアが該当する構文に対応しているか確認してください。
次の設定例はWebSocketとTLSのトランスポート部分です。実際のサーバーパラメーターを含むoutboundオブジェクトの中に記述し、JSONのトップレベルには置かないでください。例の予約ドメインは項目の位置を示すためのもので、接続できるサーバー情報ではありません。サーバー側のトランスポート方式、パス、証明書名とも一致させる必要があります。outboundのプロトコルと認証情報が正しくない状態でこの部分だけをコピーしても、接続は確立されません。
{
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "edge.example",
"allowInsecure": false
},
"wsSettings": {
"path": "/connect",
"headers": {
"Host": "edge.example"
}
}
}
}
アドレス、serverName、Hostを混同しない
outboundのサーバーアドレスは、どのホストにネットワーク接続するかを決めます。serverNameはTLSハンドシェイクと証明書名の検証に使われます。WebSocketのHostはHTTPハンドシェイクで送るホスト情報です。環境によって3つが同じ場合もあれば、サーバー側の指定で異なる場合もあります。見た目をそろえるために、すべて同じ値へ無理に変更しないでください。証明書エラーが発生したら、端末の時刻、サーバー名、サーバー側の証明書設定を確認します。証明書の検証を無効にするのは避けてください。接続時の信頼条件が変わり、接続先の指定ミスを見逃すおそれがあります。
WebSocketのパスはサーバー上のトランスポート入口と一致させる必要があります。大文字・小文字を含め、サーバー側の設定を確認してください。Webページのアドレス欄に入力する任意のディレクトリではなく、ほかのサーバー設定から流用するものでもありません。通常のWebページのような内容が返ったり、ハンドシェイクの状態エラーが出たりする場合は、同じホスト上の別サービスに接続している可能性があります。トランスポート方式、パス、ホストの項目を確認し、ユーザーIDだけを何度も変更しないでください。ポートへの接続テストで確認できるのは、ポートが応答したことだけです。その先のプロキシプロトコルの組み合わせが正しいかは分かりません。
REALITYとコアの選択
REALITYはセキュリティ層に関わる機能であり、トップレベルのプロキシプロトコル名でも、自由に有効化できる汎用の強化スイッチでもありません。使用時には、実際のコアが対応しているかに加え、サーバーから指定されたサーバー名、公開鍵の情報、ショートID、その他の必須パラメーターを確認してください。コアや設定の世代によって項目の表記が異なる場合があります。キー名を推測して互換性の問題を解決しようとしないでください。サーバー情報から切り離した汎用REALITY設定例は掲載していません。クライアントが正しく認識できる共有情報全体から始め、実際に生成されたoutboundオブジェクトと照らし合わせてください。
v2rayNの機能は、選択したコアとクライアント側の対応状況によって異なります。v2rayNGとv2flyNGも、画面が似ているからといって完全に同じとは限りません。必要なプロトコルやセキュリティ層がある場合は、まずコアの実装を確認してからクライアントを選びましょう。コアを変更すると、以前の設定に含まれる項目が拒否されたり、デフォルト動作が変わったりする場合があります。元の設定を保存し、クライアントが対応する方法で設定を再生成して、重要なパラメーターを比較してください。関連情報はXrayコアとV2Flyコアの違いをご覧ください。
| 階層 | 主な確認項目 |
|---|---|
| プロキシプロトコル | プロトコルの種類、ユーザー情報、プロトコル固有の設定。 |
| トランスポート方式 | トランスポートの種類、パス、トランスポートのハンドシェイク項目がサーバー側と一致するか。 |
| セキュリティ層 | セキュリティの種類、サーバー名、必要な認証情報。 |
| コアの実装 | その組み合わせに対応しているか。設定項目の構造が一致するか。 |
Muxによる多重化は、接続をまとめる別の仕組みです。セキュリティハンドシェイクや認証のエラーを修復するものではなく、すべてのアプリで効果があるとも限りません。クライアントのMuxスイッチがoutbound設定に影響する場合があります。使う前に、プロトコルの組み合わせとコアの制限を確認してください。トラブルシューティングでは、まず追加の接続管理オプションをオフにし、基本構成で接続を確認してから1つずつ戻します。プロトコルが接続できないうちにMux、DNS、ルーティング、トラフィック検出を同時に変更すると、たまたま復旧しても原因が分からなくなります。
プラットフォーム間で設定を移行するときは、システム環境にも注意が必要です。Windows、macOS、Linuxではシステムプロキシの仕組みが異なります。AndroidのVPN接続やアプリごとの選択も、JSONのトランスポート項目には含まれません。トランスポート設定が正しくても、アプリからinboundに接続されなければ、期待した通信は発生しません。macOSで初回起動時にシステムの許可やネットワーク権限が必要な場合は、起動許可とネットワーク権限の設定方法をご覧ください。システム権限の問題をプロトコル設定の変更で解決しようとしないでください。
8. 設定の確認、ログの読み方、元に戻す方法
構文、起動、入口、出口の順に確認
設定をトラブルシューティングする前に、元に戻せる有効なコピーを用意します。現在のクライアント設定とカスタム設定を保存し、1つの階層だけ変更してから該当するコアを再起動し、新しい接続を試してください。起動できない場合は、最初に現れた意味のあるエラーを確認します。カンマの不足はJSONの構文エラー、未対応の項目やプロトコルは設定の互換性の問題、待ち受けの失敗はアドレスやポートの競合がよくある原因です。いずれも正常な転送が始まる前に発生するため、最初にリモートサーバーの速度やWebサイトの稼働状況を調べる必要はありません。最初のエラーを修正してから、後続のログを確認しましょう。連鎖して発生したエラーだけを追いかけないようにしてください。
次の設定例は、トップレベルのログオブジェクトと一時的に置き換え、診断情報を増やすために使えます。ログレベルをdebugにすると、記録量が増え、宛先アドレスや接続の特徴が含まれる場合があります。トラブルシューティング後は、日常利用に適したレベルに戻してください。この例ではログファイルのパスを指定しません。出力場所は起動方法とクライアントの管理方法によって異なります。画面にログが表示されない場合は、ログ機能そのものの不具合を疑う前に、クライアントがそのレベルに対応しているか、実行中のプロセスが変更後のファイルを読み込んでいるかを確認してください。
{
"log": {
"loglevel": "debug"
}
}
エラーが発生した段階から原因を絞り込む
コアが正常に起動したら、まずアプリが実際にinbound接続を開始しているか確認します。該当する記録がない場合は、アプリのプロキシアドレス、プロキシプロトコル、システムプロキシのモード、アプリごとの設定を確認してください。記録はあるのに出口が違う場合は、タグ、ルールの順序、宛先の形式を確認します。正しい出口が選ばれているのに接続できない場合は、リモートアドレス、認証、トランスポート、セキュリティ層を確認します。接続できても一部のドメインだけで問題が起きる場合に、DNS、ドメインのマッチ条件、宛先サービスを調べましょう。この順序で確認すれば、すべての問題を「ノードが使えない」と一括りにせずに済みます。
ポートへの接続拒否は、通常、対象ポートで待ち受けていないか、接続が明示的に拒否されたことを示します。DNSエラーとは異なります。名前解決のタイムアウトはアドレスが得られる前に発生します。ハンドシェイクの失敗は、何らかのプロトコル交渉段階まで進んでいることを示しますが、原因はログと合わせて判断する必要があります。タイムアウトだけでは原因を特定できません。接続の確立、プロトコルのハンドシェイク、応答待ちのいずれでも発生する可能性があります。問題を相談するときは、曖昧なエラーを1行貼るだけでなく、発生した段階と再現手順を伝えてください。ログの時刻が分かると、操作と該当する記録を照合しやすくなります。
状況を再現できる最小構成を作る
まず使用中のサーバーを1つ選び、明確な入口と単純な出口ルール1つを使って、追加の振り分けを一時的に取り除きます。基本接続を確認した後、ドメインルール、IPルール、DNS条件、高度なpolicyを順に戻してください。いずれかの階層を戻したときに問題が再発したら、その階層の最小限の条件を残して調査を続けます。ルールデータファイルに依存する場合は、ファイルの有無とカテゴリが有効かどうかも伝えてください。関係のないルールが大量に含まれるエクスポート設定を、最初の調査資料として使わないでください。情報が多すぎると、問題との関連が分かりにくくなります。
クライアントによる設定の再生成は、よくある変動要因です。変更直後は有効でも、サーバーを切り替えると元に戻る場合は、一時ファイルを編集しているか、現在のモードでカスタム設定が保存されていない可能性があります。クライアントが対応する設定画面で保存先を確認し、再エクスポートした設定と比較してください。サブスクリプションの更新は、管理対象のサーバー情報を更新するものです。手動で追加したすべての項目が保持されるとは限りません。メイン画面の項目についてはサーバー一覧、ログパネル、パラメーター設定の概要を、設定の構造についてはconfig.jsonを項目ごとに解説をご覧ください。
よくある境界の問題
設定が起動しているのに、アプリがプロキシを使わないのはなぜ?
起動に成功したことが示すのは、コアが動作状態になったことだけです。アプリがシステムプロキシ、個別に指定したプロキシ、またはクライアントによる取り込みを通じて、該当するinboundに接続しているか確認してください。その後、ルーティングで意図したoutboundが選ばれているかを調べます。まずinboundの記録があるか確認し、次にプロトコル設定をチェックしましょう。
ルールを変更したのに、既存のWebページ接続に反映されないのはなぜ?
既存の接続では、以前と同じ出口やアドレスが引き続き使われる場合があります。テスト中のアプリの古いセッションを終了し、新しい接続を作成してから、新しいログを確認してください。必要であればコアを再起動します。ただし、再起動をルール確認の代わりにしないでください。
元に戻すときは、最後に正常動作していたクライアント設定または完全な設定ファイルを復元し、コアを再起動して、使用中のサーバー、プロキシモード、入口のポートを確認してください。問題が続く場合は、今回のJSON変更以外に、システムネットワーク、権限、サーバー側の状態も調べる必要があります。基本的な操作手順はクイックスタートで確認してください。端末に合ったクライアントを選び直す場合はダウンロードページをご利用ください。エラーが発生した段階を特定せず、クライアントを何度も変更して解決しようとしないでください。