クライアントへの設定インポートを済ませ、コアの実行設定を理解したい方向けの記事です。ローカルinbound、directと拒否用outboundだけを含む完全なJSONから構造を確認し、tagの参照関係、ルーティングの順序、DNSとの関係を解説します。例にはリモートプロキシサーバーを含みません。読み終えると、リクエストの入口、適用されるルール、変更後に確認すべき項目が分かります。
1. クライアント設定とコア設定を区別する
v2rayN、v2rayNG、v2flyNGはクライアントであり、コアそのものではありません。クライアントはサブスクリプションやノード、操作画面を管理し、関連設定をコアが読み込める形式に変換します。v2rayNGはXrayコア、v2flyNGはv2flyコアを使用します。v2rayNの実行設定は、選択中のコアに応じて判断してください。コアやバージョンが異なると、対応する項目も異なります。
この記事では、V2Rayで使われる従来のJSON設定形式の一般的な項目を取り上げます。実際の設定を読む際は、まずコアの設定ファイルか、クライアント独自の設定ファイルかを確認しましょう。画面で保存したサブスクリプションのグループ、ウィンドウ設定、更新設定などは、コアのconfig.jsonに含まれないことがあります。一方、実行設定のローカルポートはクライアントが自動生成している場合があります。
この流れは、アプリがローカルプロキシを明示的に使用する場合のものです。コアを起動しただけで、すべてのプログラムがローカルポートに接続されるわけではありません。システムプロキシ、アプリ内プロキシ、TUNでは接続方法が異なります。この記事ではSOCKSまたはHTTPのinboundを前提とし、接続範囲の問題をルーティングの誤りと混同しないようにします。
2. config.jsonの全体例
以下は構造を読み解くための完全な設定例です。2つのループバックアドレスとポートで待ち受け、example.orgへの完全一致リクエストを拒否し、それ以外の通信はdirectで接続します。example.orgはドキュメント用の例示ドメインで、利用可能なノードを示すものではありません。VMessやVLESSのリモートoutboundは含まれていないため、通信はプロキシサーバーに転送されません。
{
"log": {
"loglevel": "warning"
},
"dns": {
"servers": [
"1.1.1.1"
]
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": [
"full:example.org"
],
"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"
],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": [
"socks-in",
"http-in"
],
"network": "tcp,udp",
"outboundTag": "direct"
}
]
}
}
標準JSONでは、キー名と文字列を二重引用符で囲み、配列やオブジェクトの最後の項目の後に余分なカンマを付けてはいけません。コードブロックにはコメントがないため、単独の読み取り用サンプルとして保存できます。特定のコアで読み込めるかどうかは、そのコアの設定検証コマンドで確認してください。
3. inbounds:待受アドレス・ポート・入口タグ
inboundsは配列です。1つのコアプロセスで複数の入口を受け付けられます。各入口のprotocolで受け付けるプロトコルを指定し、settings内の項目はプロトコルによって異なります。この例のSOCKS入口にあるudp: trueは、SOCKS UDP転送を許可する設定です。すべてのアプリのUDP通信が自動的に取り込まれるという意味ではありません。
SOCKS入口
- tag
- socks-in
- listen
- 127.0.0.1
- port
- 10808
- protocol
- socks
- auth
- noauth
アプリからこのSOCKS入口への接続が必要です。ループバックで待ち受けるため、接続範囲はこの端末内に限定されます。
HTTP入口
- tag
- http-in
- listen
- 127.0.0.1
- port
- 10809
- protocol
- http
- settings
- 空のオブジェクト
HTTPプロキシリクエストやCONNECTトンネルに使用します。ローカルでWebサイトを公開する設定ではありません。
listenとportで待受位置を指定します。127.0.0.1を0.0.0.0に変更すると接続可能な範囲が変わり、ほかの端末からプロキシポートにアクセスできるようになる場合があります。この例では認証なしのSOCKSも使用しているため、接続しやすくする目的で待受範囲を安易に広げないでください。LANから接続する必要がある場合は、認証とファイアウォールも合わせて設定しましょう。
tagは設定内で参照するための識別子で、サーバーアドレスではなく、新しいポートを自動作成するものでもありません。3つ目のルーティングルールにあるinboundTagは、ここに設定した2つの文字列を参照します。入口タグを変更した場合は、対応するルールも同じ大文字・小文字とハイフンで変更してください。
4. outbounds:接続方式とデフォルトの行き先
outboundsでは、通信がコアから出る際の処理方法を定義します。freedomは端末から接続先へ直接接続し、blackholeは通信を拒否します。ここでのdirectとblockは任意に付けたタグ名です。outboundの動作を決めるのはprotocolであり、タグ名から動作が決まるわけではありません。
| 位置 | 項目または値 | 実際の役割 |
|---|---|---|
| 1つ目のoutbound | tag: direct | ルールから参照され、この例ではどのルールにも一致しない場合のデフォルトoutboundになります。 |
| directプロトコル | protocol: freedom | 接続先アドレスに直接接続します。 |
| 2つ目のoutbound | tag: block | 完全一致のドメイン拒否ルールから参照されます。 |
| 拒否プロトコル | protocol: blackhole | リクエストを接続先サーバーに転送しません。 |
ここで使っている一般的なルーティング方式では、どのルールにも一致しない場合、最初のoutboundが使われます。そのため、outbounds配列の順序変更は、表示順を整えるだけではなく、デフォルトの通信経路を変える可能性があります。この例では、既知の2つの入口に対して最後にdirectルールを追加し、デフォルトの動作を分かりやすくしています。
要点:outboundを変更する前にタグの参照を確認
まず、すべてのoutboundTagを検索し、既存outboundのtagに対応していることを確認します。次に、1つ目のoutboundが、どのルールにも一致しない通信に対する想定と合っているか確認してください。タグ名を間違えても、同じ名前のプロトコルに自動で切り替わるわけではありません。
リモートノードを利用するには、実際のパラメーターを設定し、使用中のコアが対応するプロキシoutboundを追加して、該当ルールから参照します。VMessとVLESSでは、ユーザー情報、トランスポート層、セキュリティ設定が異なります。protocolの文字列だけを変更しても、変換が完了したことにはなりません。信頼できるサブスクリプションをインポートして生成された設定を参考に、サーバー、ポート、ユーザーID、トランスポート設定を1つずつ確認してください。
5. routing:ルールの順序と照合条件
routing.rulesは順序のあるルール配列です。リクエストごとに先頭から確認し、一致したルールで指定されたoutboundを使います。後続のルールをすべて実行するわけではありません。条件の広いルールを先に置くと、後続の詳細なルールが一度も適用されないことがあります。
- 最初に完全一致のドメインを照合します。
full:example.orgはそのドメイン名だけに一致し、サブドメインは対象外です。リクエストにドメイン名が含まれるか、コアがドメイン名を取得できる場合に、このドメインルールで照合できます。 - 次に指定したIPアドレス範囲を照合します。この例ではループバックと、よく使われる3つのプライベートIPv4範囲を指定し、一致した通信を
directに送ります。特殊用途アドレスの一覧を網羅しているわけではなく、IPv6のプライベートアドレスやリンクローカルアドレスも対象外です。 - 最後に2つのローカル入口からの通信を照合します。
socks-inまたはhttp-inから入り、ネットワーク種別がTCPまたはUDPのリクエストをdirectに送ります。
1つのルールで、inboundTag配列内の入口は「いずれか1つに一致すればよい」という条件です。一方、同じルール内の異なる条件項目は通常すべて満たす必要があります。したがって3つ目のルールは「この2つの入口から、またはTCP」ではなく、「この2つの入口のいずれかから入り、さらにネットワーク種別も一致する」という意味です。
domainStrategy: "AsIs"は、IPルールとの照合のためにドメイン名を積極的にIPアドレスへ解決しない設定です。アプリからコアにドメイン名が渡された場合、最終的にプライベートIPへ解決される可能性があるというだけでは、2つ目のプライベートアドレスルールに一致しません。IPアドレスが渡された場合は、そのままアドレス範囲を照合できます。この設定が制御するのはルーティング段階の処理であり、接続中にDNS問い合わせが発生しないという意味ではありません。
6. dnsとlog:名前解決とルーティングを混同しない
この例ではdns.serversに1.1.1.1を設定しています。これはコア内蔵DNSのサーバー設定であり、OSやブラウザー独自の名前解決設定を自動的に置き換えるものではありません。この項目を設定しただけで、すべてのDNSリクエストがプロキシ経由になる保証もありません。どのモジュールが内蔵DNSを使うか、名前解決の通信がどの経路を通るかは、使用するコアや関連ポリシーに応じて確認してください。
- ルーティングポリシーでは、ドメイン名やIPアドレスが照合にどう使われるかを確認します。この記事の
AsIsは、IPルーティングルールのためにドメイン名を追加で解決しません。 - outbound接続時には、名前解決が必要になる場合があります。
freedomは最終的に接続を確立する必要があり、どの名前解決経路を使うかはoutboundのポリシーやコアの実装にも左右されます。 - アプリが独自に名前解決する場合もあります。アプリ内のセキュアDNSやシステムの名前解決によるリクエストが、設定に
dnsがあるだけで必ず取り込まれるわけではありません。 - ネットワーク環境に合わせてアドレスを選びます。例のDNSサーバーは構造を示すためのもので、すべてのネットワーク環境で接続できる、または適切であることを示すものではありません。
log.loglevelはwarningに設定されており、警告やエラーを優先して確認する場合に適しています。ルールの調査中は、一時的にinfoに変更できます。より詳細な情報が必要な場合はdebugも検討してください。ログレベルはアクセスログのファイルパスを示すものではなく、すべてのバージョンで同じ形式のログが出力される保証もありません。ログを共有する前に、サブスクリプションURL、ユーザーID、サーバーアドレス、アクセス先などの機密情報を削除してください。
7. 変更・検証・復元の手順
クライアントは、ノードの切り替え、サブスクリプションの更新、再起動などの際に、実行設定を再生成することがあります。自動生成されたファイルを直接編集すると、次回の操作で変更が上書きされる可能性があります。「生成された設定を確認する」のか「カスタム設定を使う」のかを区別し、クライアント画面から変更するか、提供されているカスタム設定機能を使うか判断してください。
- 元に戻せるようにコピーを保存します。元の設定を残し、使用中のコア、設定ファイルの場所、待受ポートを記録してください。サブスクリプションURLを公開メモに記載しないでください。
- 変更するのは一度に1つの項目だけにします。たとえばドメインルールを1つ追加する場合、DNS、ポート、リモートノードを同時に変更しないでください。どの変更が影響したのか分からなくなるのを防げます。
- まず構文と設定を検証します。標準JSONの検証ではカンマや引用符の誤りを確認できます。コアによる検証では、未対応のプロトコルや項目の型、一部の参照ミスも検出できます。
- 次に起動して待受状態を確認します。アドレスが使用中と表示された場合は、10808や10809をクライアントがすでに使っていないか確認してください。同じポートを使う設定でコアを2つ同時に起動しないでください。
- 最後に実際の通信経路を検証します。アプリがローカル入口に接続していることを確認してから、対象リクエストが想定したoutboundに一致するかを確認します。失敗した場合は、直前の動作する設定に戻してください。
よく使われるコアのコマンドライン検証方法は次のとおりです。どちらか一方を使い、異なるコアに続けて適用しないでください。実行ファイル名や呼び出し方は、使用しているOSに合わせてください。現在のバージョンでオプションが認識されない場合は、そのコアのhelp出力を確認してください。検証に成功しても、設定が受け入れられたことを示すだけで、リモートサーバーへの接続やルーティングが想定どおりであることは保証されません。
v2ray test -c config.json
xray run -test -config config.json
デスクトップ環境にcurlがインストールされている場合、以下のコマンドでこの例を明示的なプロキシ経由でテストできます。1つ目はSOCKSプロキシにドメイン名を渡すため、full:example.orgの拒否ルールの確認に適しています。2つ目はHTTP入口を使って別の例示ドメインにアクセスし、directで接続します。どちらもコアが正常に起動し、ポートがこの例と一致していることを確認してから実行してください。
curl --proxy socks5h://127.0.0.1:10808 --connect-timeout 10 https://example.org/
curl --proxy http://127.0.0.1:10809 --connect-timeout 10 https://example.com/
1つ目は接続失敗が想定されますが、エラー表示だけでは拒否ルール、入口の未起動、ネットワーク障害を区別できません。2つ目が成功するかどうかも実際のネットワーク環境に左右されます。コマンドの結果とコアのログを合わせて判断し、Webページが開かなかったという理由だけで、ルールに一致したと結論づけないでください。
8. 設定を読む際によくある質問
サブスクリプションをインポートした後、その内容をそのままconfig.jsonとして保存できないのはなぜですか?
サブスクリプションは、クライアントがノードを認識・更新するためのデータであり、コアが直接読み込める完全な設定ファイルとは限りません。共有リンクやエンコードされたリストが含まれる場合があり、通常はローカルの待受入口も定義されていません。まずクライアントにインポートし、生成された実行設定を確認してください。ファイルの拡張子を変えるだけでは使えません。
SOCKSとHTTPのポートは入れ替えて使えますか?
ポート番号自体にプロトコルは紐付いていないため、設定上は変更できますが、アプリ側も合わせて変更する必要があります。HTTPプロキシのアドレスにこの記事の10808を指定しても、ポートに接続できるだけでHTTP inboundに切り替わるわけではありません。まずprotocolを確認し、次にポートとアプリ側のプロキシ種別を照合してください。
拒否ルールを設定したのに、リクエストがdirectで接続されるのはなぜですか?
次の4点を順に確認してください。アプリが本当にプロキシ入口を使っているか、コアが受け取った接続先がドメイン名かIPアドレスか、先行するルールに一致していないか、変更後の設定でコアが実行されているか。完全一致のドメインルールはサブドメインには適用されない点にも注意してください。最初からノードを変更して、ルールの問題を覆い隠さないようにしましょう。
この設定例をv2rayNGの実行設定にそのまま置き換えられますか?
そのまま置き換えるのは避けてください。Androidクライアントでは、VPN接続、DNS、アプリごとのルーティングなどの設定に応じて実行設定が生成されます。この記事で説明しているのは、ローカルSOCKS・HTTPとルーティングの基本構造のみです。変更する際はクライアントの該当機能を使い、復元可能な設定を残してください。プロキシとして完全に利用するには、有効なリモートoutboundも必要です。