サブスクリプションをインポートしたことがあり、コアの実行設定を理解したい方に向けた解説です。アプリの入口、接続先、ルーティングの選択を整理したうえで、ローカル待ち受け・直接接続・通信遮断だけを使った完全な設定例で項目間の関係を確認します。読み終えると、ポート競合、タグの入力ミス、ルール順序の不備、DNS設定が反映されない原因を特定しやすくなります。
まず押さえる基本:config.jsonはコアの設定ファイルで、サブスクリプション一覧ではない
v2rayNはデスクトップクライアント、V2RayとXrayは接続を処理するコアです。クライアントはサブスクリプション、ノード、画面設定を保存し、選択したコアに応じて実行設定を生成します。そのため、サブスクリプション内のVMessやVLESSの共有リンクは、完全なconfig.jsonではありません。通常はリモート接続の情報のみが記載され、ローカルの入口、ログ、DNS、ルーティングルールなどは含まれていません。
この記事では、V2Rayの従来型JSON設定を使い、V2RayとXrayでよく見られる項目間の関係を説明します。V2Ray v5には別形式の設定もあるため、拡張子だけで形式を判断したり、異なる形式の項目を混在させたりしないでください。プロトコルやトランスポートの項目は、実際に使用するコアのバージョンに合わせる必要があります。
問題を調べるときは、この流れに沿って確認します。Webリクエストは、まず何らかのinboundに入らなければルーティングの対象になりません。ルーティングで指定するのはoutboundのタグであり、サブスクリプションのグループ名ではありません。DNSは名前解決や一部のルーティング判定を支えますが、すべての通信が必ず通る「プロキシ出口」ではありません。
- まず実行中のコアを確認:クライアントのウィンドウタイトルだけで判断せず、現在XrayとV2Rayのどちらを使用しているか確認します。
- 次に実際の設定ファイルを確認:ディスク上で同名ファイルを探すより、起動ログに表示された設定ファイルのパスを確認するほうが確実です。ファイル名は任意で、
config.jsonはよく使われる名前にすぎません。 - 元の設定を残す:クライアントが自動生成したファイルは、ノード切り替え、サブスクリプション更新、再起動などで上書きされる場合があります。継続的に変更する場合は、クライアントが対応する設定項目やカスタム設定の入口を利用してください。
log:確認できる情報を把握してから接続設定を調整
logはトップレベルにあり、ログ出力を制御します。トラブルの調査中はまずinfoを使い、解決後は通常warningに戻します。最初からdebugを有効にすると詳細なログが大量に出力され、単純なポート競合の情報が埋もれるおそれがあります。
{
"log": {
"loglevel": "info"
}
}
これは項目の抜粋であり、実行に必要な設定一式ではありません。一般的なログレベルはdebug、info、warning、error、noneです。ここではログファイルのパスを指定せず、まず端末やクライアントのログ画面で起動結果を確認できるようにしています。accessやerrorの出力先を設定する場合は、対象ディレクトリが存在し、実行ユーザーに書き込み権限があることを確認してください。
address already in use:リモートノードを変更する前に、まずローカルの待ち受けポートを確認します。permission denied:ログディレクトリ、設定ファイル、待ち受けポートのアクセス権を確認します。- outboundタグが見つからない場合:
routing.rules[].outboundTagとoutbounds[].tagの綴りが一致しているか確認します。 - ログを共有する前に、サブスクリプションURL、ユーザー識別情報、サーバーアドレス、公開したくないアクセス先ドメインを削除してください。
inbounds:アプリはどのアドレス・ポートから接続するか
inboundsは配列で、1つの設定でSOCKSとHTTPのプロキシリクエストを同時に受け付けられます。listenは待ち受けアドレス、portはローカルポート、protocolはアプリが接続に使うプロキシプロトコルを指定します。いずれもリモートノードのアドレスやポートではありません。
ここで示すポートは、この記事で明示的に指定した値であり、すべてのクライアントバージョンのデフォルト値ではありません。v2rayNがすでにいずれかのポートを使用している場合、テスト用コアは同じポートを再度バインドできません。使用中のプロセスを停止するか、設定とテストコマンドのポートを両方変更してください。片方だけを変更しないようにします。
SOCKS inbound
- tag
- local-socks
- listen
- 127.0.0.1
- port
- 10808
- protocol
- socks
- settings
- authはnoauth、udpはfalse
この例ではTCPのみをテストします。UDP転送を無効にしても、通常のHTTPS接続には影響しません。
HTTP inbound
- tag
- local-http
- listen
- 127.0.0.1
- port
- 10809
- protocol
- http
- settings
- 空のオブジェクト。inboundのデフォルト設定を使用
HTTPSサイトでは通常、HTTPプロキシのCONNECTメソッドを使ってトンネルを確立します。
ローカルアプリのHTTPプロキシには127.0.0.1:10809、SOCKS5プロキシには127.0.0.1:10808を設定します。ポート番号だけを見て、異なるプロトコルを入れ替えてはいけません。待ち受けアドレスを0.0.0.0にすると、接続可能な範囲が広がります。アクセス制御やファイアウォールの制限がない状態で、認証なしのプロキシを他の端末から到達可能なネットワークに公開しないでください。
outbounds:出口タグと接続プロトコルは別のもの
outboundsも配列です。tagは設定内で参照する名前で、実際の送信方式はprotocolで決まります。タグをproxyと名付けても、自動的にプロキシ機能が有効になるわけではありません。プロトコルがfreedomなら、接続は直接行われます。
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
]
}
この2つのoutboundにはリモートアカウントは不要です。freedomはローカルのネットワークを使って接続先に直接接続し、blackholeは該当する通信を破棄します。この記事の設定にはロードバランサーなどの追加設定がないため、どのルールにも一致しない通信には配列の先頭にあるoutboundが使われます。したがって、デフォルトの出口はdirectです。
- VMess outbound:サーバーアドレス、ポート、ユーザー識別情報、対応するトランスポートとセキュリティ設定が必要です。UUIDだけでは設定できません。
- VLESS outbound:サーバーの認証情報とトランスポートのセキュリティ設定を正しく組み合わせる必要があります。特定の拡張機能を利用できるかどうかは、選択したコアにも左右されます。
- サブスクリプションの設定値:有効なサブスクリプションまたはサーバー設定から取得してください。HTTP inboundの
10809をリモートサーバーのポートとして流用してはいけません。 - 配列の順序:遮断用outboundを先頭に置くと、どのルールにも一致しないリクエストがすべて遮断される場合があります。
結論:出口を変更する前に、タグが指すプロトコルを確認
「ルールに一致したのにローカル回線で接続される」場合は、まず該当するoutboundのprotocolを確認します。freedomなら出口の設定を修正してください。ドメインの一致条件を何度も変更しても解決しません。
routing:上から順に照合し、タグの参照先を確認
routing.rulesは上から順に評価され、最初に一致したルールで通信先が決まります。よく使われる条件は、ドメインのdomain、宛先IPのip、ポートのport、inboundタグのinboundTagです。1つのルールに異なる種類の条件を指定した場合、通常はすべてを満たす必要があります。同じドメイン一覧に含まれる複数の項目は、いずれかが一致すれば候補になります。
{
"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"],
"outboundTag": "direct"
}
]
}
}
full:blocked.exampleはこの完全一致のドメインだけを対象にします。domain:example.orgは該当ドメインとそのサブドメインに一致します。この記事では予約済みのサンプルドメインを使って遮断をテストし、実在サイトへの依存を避けています。ルールのoutboundTagは、定義済みのblockまたはdirectに対応させ、英字の大文字・小文字も一致させてください。
| domainStrategy | 照合の動作 | 設定を読む際のポイント |
|---|---|---|
| AsIs | リクエストに含まれる宛先情報を使って照合し、ルーティングのためにドメインを自動で名前解決しない | ドメイン宛てのリクエストが、名前解決後のIPルールに自動で一致するとは限らない |
| IPIfNonMatch | ドメインがルールに一致しない場合、名前解決後にIPルールとの照合を試みる | DNSの結果と、名前解決によって追加される可能性がある待ち時間を確認 |
| IPOnDemand | ルーティングの照合にIP情報が必要な場合に名前解決する | IPルールの配置によって、早い段階で名前解決が行われる場合がある |
この例ではAsIsを使うため、192.168.1.1への直接リクエストはプライベートIPルールに一致します。一方、プライベートアドレスに解決されるドメインへのアクセスは、このルールだけを理由にルーティングで名前解決されることはありません。直接接続の確立時にドメインの名前解決が必要になる場合はありますが、これはoutboundの接続処理であり、ルーティングの判定方式とは別のものです。
dns:組み込みリゾルバーがすべてのDNSリクエストを処理するわけではない
トップレベルのdnsで組み込みリゾルバーを設定します。ルーティングでドメインに対応するIPが必要な場合や、outboundの設定で組み込みの名前解決結果を使う場合に、該当する処理で利用されます。dns.serversを書くだけでは、ブラウザーの暗号化DNSやシステム全体の名前解決を自動で引き受けることはありません。また、ローカルのDNS待ち受けポートが新たに作られるわけでもありません。
{
"dns": {
"servers": ["localhost"]
}
}
ここでのlocalhostは、システムの名前解決機能を呼び出す特殊な値です。127.0.0.1:53でDNSサーバーを稼働させる必要があるという意味ではありません。この記事では例を簡潔にするために使用していますが、DNSを分離する方法として使うものではありません。特定の出口経由で名前解決したい場合は、コアのDNS動作、関連するルーティング、outboundのドメイン解決方式をあわせて確認してください。
- まずアプリから何が渡されるか確認:HTTPプロキシのCONNECTリクエストには通常ドメイン名が含まれます。SOCKSリクエストにはドメイン名が含まれる場合と、アプリが解決済みのIPが含まれる場合があります。
- 次にルーティングで名前解決するか確認:
routing.domainStrategyで、ルーティング時にドメインをIPに変換するタイミングを指定します。 - 最後にoutboundの接続方法を確認:
freedomの名前解決方式はoutbound側の設定です。ルーティング側にある同名の項目とは別の階層に属します。項目を誤った階層にコピーしないでください。
たとえばcurlでsocks5://127.0.0.1:10808を使うと、通常はcurlがローカルで宛先を名前解決します。socks5h://127.0.0.1:10808では、ドメイン名がSOCKSプロキシ側に渡されます。ドメイン別ルーティングをテストするときは、後者を使うのがおすすめです。前者ではコアにIPアドレスしか渡らず、ドメインルールが照合されない場合があります。
完全な設定例:直接接続と遮断で5つのトップレベル項目を確認
以下は従来型JSON形式の完全な設定例です。ローカル向けのHTTP・SOCKS入口と、直接接続・遮断のoutboundのみを設定しています。リモートプロキシノードは含まれておらず、ローカル環境から直接接続できないWebサイトにアクセスできるようになるわけではありません。まず設定の構造、ポートの待ち受け、ルールの参照関係を確認し、その後で実際のノード情報を追加するための例です。
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": false
}
},
{
"tag": "local-http",
"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: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"
],
"outboundTag": "direct"
}
]
},
"dns": {
"servers": ["localhost"]
}
}
JSONオブジェクトのトップレベル項目の記述順は、処理順には影響しません。この記事では読みやすさを考慮して並べています。動作を左右するのは、ルール配列の順序、デフォルトoutboundの位置、項目間の参照関係です。UTF-8で保存し、キー名と文字列には半角の二重引用符を使います。最後の項目の後にカンマを付けず、説明用のコメントをファイルにコピーしないでください。
portは数値なので、10808と記述します。udpは真偽値なので、falseと記述します。文字列の"false"ではありません。inbounds、outbounds、rulesは配列です。単一のオブジェクトに変更しないでください。tagは内部識別子です。名前を変更する場合は、対応するoutboundTagの参照も忘れずに変更してください。
検証の手順:構文・起動・inbound・ルーティングを分けて確認
完全な設定例を、現在のディレクトリにあるconfig.jsonとして保存します。以下ではLinuxの端末を例に、まずJSONの構文を確認し、次に実際のコアで設定を検証します。構文チェックに通っても、JSONを解析できることがわかるだけで、プロトコル項目、ファイル依存関係、ネットワーク接続が正しいとは限りません。
python3 -m json.tool config.json > /dev/null
# Xrayを使う場合に実行
xray run -test -config config.json
# このコマンド形式に対応したV2Ray v5を使う場合に実行
v2ray test -c config.json
2つのコア検証コマンドは、実際に使用しているコアに応じてどちらか一方を実行してください。テストのために両方のサービスを同時に起動しないでください。旧バージョンでは実行ファイルのサブコマンドが異なる場合があります。まずxray helpまたはv2ray helpで確認してください。検証に成功したら、そのバージョンに対応した実行コマンドで同じファイルを読み込みます。たとえばXrayではxray run -config config.jsonを使用します。
# 別の端末でTCPの待ち受けを確認
ss -lntp 'sport = :10808 or sport = :10809'
# HTTP inbound経由で直接接続のoutboundをテスト
curl --noproxy "" --proxy http://127.0.0.1:10809 --max-time 15 -I https://example.org/
# ドメイン名をSOCKS inboundに渡して遮断ルールをテスト
curl --noproxy "" --proxy socks5h://127.0.0.1:10808 --max-time 5 -I https://blocked.example/
1つ目のcurlが成功するかどうかは、ローカルネットワーク、システムの名前解決、接続先サイトに左右されます。プロキシノードの速度テストではありません。2つ目のリクエストは、宛先ドメインがblockに一致するため、接続先からHTTPレスポンスを取得できない想定です。具体的なエラー内容はコアや接続段階によって異なるため、ログも確認してください。一度タイムアウトしただけで、ルーティングが機能したと判断しないでください。
結論:一度に確認するのは1つの段階だけ
まず待ち受けが存在することを確認し、次に明示的なプロキシ指定でリクエストがコアに届くことを確かめ、最後にログで出口を確認します。これにより「アプリがプロキシを使っていない」問題と「プロキシに届いた後のルールが正しくない」問題を切り分けられます。ポート、DNS、ノードを同時に変更して、新たな混乱を招くことも避けられます。
- 接続が拒否される:プロセスが起動しているか、待ち受けアドレスとポートが一致しているか確認します。まずはリモートノードの設定を調べる必要はありません。
- inboundにリクエストが届くが、出口が違う:ルールの順序、リクエストに含まれるのがドメインかIPか、デフォルトoutboundの位置を確認します。
- ルールは正しいのに接続できない:次に名前解決の結果、宛先への到達性、リモート認証、トランスポートのセキュリティ設定を確認します。
- 再起動後に変更が消える:手動で管理している設定を変更したのか、クライアントが生成した一時的な実行ファイルを変更したのか確認します。クライアントを利用している場合は、使い方ガイドで該当する設定画面を確認してください。
この構造を理解すると、v2rayNが生成した設定も読み解きやすくなります。まずinboundのポート、次にデフォルトoutbound、続いてルール、最後にDNSが実際に使われる箇所を確認します。プラットフォームへのインストールやコアの準備手順を確認する場合は、総合ドキュメントもご覧ください。最初からすべての高度な項目を1つのファイルに詰め込む必要はありません。