V2Ray設定ファイルリファレンス
データの流れに沿って項目を確認します:ローカルアプリ → inbounds → routing → outbounds。続いてDNS、トランスポート、policyを確認しましょう。
初めて使う場合は、まず利用ガイドのクイックスタートをお読みください。このページでは設定をインポートした後の確認事項として、各項目の配置や相互に影響する設定、変更が反映されたかの確認方法を解説します。デスクトップクライアントにはv2rayNがおすすめです。インストール方法はダウンロードセンターをご覧ください。
1. JSON構造と設定の範囲
クライアントのデータとカーネル設定を区別する
v2rayNが保存するサブスクリプショングループ、画面の設定、サーバー情報はクライアント側のデータです。接続を開始すると、クライアントは選択中のサーバー、ルーティングプリセット、各種パラメーターをもとにカーネル設定を生成します。カーネルが読み込むのは後者であり、画面上のデータベースではありません。実行ディレクトリにある一時設定を直接編集すると、サーバーの切り替えや再起動で上書きされることがあります。変更したいのが画面設定、ルーティングテンプレート、独立したカスタム設定のどれなのか、まず確認しましょう。
v2rayNGも、設定のインポートやサーバーの選択、カーネルの起動を行います。v2flyNGはV2Flyカーネルを使用するAndroid向けの代替クライアントです。メニュー名が似ていても、3つのクライアントが同じ設定を出力するとは限りません。ログを確認する際は実際に起動したカーネル名を記録し、設定を確認する際は前回のエクスポートではなく今回の起動で使われたファイルか確かめてください。設定ファイルのパスはプラットフォームやクライアントの設定によって異なります。他の端末の固定パスをそのまま使わないでください。
トップレベルの各項目の役割
従来のJSON設定では、一番外側にオブジェクトを置きます。inboundsとoutboundsは配列で、1つ以上の入口・出口を格納します。routing、dns、policyは通常オブジェクトです。各項目は対応する階層に置く必要があり、outbound内のsettingsをトップレベルに置くことはできません。波括弧はオブジェクト、角括弧は配列を表します。キー名と文字列は半角のダブルクォートで囲み、数値と真偽値にはクォートを付けません。
| トップレベル項目 | 役割 | よくある誤解 |
|---|---|---|
log | アクセス記録、エラー、ログレベル | ログレベルを接続ポリシーと混同する |
inbounds | ローカルの待ち受けとプロトコル | ローカルポートにリモートポートを指定する |
outbounds | 接続先とリモートパラメーター | タグの指定漏れやプロトコル構造の誤り |
routing | トラフィックの条件判定と出口の選択 | ルールの順序を見落とす |
dns / policy | 名前解決と接続の動作 | システムネットワークを自動的に制御すると誤解する |
ローカル環境の切り分けに使う完全なベース設定
以下の設定は、ローカルホストからのSOCKS通信だけを受け付け、ローカルネットワーク経由で宛先へ直接接続します。リモートプロキシには接続せず、システムプロキシも自動設定しません。まずカーネルが起動するか、ローカルポートでリクエストを受け付けられるか確認するための設定です。独立したファイルとして保存する場合はUTF-8で保存してください。説明文、コードフェンス、行番号はファイルに含めないでください。クライアントが同じポートを使用中の場合は、先に既存のカーネルプロセスを停止してください。
{
"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とリモートサーバーをあえて含めていません。リクエストが成功しても、ローカル待ち受けと直接接続の基本動作が確認できただけで、サブスクリプションのサーバーが使えるとは限りません。outboundを追加する際は、デフォルトの出口にする項目を先頭に置き、ルールを少しずつ追加してください。動作する設定を毎回残し、問題が起きたら変更を積み重ねず、直前の変更だけを戻しましょう。
標準JSONでは末尾のカンマやコメントは使用できません。一部のカーネルでは拡張構文を受け付ける場合がありますが、ツール間の移行では依存しないでください。重複キーも削除してください。重複キーの処理結果はパーサーによって異なることがあります。エディターの構文チェックで確認できるのは括弧やクォートなどの形式上の問題です。現在のカーネルがプロトコル項目に対応しているか、サーバーに実際に接続できるかまでは判断できません。
2. inbounds:ローカルの待ち受けと通信の入口
待ち受けアドレスとポートの役割
inboundsは、アプリからカーネルへ通信を渡す方法を定義します。listenはバインドするローカルアドレス、portは接続を待ち受けるローカルポート、protocolは入口で使うプロトコルです。127.0.0.1で待ち受けるとローカルアプリだけが利用できます。0.0.0.0ではすべてのIPv4インターフェースにバインドされ、LAN内の端末から接続される可能性があります。待ち受け範囲を広げる場合は、ファイアウォールや認証、ネットワークの信頼性も考慮してください。
ローカルの待ち受けポートとサーバーのポートを同じ番号にする必要はありません。ブラウザーはローカルポートに接続し、カーネルはその後リモートサーバーのポートに接続します。この2つは別々の接続です。ポートが使用中の場合、起動ログにバインド失敗が記録されることがあります。使用中のプロセスを確認してから、停止するかポートを変更してください。コマンドのポートだけ変えてクライアント側の待ち受け設定を変えなければ、引き続き接続は拒否されます。
SOCKSとHTTP、どちらのinboundを使うか
SOCKS inboundはSOCKSプロキシに対応したアプリに、HTTP inboundはHTTPプロキシのアドレスを設定するアプリに適しています。両者は別のプロトコルなので、ポートに接続できるというだけで使い分けを省略することはできません。以下の断片では別々のポートで待ち受け、タグも分けて、routingやログで入口を判別しやすくしています。これは2つのポートを使う独立した例であり、クライアントが現在必ずこの構成を生成するという意味ではありません。
{
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
},
{
"tag": "local-http",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
]
}
この設定でHTTP inboundをテストする場合は、http://127.0.0.1:10809を指定します。SOCKS inboundをテストする場合は、対応するSOCKSアドレスを使ってください。クライアントによっては、1つのポートで複数のプロキシリクエストを判別する混合inboundを生成できますが、対応状況はカーネルと生成方法によって異なります。トラブル時は実際の設定を確認し、解説記事のスクリーンショットからポートのプロトコルを推測しないでください。
UDPとトラフィック検出の範囲
SOCKSのudpを有効にしても、このinboundが対応するUDP転送リクエストを処理できるようになるだけです。アプリ側がSOCKS UDPに対応し、後続のoutboundとリモート接続も必要な機能をサポートしている必要があります。システム上のすべてのUDP通信が自動的に取り込まれるわけではありません。通常のHTTPプロキシリクエストと、一部アプリのUDP通信では経路が異なる場合もあるため、個別に検証してください。
sniffingは、カーネルに届いた通信からHTTPのホスト名やTLSハンドシェイク内のドメインなどを識別し、routingの判定を補助します。通信を復号する機能ではなく、すべてのリクエストからドメインを特定できる保証もありません。暗号化されたハンドシェイクやIPアドレスだけで接続するサービス、独自プロトコルでは情報を取得できない場合があります。「検出を有効にする」だけで適切なDNSやroutingの設計を代替することはできません。
destOverrideは検出した情報を使って宛先を扱うための設定で、ログに名前を表示するだけの機能ではありません。元の宛先が特定のIPアドレスで、検出結果がドメイン名の場合、その後の名前解決や接続先に影響する可能性があります。検出を有効にした場合だけ特定のサイトで問題が起きるなら、同じリクエストで設定の有効・無効を比較し、異なるルールに一致していないか確認してください。検出、DNS、サーバーを同時に変更すると原因を特定しにくくなります。
LAN共有とシステム通信の取り込みは別の機能
パソコンのプロキシをスマートフォンやテレビと共有する場合、接続する端末にはパソコンのLAN内アドレスを指定します。パソコン側から見たループバックアドレスは使えません。該当するinbound接続を許可し、接続元のネットワークも制限してください。認証なしの入口を公共のネットワークに公開するのは避けましょう。画面上の設定手順はLAN接続を許可する設定方法をご覧ください。変更後はパソコン上だけでなく、別の端末から接続をテストしてください。
通常のSOCKSやHTTP inboundを使うには、アプリ側でプロキシを利用する設定が必要です。システムプロキシの切り替えは、対応アプリにプロキシ設定を通知する機能です。一方TUNは仮想ネットワークインターフェースやルーティング、権限が関係するため、通常のinboundを追加するだけでは同じ動作になりません。ブラウザーは使えるのにターミナルから通信できない場合は、対象のプログラムがシステム設定や環境変数を参照しているか確認してください。inboundのログがまったくない場合は、リモートプロトコルより先に通信の入口を調べましょう。
3. outbounds:出口、タグ、リモート接続
outboundオブジェクトとデフォルトの出口
outboundは、カーネルがリクエストを受け取った後、どの方法で宛先へ接続するかを定義します。各オブジェクトのprotocolによって、settingsで利用できる項目が決まります。同じ名前の設定でも、プロトコルが異なればそのまま流用できません。tagはローカルで識別するためのラベルで、routingから参照します。サーバーに送信される情報ではなく、サブスクリプション上の表示名でもありません。画面上のメモと設定内の参照を分け、短く一貫したタグを使うと管理しやすくなります。
ルールに一致しない場合、従来の設定では通常outbounds配列の先頭が使われます。そのため、配列の順序を入れ替えるだけで、明示的なルールに一致しない多くの通信の経路が変わることがあります。プロキシoutboundを先頭にしてプライベートアドレスを直接接続する構成と、directを先頭にして特定のドメインだけをプロキシに通す構成では、デフォルトの動作が異なります。設定を移行する際は、まずどちらの動作にするか決めてからルールを確認してください。タグがそろっているかを見るだけでは不十分です。
directとblock、2つの基本的なoutbound
freedomはローカルのネットワークを使って宛先に接続します。ドメインの名前解決が不要という意味ではなく、宛先に必ず接続できる保証もありません。blackholeは選択された通信を拒否します。誤って先頭に置くと、ルールに一致しないリクエストまで拒否される場合があります。以下の断片はroutingの基本設定と組み合わせて使えます。2つのタグがそれぞれ直接接続とブロックを示しますが、リモートプロキシへの接続設定は含みません。
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
]
}
routingのoutboundTagは、ここで指定したタグと大文字・小文字やハイフンまで完全に一致させてください。タグを変更したら、参照している箇所もすべて確認します。同じタグを複数のoutboundに付けると、設定の把握や問題の切り分けが難しくなるため、タグを重複する分類名として使わないでください。参照先がない場合、設定の読み込み時にエラーになることもあれば、リクエストの処理時に問題が表面化することもあります。
ローカルの上流サービスでoutboundの構造を確認
以下のoutboundは、リクエストをローカルホスト上の別のSOCKSサービスに渡します。リモートアカウントが不要なため、サーバー一覧の階層構造を確認する例として使えます。ただし、127.0.0.1:2080で別のサービスが実際に待ち受けている場合に限り動作します。このポートを現在のカーネル自身のinboundに向けると、通信がループすることがあります。個別にテストする場合は、先に上流サービスが利用可能か確認してください。
{
"outbounds": [
{
"tag": "upstream",
"protocol": "socks",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": 2080
}
]
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
}
]
}
VMess、VLESS、Trojan、Shadowsocksでは認証の構造が異なります。サーバーアドレス、ポート、ユーザーIDやパスワード、暗号化方式はサーバー側から提供された設定を使ってください。protocol名を変更するだけでプロトコルを変換することはできません。プロトコルのパラメーターに加えて、トランスポートやTLSの条件が関係する場合もあります。クライアントがリンクをインポートできても、それだけでリモート認証やトランスポートの設定が一致しているとは限りません。
接続エラーをどの段階で調べるか
リモートアドレスがドメイン名の場合、プロキシ接続を確立する前に名前解決が必要になることがあります。この名前解決を、まだ確立していないプロキシ経由に限定すると、依存関係が循環してしまいます。接続ログに表示される名前解決失敗、接続タイムアウト、接続拒否、認証失敗、TLSハンドシェイク失敗は、それぞれ異なる段階の問題です。出口のパラメーターを次々に変更するより、エラーが発生した段階から順に調べるほうが効率的です。
多段転送を設定する場合は、現在のカーネルが対応するoutbound連鎖の項目と適用範囲を確認してください。他のカーネル向けの例をそのまま組み込んではいけません。ローカルの上流待ち受け、中間の出口、最終出口にはそれぞれ異なる障害要因があります。経路が長いほど、1段ずつの検証が重要です。通常のサブスクリプション利用ではクライアントが生成する単一outboundの設定を維持し、追加の中継が必要な理由を明確に説明できる場合にだけ複雑な構成を加えましょう。
サブスクリプションを更新するとサーバー情報は置き換わっても、カスタム設定内の古いアドレス、認証パラメーター、タグが更新されるとは限りません。画面では更新済みなのに古い情報で接続している場合、選択中の設定の種類と起動ログを確認してください。設定を共有する際は、認証情報、サブスクリプションURL、個人アカウントに結び付く情報を削除してください。階層、プロトコル名、エラーが起きた段階が残っていれば、構造上の問題を話し合うには十分なことが多いです。
4. routing:ルールの順序と出口の選択
条件に一致した後で出口を選ぶ
routingはサーバー一覧ではなく、カーネルに入ったリクエストを判定する仕組みです。ルールは通常、配列の先頭から順に評価され、条件に一致すると対応するoutboundを選択して、その後のルールは確認しません。そのため、広い範囲に一致するルールを先頭に置くと、後ろにある細かなルールが適用されないことがあります。設定を読むときはドメインとIPのルールを別々に確認して結果を推測せず、先頭から条件を追っていきましょう。
1つのルール内では、通常、異なる種類の条件をすべて満たす必要があります。同じ種類の条件に複数の値を指定した場合は、そのいずれかに一致すれば条件を満たします。たとえばinboundTagとdomainを同時に指定すると、特定のinboundから入り、宛先のドメインも条件に一致する通信が対象になります。どちらか一方に一致すればよいという意味ではありません。異なるケースを表す場合はルールを分けてください。タグ条件を使うと、ブラウザー用の入口と他のアプリ用の入口を区別しやすくなります。
読みやすいルールの例
以下の断片を使うには、第3章のdirectとblockのoutboundが必要です。例として、ブロック対象のドメイン、プライベートアドレス、ドキュメント用のテストドメインの順に処理します。geoip:privateを使うには、実行環境に対応するデータリソースが必要です。ログにデータファイルの不足が表示された場合は、リソースのパスを修正するか、実際のネットワークに合うCIDRのリストを明示してください。起動エラーを無視しないでください。
{
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": ["full:blocked.example.com"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["domain:example.com"],
"outboundTag": "direct"
}
]
}
}
full:はドメイン全体との完全一致に使います。domain:は指定したドメインとそのサブドメインに使います。どちらにもWebページのパス、クエリパラメーター、プロトコルのプレフィックスは指定しません。特定のWebサイトへの通信を判定するために、URL全体をドメインの配列に入れることはできません。正規表現はパターンによる指定が必要な場合に便利ですが、内容を確認しにくくなります。ドメインを明示できるなら、複雑な正規表現は避けましょう。
ドメインのルーティングポリシーはDNS全体を制御するものではない
AsIsは、routingの段階で既存の宛先情報をできるだけ維持し、IPルールのためにドメインを積極的に名前解決しません。IPIfNonMatchはドメインの判定で一致しなかった場合に名前解決を試み、続けてIPルールを判定します。IPOnDemandは、IP判定が必要なルールに達したときに名前解決を行います。実際の処理はリクエストにドメイン名とIPアドレスのどちらが含まれているかにも左右されるため、ポリシー名だけで判断しないでください。
アプリがドメインをIPアドレスに名前解決してからローカルプロキシに接続すると、カーネルが元のドメイン名を取得できないことがあります。トラフィック検出で情報を補える場合もありますが、すべてのプロトコルに対応するわけではありません。「ドメインルールに一致しない」場合は、まずinboundが受け取った宛先の形式を確認し、次に検出結果を確認してからドメインのリストを調べてください。情報不足をルール構文の誤りと取り違えやすいためです。
ポート、ネットワーク種別、プライベートアドレス
portが判定するのは宛先サービスのポートであり、ローカルプロキシの待ち受けポートではありません。networkではTCPとUDPを区別できます。Web通信のポートをすべてプロキシに振り分けても、特定のブラウザーの動作全体をプロキシ経由にできるわけではありません。DNS、リアルタイム通信、その他のプロトコルでは異なる宛先ポートが使われることがあります。通常の項目によるroutingから、プロセス単位で出口を選択できると推測することもできません。
プライベートアドレスのルールを使うと、ルーターの管理画面、LAN内のサービス、ローカルリソースへの直接接続を維持できます。ただし、ドメインがプライベートアドレスに名前解決された場合にIPルールへ一致するかは、routingがその結果を取得できるかどうかによります。合成アドレス方式を使う場合は、マッピングや通信の取り込みをカーネルの要件に従って処理してください。合成アドレスを通常のプライベートアドレスと同様に直接接続すると、必要な復元処理を迂回することがあります。
ルールを検証する際は、宛先を1つ選び、出口タグを確認できるログを一時的に有効にしてリクエストを1回送信します。その後、inbound、宛先、outboundを確認してください。リクエストが再試行されて複数のログが残ったり、ブラウザーのバックグラウンド接続が判定に影響したりすることがあります。切り分けにはコマンドラインから単一のリクエストを送るほうが適しています。接続テストについては初回接続とプロキシ動作の確認方法もご覧ください。ページの表示速度だけでroutingを判断しないでください。
5. dns:名前解決の経路と循環依存
まず3種類の名前解決を区別する
DNSを設定する前に、アプリによる名前解決、カーネル内蔵の名前解決、リモートサーバーによる名前解決を区別してください。アプリがシステムからIPアドレスを取得して、そのIPをプロキシに渡すこともあります。ドメイン名をSOCKSに渡し、後続の経路で処理することもあります。カーネル内のdnsオブジェクトが影響するのは、内蔵リゾルバーを使う経路だけです。システムのリゾルバーを自動的に置き換えるものではなく、ブラウザーごとに設定した暗号化DNSの動作も変更しません。
サーバー自身のドメイン名も名前解決が必要ですが、最終的にアクセスするWebサイトのドメイン名とは別の処理です。前者はプロキシ接続を確立するための前提で、後者はプロトコルやoutboundの動作に応じてリモート側で処理される場合があります。DNSの問題を調べる際は、この2つのドメイン名を分けて記録してください。サーバーアドレスを名前解決できなければ、どのWebサイトにも接続できないことがあります。それだけで、すべての宛先サイトの名前解決に問題があるとは判断できません。
基本項目と条件付きの名前解決
serversには、単純なDNSサーバーアドレスのほか、条件付きのオブジェクトも指定できます。hostsでは、内蔵リゾルバーに明示的な名前解決の対応を設定できます。以下の例では、固定のマッピングとドメイン条件付きのサーバーを配置する階層を示します。すべてのネットワークで推奨される設定ではありません。実際のサーバーへの到達性、ネットワークポリシー、プライバシー上の要件を検討してください。パブリックDNSアドレスがどの環境でも使えるとは限りません。
{
"dns": {
"hosts": {
"lab.example.com": "192.168.50.10"
},
"servers": [
{
"address": "1.1.1.1",
"port": 53,
"domains": ["domain:example.com"]
},
"8.8.8.8"
]
}
}
例に使うLAN内アドレスは静的マッピングの説明用です。ローカルに該当するサービスが存在する場合にのみ意味があります。カーネルのhostsはOSのhostsファイルと同じではありません。リクエストが内蔵リゾルバーを通らなければ、このマッピングは使われないことがあります。ドメイン名に固定のアドレスを割り当てる場合は、サービスアドレスの変更、複数地域の接続先、証明書の名前も考慮してください。固定IPは、通常の名前解決に代わる万能な方法ではありません。
DNSクエリの送信方法とフォールバック
DNSサーバー項目のドメイン条件は、どのDNSサーバーで名前解決するかを選ぶもので、通信のプロキシ出口を選ぶものではありません。通信のルーティングはroutingで処理します。条件付きのDNSサーバーが失敗した場合に別のサーバーを使うか、並列でクエリを送るか、返されたアドレスを採用するかは、使用中のカーネルが対応する項目を確認してください。異なるカーネルのフォールバック設定を流用せず、変更前に項目名と実際の意味を確かめましょう。
内蔵DNSが送信するクエリにもネットワーク経路があります。一部の形式はカーネルのroutingを通りますが、ローカルネットワーク上で名前解決する形式もあります。「暗号化DNSを使っている」というだけでは、クエリがどの出口を通るかは判断できません。ドメイン形式でDNSサーバーを指定する場合は、そのサーバー自身のドメイン名を解決するための初期設定も必要です。その解決が同じDNSサーバーに依存すると、循環する可能性があります。
典型的な循環依存は、プロキシ接続にサーバーのドメイン名解決が必要なのに、その名前解決をまだ確立していないプロキシ経由に限定している状態です。依存関係の順序を整理し、まず接続を確立するための名前解決経路を確保してから、通信先のドメインを処理してください。すべてのDNSクエリを同じプロキシ出口に送る設定は、一見シンプルですが、起動時の処理を完了できなくなる可能性があります。
IPv4、IPv6、キャッシュ
AAAAレコードを取得できても、現在のネットワークでIPv6接続が安定しているとは限りません。IPv4でしか接続できなくても、ドメインにIPv6のサービスがないとは限りません。クエリポリシーを変更すると返されるアドレスの種類は変わりますが、ルーター、通信事業者のネットワーク、リモート側の待ち受けの問題は解決しません。一部の宛先でタイムアウトが発生する場合は、名前解決の結果と実際の接続先アドレスをそれぞれ確認してから、比較テストとして一時的にアドレスファミリーを制限するか検討してください。
DNSキャッシュはブラウザー、OS、クライアント、リモート側など複数の場所に存在することがあります。設定を変更しても同じドメインで以前と同じ動作が続くからといって、新しい設定が反映されていないとは限りません。まず実際に名前解決を担当するコンポーネントを再起動するか、別のテスト用ドメインで確認してください。キャッシュを消すためにクライアントの全データを削除すると、サブスクリプション、routing、サーバー選択など別の要因が加わるため避けましょう。
curlでテストする場合、socks5://とsocks5h://ではドメイン名の処理が異なります。後者では宛先のドメイン名をSOCKSプロキシ側に渡します。この違いを使うとローカルでの名前解決が関係しているか確認できますが、テストの成功が示すのはそのリクエスト経路が使えることだけです。サブスクリプション更新時の名前解決エラーも調べる場合は、サブスクリプション更新に失敗する場合の対処をご覧ください。サブスクリプションのダウンロードには、現在のプロキシ経路が使われるとは限りません。
6. policy:タイムアウト、ユーザーレベル、統計
policyは動作を制御し、出口を選ばない
policyは、ハンドシェイクの待ち時間、アイドルタイムアウト、統計の有効・無効など、接続の処理方針を設定します。routingルールではなく、特定のドメインを直接接続するかプロキシ経由にするかを決めるものでもありません。接続に失敗した場合は、まずどの段階で失敗したか確認してください。ログから待ち時間やアイドル切断が原因とわかった場合にのみ、policyを調整する理由があります。すべてのタイムアウトを延ばすと、エラーの発生が遅くなるだけの場合もあります。
levelsのキーはユーザーレベルを表し、JSONでは文字列で記述します。速度の段階やサブスクリプションのプランではなく、プロトコルのユーザー設定から参照されるpolicyのインデックスです。参照できるユーザーレベルが存在するかは、該当するinboundとプロトコルによって異なります。専用レベルを設定していない場合は、デフォルトの動作を確認してください。レベルのオブジェクトを追加するだけで、すべての通信に自動適用されるわけではありません。
接続時間に関する項目の意味
以下の断片では、レベル0とシステム統計の有効・無効の構造を示します。時間の単位は秒です。数値は記述形式を示す例であり、あらゆるネットワークに推奨される最適値ではありません。カーネルのデフォルト値を維持する場合は、該当項目を明示しなくてもかまいません。変更する場合は元の動作を記録し、1項目ずつ比較してください。特に長時間接続するアプリでの結果を残しておきましょう。
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5,
"statsUserUplink": false,
"statsUserDownlink": false
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true
}
},
"stats": {}
}
handshakeは、このpolicyの対象となるプロトコルのハンドシェイク待ち時間を指します。すべてのリモート接続、TLSネゴシエーション、Webページの応答に共通するタイムアウトではありません。connIdleは、有効なデータ通信がない接続をアイドル状態として扱う時間です。リアルタイム通信、リモートセッション、プッシュ通知では、実際の通信データがない状態が長く続くことがあります。短く設定しすぎると再接続が増え、長すぎると無効な接続が長くリソースを占有する可能性があります。
uplinkOnlyとdownlinkOnlyは、接続の片側が終了した後、もう片側の通信を継続できる待ち時間に関する設定です。アップロードやダウンロードの速度制限ではありません。短い値にすると接続を早く解放できますが、半閉鎖状態のセッションで残りのデータが切り捨てられることがあります。大きなファイルのダウンロード、ストリーミング応答、長時間接続するリクエストをテストする際は、短いWebページだけでなく、こうした終了時の動作も確認してください。
統計設定と表示画面の関係
統計を有効にするには、通常、statsオブジェクトと対応する統計policyの両方が必要です。システム全体の統計はinboundなどのオブジェクトを対象とし、ユーザーごとの統計にはプロトコルユーザーを識別できる設定が必要です。ユーザー統計を有効にしても、匿名のSOCKSリクエストがすべて個別のユーザーレポートに表示されるわけではありません。統計の名称や読み取り方法は、カーネルのサービスインターフェースとクライアントの実装にも左右されます。
設定で統計を累積するようにしても、グラフィカルな画面に数値が必ず表示されるわけではありません。統計を読み取るプログラムには、適切なインターフェースと呼び出し方法が必要です。インターフェースの待ち受け範囲も信頼できるネットワークに制限してください。通常の利用ではv2rayN自体の統計機能を使い、特定の数値を画面に表示するためだけに制御用インターフェースを公開する必要はありません。統計に記録がない場合は、まず通信が対象のオブジェクトを通っているか確認してください。
ログレベルとリソース使用量
通常利用では、warningなど控えめなログレベルに設定できます。トラブルシューティングの際だけ詳細なログレベルに一時変更し、問題を再現したらすぐ元に戻してください。ログが増え続けるのを防げます。アクセスログはリクエストの経路、エラーログは接続が失敗した段階を確認するためのものです。ログファイルのパスに書き込み権限がないと、記録されないことがあります。ログがないからといって、リクエストもないとは限りません。
ファイルにログを出力する場合、通常ユーザーとして動作するデスクトップクライアントから、管理者しか書き込めないシステムディレクトリを指定しないでください。ディスク容量不足、読み取り専用ディレクトリ、セキュリティポリシーによって、ログの確認に影響が出ることがあります。クライアントを起動するとすぐ終了する問題を調べる場合は、接続policyより先にプロセスの起動状況とディレクトリの権限を確認してください。手順はv2rayNが起動時にクラッシュする場合の対処をご覧ください。
policy項目では、OSレベルのプロセス優先度、全体の帯域制限、電源管理は設定できません。Androidのバックグラウンド制限、Linuxのスリープ復帰、ネットワークインターフェースの切り替えによって、既存の接続が無効になることがあります。アイドル時間を延ばすだけでは解決しません。スリープ後に接続が復旧しない場合は、まずスリープ前後の状態とネットワークの変化を確認し、クライアントのバックグラウンド動作条件、システムプロキシの復元状態、カーネルログを個別に調べてください。
7. プロトコル、トランスポート、カーネルの互換性
接続を3つの層に分けて考える
サーバー設定では、プロキシプロトコル、接続を運ぶトランスポート、セキュリティ層を区別してください。VMess、VLESS、Trojan、Shadowsocksはプロキシ通信や認証を扱います。TCPやWebSocketなどは接続の運び方を示し、TLSなどのセキュリティ機構は接続を保護します。3つの層の設定はサーバー側と一致させる必要があります。ドメイン名とポートが正しくても、トランスポートの種類、パス、証明書の名前を確認してください。
設定内のsettingsはプロキシプロトコル、streamSettingsは接続のトランスポートに関する項目です。WebSocketのパスをプロトコルのユーザー設定に入れても、通常は期待した動作になりません。認証項目をトランスポートに入れても、プロトコル認証はできません。同じリンクを何度もインポートするより、まず項目の階層、次に値を確認しましょう。
WebSocketとTLSの設定例を確認する
以下は、対応するoutboundオブジェクト内で使うトランスポートの断片であり、単独では動作しません。実際のサーバーのプロトコル設定と組み合わせる必要があります。例のドメイン名とパスは項目の配置を示すためのもので、接続可能なサーバーではありません。クライアントが生成した項目名と異なる場合は、選択中のカーネルが実際にサポートする構造を優先してください。特に異なる世代のトランスポート名を、自由に置き換えられる別名として扱わないでください。
{
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "edge.example.com",
"allowInsecure": false
},
"wsSettings": {
"path": "/proxy",
"headers": {
"Host": "edge.example.com"
}
}
}
}
outboundのサーバーアドレスは最初の接続先を決めます。TLSのserverNameはサーバー名表示と証明書の検証に使われます。WebSocketのHostはHTTP Upgradeリクエストのホスト情報です。これらの値は同じ場合も、正規のリバースプロキシ構成で異なる場合もありますが、推測で設定しないでください。正しいIPアドレスに接続していても、名前が一致しないと接続先のフロントエンドで拒否されることがあります。
WebSocketのパスはサーバー側のルーティングと一致させる必要があります。先頭のスラッシュ、大文字・小文字、末尾のスラッシュ、クエリ部分が処理に影響することがあります。想定外のHTTP応答が返る場合は、リバースプロキシが正しいバックエンドにリクエストを転送しているか確認してください。ブラウザーでドメインのトップページを開けても、指定したUpgradeパスやプロキシプロトコルのバックエンドが正常とは限りません。
証明書エラーを検証無効化で隠さない
allowInsecureは無効のままにしてください。証明書エラーが発生した場合は、システム時刻、証明書の有効期限、名前の一致、証明書チェーンの完全性、システムの信頼ストアをそれぞれ確認します。企業ネットワークで正規の内部証明書を使う場合は、組織のルールに従って信頼設定を管理してください。すべての接続で検証を無効にすることは避けましょう。無効にすると、誤ったサーバーを識別する能力が弱まり、設定の問題も隠れてしまいます。
TLSハンドシェイク失敗は、セキュリティ層の不一致が原因の場合もあります。クライアントがTLSで接続しようとしているのに、サーバー側の該当ポートが通常のTCPしか受け付けない場合や、その逆です。認証前に発生するエラーもあるため、ユーザーIDを変更しても解決しません。まずポートで実際に動作しているサービスを確認し、次にセキュリティ層、トランスポートのUpgrade、プロキシ認証の順に調べてください。順序立てて確認すれば、無駄な試行を減らせます。
V2Fly、Xray、クライアントの役割
Project Vは、関連するモジュール型プロキシ設計の背景となるプロジェクトです。V2FlyとXrayは異なるカーネルの系統に属します。基本的なJSON構造には共通点がありますが、新しいプロトコル機能、セキュリティ層の項目、routingの一部の動作は異なります。REALITYを使用するには、カーネルが対応しているか確認してください。任意のV2Ray設定に関連項目を追加できるわけではありません。具体的なパラメーターはサーバー側と一致する設定情報を参照してください。
デスクトップでv2rayNを使う場合は、現在の設定が実際にどのカーネルを呼び出しているか確認してください。Androidでv2rayNGを使う場合はXrayの設定機能を、v2flyNGを使う場合はV2Flyの機能を前提に確認します。クライアント名だけで対応する項目の集合が決まるわけではなく、画面が似ているからといって互換性があるとは限りません。選び方は3つのクライアントとカーネルの比較を参考にしてから、移行するか判断してください。
設定を移行する際は、プロトコル、認証、セキュリティ層、トランスポート、routing、DNSの順に確認し、まず動作するサーバーを1つ残してから追加ルールを移してください。見慣れない項目があっても、削除してそのまま使い続けないでください。接続に必要な設定の可能性があります。設定を読み込めることと、元の意図どおりに動作することは別です。最終的には、明確なリクエストとログで実際の動作を確認してください。
8. 設定の統合、検証、段階的なトラブルシューティング
実際に読み込まれる設定の場所を変更する
変更前にクライアントのデータを書き出すかバックアップし、現在動作しているカスタム設定も別名で保存してください。通常のサーバー情報はv2rayNの画面から編集し、ルーティングプリセットはルーティング管理から変更します。完全なカスタム設定は独立して管理してください。クライアントが生成した一時ファイルを編集しながら画面上でサーバーを切り替えると、最終的にどの設定が使われているか判断しにくくなります。
この記事の断片を統合する際は、まず項目のチェックリストを作成してください。トップレベルには同名のキーを1つだけ置く、inboundのポートを既存の待ち受けと重複させない、outboundのタグを一意にする、ルールから参照するタグが存在する、必要なデータリソースがそろっていることを確認します。例にあるプライベートアドレスやドキュメント用ドメインは、目的に応じて処理してください。不要なルールは削除し、説明用の設定を長期間残さないようにしましょう。
入口を確認してから出口を確認する
第1章の完全なベース設定に戻して起動したら、以下のSOCKSテストを実行できます。ローカルホストの10808でSOCKSリクエストを受け付けている必要があります。接続先には公開されているドキュメント用のテストドメインを使用し、個人のサーバー情報には依存しません。現在のネットワークでそのサイトを利用できない場合は、接続できることが確認済みのHTTPSアドレスに置き換えてもかまいません。ただし、比較テストの間は接続先を変えないでください。
curl -I --connect-timeout 10 --max-time 20 \
--proxy socks5h://127.0.0.1:10808 \
https://example.com
第2章の2つのinboundを使う場合は、HTTP入口も個別にテストできます。対象のポートを実際に有効にしている場合に限り、以下のコマンドを実行してください。サーバーから成功、リダイレクト、その他の有効なHTTPステータスが返ることがあります。応答があれば、そのリクエストがHTTPサービスに到達したことはわかりますが、リモートプロキシを経由したとは限りません。ベース設定はdirectのoutboundを使うため、その結果をサーバーへの接続確認として扱わないでください。
curl -I --connect-timeout 10 --max-time 20 \
--proxy http://127.0.0.1:10809 \
https://example.com
システムプロキシだけに依存するより、プロキシアドレスを明示したほうが環境変数、デスクトップ設定、アプリの互換性による影響を減らせるため、トラブルシューティングに適しています。システムプロキシを検証する場合は、実際のアプリからリクエストを送り、inboundのログを確認してください。コマンドでは動作してブラウザーで動作しない場合は、ブラウザーの設定が原因かもしれません。ブラウザーでは動作して特定のプログラムでは動作しない場合は、そのプログラムのプロキシ対応やDNSの動作を確認してください。
エラーが起きた段階から原因を絞る
| 確認できた現象 | 最初に確認する項目 | 次に行うこと |
|---|---|---|
| カーネルが起動しない | JSONの階層、項目の対応状況、リソースファイル | 最小構成に戻し、設定を少しずつ追加する |
| ローカル接続が拒否される | 待ち受けアドレス、ポート、プロセスの状態 | リクエストのプロトコルとinboundが一致するか確認する |
| 名前解決に失敗する | サーバーのドメイン名とDNSの初期解決経路 | サーバーの名前解決と宛先の名前解決を区別する |
| リモート接続がタイムアウトする | アドレス、ポート、ネットワークの到達性 | リモートサービスを確認してからトランスポートを調べる |
| TLSまたは認証に失敗する | 名前、時刻、トランスポート、認証項目 | サーバー側の設定と層ごとに照合する |
| 一部の宛先だけで問題が起きる | 一致したルール、アドレスファミリー、outboundタグ | 宛先を1つに絞って繰り返し比較する |
カーネルの起動後にリクエストの記録がまったくない場合は、リモートサーバーを疑う前にアプリがプロキシに接続しているか確認してください。リクエストの記録はあるのにoutboundタグが想定と異なる場合は、ルールの順序とデフォルトoutboundを確認します。outboundが正しい場合は、サーバー名の解決、ネットワーク接続、TLS、認証を調べてください。根拠が得られた段階から、1つずつ先へ確認しましょう。
pingの結果をプロキシプロトコルのテストとして扱わないでください。宛先がICMPを拒否しても通常の通信を受け付けることがあります。逆にICMPに応答しても、指定したポートでサービスが待ち受けているとは限りません。同様に、TCP接続が確立しても、期待するプロトコルを使うサービスが存在するとは限りません。入口のテスト、ポートへの到達性、プロトコルのハンドシェイク、実際のリクエストを別々に記録し、1つの結果で接続経路全体を判断しないでください。
設定を戻して再確認する
変更後の検証に成功したらクライアントを再起動し、同じテストをもう一度実行してください。設定が再生成されて上書きされていないことを確認できます。その後、LAN内のリソース、プロキシが必要な宛先、長時間接続するアプリをテストし、1つの経路を直したことで別の経路が使えなくなっていないか確認します。ネットワーク切り替え後やスリープ復帰後の動作も個別に確認してください。デスクトップでシステムプロキシやTUNを有効にしている場合は特に重要です。
問い合わせ時は、カーネル名、OS、エラーが発生した段階、機密情報を削除した設定断片を共有してください。サブスクリプションURL、認証情報の全体、アカウント情報を含むログは公開しないでください。変更後に原因を特定できない場合は、バックアップに戻し、この章の順に最小限のテストからやり直してください。よくある現象についてはよくある質問をご覧ください。インポートや接続手順を最初から確認する場合は利用ガイドに戻ってください。設定の切り分けをせず、何度も再インストールする方法に頼らないでください。