サブスクリプションに触れ、コアの設定ファイルを読み始めたい方向けです。まずローカルホストだけで待ち受けるSOCKS inboundを動かし、directと拒否の2種類のoutboundで設定構造を確認します。その後、タグ参照、ルールの順序、DNSの役割を見ていきます。このサンプルにはリモートプロキシノードは含まれません。テスト後にサーバーから提供されたプロトコル情報をoutboundへ追加し、JSONの構文、ノードへの接続、ルーティングの問題を切り分けましょう。
1. 単体でテストできるconfig.jsonを用意する
ここでは、従来のV2Ray JSON設定形式を使います。この形式に対応するV2Flyコア向けです。まず v2ray version を実行して実際に使われているプログラムを確認し、続けて v2ray help を参照してください。V2FlyとXrayには共通する項目もありますが、拡張機能やコマンドライン引数は完全には一致しません。他のコア向け設定を汎用形式として流用しないでください。
以下をUTF-8形式の config.json として保存します。127.0.0.1:10808 でSOCKS接続を受け付け、example.org とそのサブドメインへの接続を拒否し、それ以外のリクエストはデフォルトで直接接続します。ここでいう「動作する」とは、入口、ルーティング、outboundが機能するという意味であり、リモートプロキシとして利用できるという意味ではありません。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-local",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": false
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "blocked",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"inboundTag": ["socks-local"],
"domain": ["domain:example.org"],
"outboundTag": "blocked"
}
]
},
"dns": {
"servers": [
"1.1.1.1",
"8.8.8.8"
]
}
}
- オブジェクトは波括弧、配列は角括弧で囲みます。
inboundsとoutboundsは項目が1つだけでも配列です。 - キー名と文字列は半角の二重引用符で囲みます。数値の
10808や真偽値のfalseは引用符で囲みません。 - 最後の項目の後にカンマは付けません。複数のツールで検証しやすいよう、このサンプルではコメントや末尾のカンマも使用していません。
- トップレベル項目の記述順はリクエストの経路に影響しません。順序が重要なのは、ルーティングルールの配列とデフォルトで使われるoutboundの位置です。
2. log:エラーの確認先を決める
log はログ出力を設定する項目で、プロキシやルーティングの機能はありません。このサンプルでは loglevel のみを設定し、ログファイルのパスは指定していません。ターミナルから手動で起動した場合は、プロセスの出力を確認してください。サービスとして起動している場合は、任意のディレクトリに既定のログファイルを探すのではなく、該当サービスのログを確認します。
| 項目または値 | 用途 | 使い方の目安 |
|---|---|---|
loglevel: warning | 警告やエラーなど、重要度の高いログを記録する | 通常の運用向け。通常の接続ではログが出ない場合があります |
loglevel: info | 実行時の情報をより詳しく出力する | 接続や設定の動作を短時間確認するときに適しています |
loglevel: debug | 詳細な診断情報を出力する | 問題を再現した後、通常のログレベルに戻します |
access / error | アクセスログとエラーログの保存先を個別に指定する | ファイルパスを指定する場合は、保存先のディレクトリが存在し、プロセスに書き込み権限があることを確認します |
起動に失敗したら、まず最初に表示された明確なエラーを確認します。構文エラーは該当する項目や位置を示すことが多く、address already in use は待ち受けポートの競合を示します。権限エラーの場合は、設定ファイルやログディレクトリの権限を確認してください。ノードのアドレスを何度変更しても、ローカルポートの競合は解決しません。
3. inbounds:アプリが接続するローカルの入口
inbounds は、コアがリクエストを受け取る方法を設定します。このサンプルの protocol: socks はアプリとローカルのコア間で使うSOCKSプロトコルであり、リモートサーバーのプロトコルではありません。ブラウザーやターミナル側でこの入口を明示的に指定する必要があります。プロセスを起動しただけでは、システムプロキシは自動設定されず、すべてのアプリの通信がコアに取り込まれるわけでもありません。
ローカルSOCKS inbound
- タグ
socks-local- 待ち受けアドレス
127.0.0.1- 待ち受けポート
10808- プロトコル
socks
ローカルからの接続のみを受け付けます。テストするアプリではHTTPプロキシではなく、SOCKSプロキシを選択してください。
デフォルトのdirect outbound
- タグ
direct- プロトコル
freedom- プロトコル設定
{}- 配列内の位置
- 1番目
どのルールにも一致しないリクエストに使用します。リモートプロキシサーバーを経由せず、接続先へ直接接続します。
listen は入口へ接続できる範囲を、port は入口のポート番号を指定します。ここではループバックアドレスを使っているため、他のLAN機器はPCのローカルIPアドレス経由で接続できません。トラブルシューティングのために安易に 0.0.0.0 へ変更し、認証なしのまま使い続けないでください。待ち受け範囲が広がります。
settings.auth が noauth の場合、ローカルSOCKS接続にユーザー名とパスワードは不要です。udp: false は、このサンプルでSOCKSのUDP転送を有効にしない設定です。この記事ではTCPリクエストだけを使って動作を確認するため、ゲーム、音声通話などのUDPアプリが使えるかどうかは判断できません。
4. outbounds:プロトコル設定とタグを分けて理解する
outbounds は、リクエストをコアから送信する方法を設定します。このサンプルの freedom は直接接続、blackhole はリクエストの拒否または破棄に使います。どちらもリモートノードではないため、サーバーアドレス、ユーザー識別情報、通信のセキュリティ設定は不要です。
- まずprotocolを確認。
settingsに指定できるプロトコル項目は、ここで決まります。SOCKS inboundの認証項目をVMess outboundにコピーしないでください。 - 次にsettingsを確認。使用するプロトコルに応じた接続パラメーターを設定します。実際のプロキシノードを追加する場合は、サーバー情報と使用中のコアのドキュメントを確認し、既定値を推測で設定しないでください。
- 最後にtagを確認。設定内で参照するための名前です。この例の
directとblockedは独自に付けたタグであり、システム予約済みのプロトコル名ではありません。 - streamSettingsを確認。必要に応じて、outboundオブジェクトに通信方式や通信のセキュリティ設定を指定します。
settingsと同じ階層に置く項目で、むやみに入れ子にしないでください。
VMessとVLESSは別のプロキシプロトコルです。protocol の値を変えるだけでは切り替えられません。VLESSを使う場合は、実際のコアのバージョンと対応範囲も確認してください。特にXray固有の通信拡張は、項目名が似ているからといって、そのままV2Flyの設定に移せるとは限りません。
まとめ:directの基準構成を保ち、実際のノードを追加する
まず 10808 の入口から直接接続できることを確認してから、プロキシoutboundを追加し、ルールから参照します。こうすれば追加後に失敗しても、入口設定を疑わずにプロトコルやサーバー側のパラメーターを優先して確認できます。
5. routing:ルールの順序に沿ってリクエストをoutboundへ振り分ける
リクエストがコアに入ると、ルーティングモジュールは接続先のドメインやIPアドレス、ポート、inboundタグなどの条件に基づいてoutboundを選択します。サンプルの処理の流れは次のとおりです。仮想NICは使用せず、システムプロキシも自動設定しません。
このサンプルでは、リクエストの送信元が socks-local で、接続先ドメインが domain:example.org に一致する場合、blocked に送ります。同じルール内の2つの条件は両方とも一致する必要があります。domain 配列に複数のドメインを指定した場合は、そのうち1つに一致すればドメイン条件を満たします。
| 設定項目 | 参照先または意味 | よくある間違い |
|---|---|---|
inboundTag | inboundオブジェクトの tag と照合します | プロトコル名の socks をinboundタグとして指定する |
outboundTag | outboundオブジェクトの tag を指定します | 存在しないタグを指定する、または大文字と小文字を間違える |
domain:example.org | ドメインとそのサブドメインに一致します | 完全一致するホスト名だけが対象だと思い込む |
full:example.org | 完全一致するドメインだけに一致します | すべてのサブドメインも対象になると思い込む |
rules 配列 | 上から順に確認し、一致したら対応するoutboundを選びます | 広い範囲に適用されるルールを、個別ルールより前に置く |
どのルールにも一致しない場合は、outbounds の1番目が使われます。この記事では1番目が direct のため、通常のリクエストは直接接続します。プロキシoutboundを先頭に移すと、ルールに一致しないリクエストの動作も変わります。「どのサイトも同じ出口になる」場合は、ルールだけでなく配列の先頭項目も確認してください。
domainStrategy: AsIs は、現在の接続先情報を使ってルーティング時に照合し、IPルールとの照合のためにドメインを積極的に名前解決しない設定です。アプリからSOCKSへIPアドレスが渡された場合、このドメインルールだけでは元のドメイン名を復元できません。この例ではスニッフィングを設定していないため、テスト時はアプリからドメイン名をSOCKS入口へ渡す必要があります。
6. dns:DNSサーバーの設定はシステムDNSの制御とは別
トップレベルの dns は、コア内蔵のDNSモジュールを設定します。このサンプルでは 1.1.1.1 と 8.8.8.8 の2つのサーバーを指定していますが、この設定を追加してもOSのDNSは変更されず、すべてのアプリのDNS問い合わせが自動的にコアへ送られるわけでもありません。
- アプリが先に名前解決する:アプリが接続先のIPアドレスを取得してから、そのIPをSOCKSへ渡します。この場合、コアから元のドメイン名が見えず、ドメインによる振り分けが一致しないことがあります。
- アプリがドメイン名を渡す:アプリがSOCKSの接続先としてドメイン名を渡すため、ルーティングモジュールはドメイン条件を直接照合できます。
- ルーティングが名前解決を実行する:名前解決が必要なルーティング方針を使う場合、IPルールとの照合を続けるためにルーティングモジュールが内蔵DNSを呼び出すことがあります。
- outboundで名前解決する:direct outboundの名前解決は、そのoutbound自身の設定にも左右されます。既定の
AsIsを使用している場合、トップレベルで指定したDNSサーバーが必ず使われるとは限りません。
このため、この例のDNS設定は主に構造を示すものであり、すべてのテストで実際に呼び出されるとは限りません。routingの domainStrategy とdirect outboundの settings.domainStrategy は異なる階層の設定です。前者はルールの照合方法、後者はdirect接続での接続先アドレスの扱いに影響します。同じ名前だからといって、どちらか一方を変えればすべての名前解決経路が変わるわけではありません。
まとめ:まず、どこで名前解決しているか確認する
ドメインルールに一致しない場合は、まず socks5h://127.0.0.1:10808 で再試行し、curlから接続先のドメイン名をSOCKSへ渡します。リクエストの渡し方を確認してから、DNSやルーティング方針を変更するか判断してください。
7. 設定のテストと2種類のリクエストによる確認
test と run サブコマンドが使えるV2Flyのバージョンでは、設定ファイルのあるディレクトリで次のコマンドを実行できます。Windowsでカレントディレクトリから実行する場合は、プログラム名を .\v2ray.exe とします。他のバージョンでは、ローカルのヘルプで引数を確認してください。起動前に、デスクトップクライアントが 10808 を使用していないことを確認します。
v2ray version
v2ray help
v2ray test -c config.json
v2ray run -c config.json
test の成功は、現在のコアが設定を受け付けたことを示すだけで、ネットワークに接続できることを保証しません。コアを起動したまま、別のターミナルで次のコマンドを実行してください。Windowsでは curl.exe を使うと、コマンド名がターミナルのエイリアスに置き換わるのを防げます。
curl --connect-timeout 10 --max-time 20 --proxy socks5h://127.0.0.1:10808 -I https://example.com/
curl --connect-timeout 10 --max-time 20 --proxy socks5h://127.0.0.1:10808 -I https://example.org/
- 1つ目のテストでは直接接続を確認します。現在のネットワークから接続先にアクセスできる場合、最初のコマンドでHTTPレスポンスヘッダーが返ります。ステータスコードは接続先サイトによって異なり、必ず
200になるわけではありません。 - 2つ目のテストでは接続拒否を確認します。2つ目のリクエストでは、正常なHTTPSレスポンスが返らないはずです。エラーの内容はcurlやコアのバージョンで異なるため、特定のエラーメッセージだけで成否を判断しないでください。
- タイムアウトも確認します。コマンドでは接続タイムアウトを10秒、全体のタイムアウトを20秒に設定し、長時間の待機を避けています。これは応答速度の測定でも、性能の評価でもありません。
- 設定を1項目ずつ変更します。まず拒否ルールの
outboundTagをdirectに変更し、再テストしてからコアを再起動します。2つ目のリクエストが再び応答すれば、タグ参照とルールが処理に反映されていることを確認できます。
ディスク上のJSONを変更しても、実行中のプロセスが自動的に読み直すとは限りません。この記事の手動実行手順では、旧プロセスを停止し、設定をテストしてから再起動してください。v2rayNでサブスクリプションのノードを使う場合、クライアントが実行用設定を再生成することがあります。クライアントが生成したファイルと、自分で管理するカスタム設定を区別し、編集前にコピーを保存してください。
8. よくある設定トラブルと対処法
設定テストは成功したのに、ブラウザーが入口を経由しないのはなぜ?
設定テストではシステムプロキシは設定されません。まずこの記事のcurlコマンドで入口が動作することを確認し、次にブラウザーで選択しているプロキシの種類とポートを確認してください。この設定の 10808 はSOCKSポートです。HTTPプロキシ専用の設定欄には指定できません。
blockedを設定したのに、サイトへアクセスできるのはなぜ?
まずリクエストが本当に 127.0.0.1:10808 を経由していることを確認し、次に socks5h でドメイン名を渡します。その後、inboundTag が socks-local か、より前に一致するルールがないかを確認してください。設定変更後はプロセスを再起動してテストします。
起動時に10808が使用中と表示されたら、どこを変更すればよい?
古いコアのプロセスを終了するか、inboundの port を未使用の 10818 に変更し、テストコマンドのポートも 10818 に合わせます。アプリ側のポートだけを変えて、コアの待ち受けポートをそのままにしないでください。両方のポート番号を一致させる必要があります。
サブスクリプションURLをそのままoutboundsに設定できる?
できません。サブスクリプションはクライアントがノード情報を取得するためのもので、outbounds にはコアが認識できる構造化オブジェクトが必要です。まずv2rayNにサブスクリプションを登録し、現在のノード用に生成された設定を確認してください。トラブルシューティング用の設定抜粋を共有する前に、サブスクリプションURL、サーバー認証情報などの機密情報を削除します。
最終確認は、JSONを解析できる、コアが起動する、inboundに接続できる、ルールに一致する、outboundから接続先へ到達できる、の順に行います。一度に変更するのは1つの階層だけにし、動作する基準設定を残してください。後からVMess、VLESSや複雑なDNS振り分けを追加する場合も、設定全体を入れ替えて試行錯誤するのではなく、問題のある項目を絞り込めます。
クライアントとプラットフォームの選択
端末のOSに合ったインストーラーを選びます。デスクトップではv2rayN、Androidでは必要なコアに応じてv2rayNGまたはv2flyNGを使用できます。まずチュートリアルに沿って基本接続を設定し、その後この記事に戻って設定構造とルールの参照先を確認してください。