V2Ray設定ファイルのJSON構造を詳しく解説:inbounds・outbounds・routingの役割
実際の構成例をもとに、inbounds、outbounds、routingの3ブロックにある項目の意味と関係を解説。設定内容を理解し、自分で微調整できるようになります。
V2RayのJSON設定は実行順に並んだスクリプトではなく、通信経路を定義する設計図です。アプリの通信はまず入站に入り、ルーティング規則がドメイン名、宛先アドレス、ポート、入站タグなどを確認して、送信先の出站を選びます。DNS、ログ、ポリシーの各ブロックは、名前解決、状況の確認、動作制御によってこの経路を支えます。設定を読むときにサーバーアドレスだけを見ていると、通信先を実際に決めるタグの関係を見落としがちです。
サブスクリプションのインポートはできるものの、生成された設定を読み取れない方に向けた内容です。全体の構造から始め、入站の待受、プロキシ・直接接続の出站、ルーティングの照合順序、DNSとの連携を確認し、設定をレビューするための項目一覧も紹介します。
まず通信経路全体を把握する:JSONの各ブロックは独立していない
V2Rayコアは設定を読み込むと、待受ポート、出站ハンドラー、ルーターを作成します。ローカルブラウザーを例にすると、ブラウザーはリクエストをローカルのSOCKSまたはHTTPプロキシポートへ渡します。入站が接続を受けて宛先を識別し、routingが上から順に規則を照合します。一致したoutboundTagがプロキシ、直接接続、または遮断用の出站を指します。一致する規則がない場合、通常はoutbounds配列の先頭にある出站へ送られるため、配列の順序にも意味があります。
以下の骨格ではサーバー認証情報を省略していますが、各ブロックをつなぐ部分は残しています。inboundのtag、routing.rules内のinboundTagとoutboundTag、そしてoutbounds内の対応するtagに注目してください。タグは設定内部で使う名前なので自由に変更できますが、参照する箇所では完全に同じ文字列を使い、大文字・小文字も統一する必要があります。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vmess",
"settings": {}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
結論:まずタグを追い、その後にプロトコルの詳細を確認
「規則を書いたのに振り分けられない」ときは、まずinboundTag、outboundTag、実際のtagが正しく対応しているかを確認し、次にドメイン名とIPの条件を確認します。通信方式のパラメーターを先に変更するより、問題を見つけやすい方法です。
inbounds:待受対象とコアへ入れる通信
inboundsは入站の配列で、各オブジェクトが1つの受信入口を表します。デスクトップのプロキシでは、SOCKS、HTTP、またはクライアントが組み合わせて管理するローカル入口が一般的です。listenは待受アドレス、portはポート、protocolは接続の解釈方法、settingsはプロトコル固有のオプションを指定します。listenが127.0.0.1の場合は同じ端末上のプログラムだけがアクセスできます。0.0.0.0に変更するとすべてのネットワークインターフェースで待ち受けるため、設定前にLANからのアクセス範囲とOSのファイアウォール規則を明確にしてください。
SOCKS入站
- tag
- socks-in
- listen
- 127.0.0.1
- port
- 10808
- protocol
- socks
- udp
- true
ブラウザー、ターミナルツール、SOCKS5に対応したアプリから明示的に接続する場合に適しています。
HTTP入站
- tag
- http-in
- listen
- 127.0.0.1
- port
- 10809
- protocol
- http
- timeout
- 300
システムのHTTPプロキシ設定を読み取るデスクトップアプリに適しています。
tagはプロトコルを変更するものではなく、routingやログから安定して参照するための名前です。1つの設定に複数の入站を定義し、それぞれに異なるポリシーを適用することもできます。たとえばsocks-inは通常プロキシを使い、http-inは内部ネットワークだけに接続させる構成です。この場合、ルーティング規則はinboundTagで2種類の接続を区別でき、送信元のアプリを推測する必要がありません。
sniffingは、接続初期のデータから宛先ドメイン名を復元するために使います。ブラウザーがドメイン名をIPアドレスへ解決してから接続すると、ルーターにはIPしか見えない場合があります。sniffingを有効にし、destOverrideを設定すると、コアがHTTPリクエストやTLSハンドシェイクからドメイン名を取得し、domain規則を照合できる可能性があります。ただし、これはDNSリゾルバーではなく、すべてのドメイン振り分け問題を自動的に解決するものでもありません。アプリが識別できない形式で通信する場合、ルーティングからはアドレスしか見えないことがあります。
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {
"timeout": 300
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
- ポートの競合:起動に失敗して待受エラーが表示された場合は、まず10808または10809が別のプロセスに使用されていないか確認してください。
- プロキシの種類:アプリで指定するSOCKS5またはHTTPの種類は、対応する入站のprotocolと一致させる必要があります。ポート番号だけを見て判断してはいけません。
- UDPの設定:SOCKS入站でUDPを処理する場合は、settings.udpをtrueに設定し、出站と通信経路が対象の通信に対応していることも確認してください。
- LAN共有:listenだけを変更せず、クライアントのLAN接続オプション、OSのファイアウォール、アクセス制御範囲も確認してください。
outbounds:プロキシ、直接接続、遮断を定義する方法
outboundsは出站の配列です。プロキシ出站は通信をリモート経路へカプセル化し、freedom出站はコアから宛先へ直接接続し、blackhole出站は一致した接続を終了させます。routingはサーバー接続情報を保持せず、outboundTagだけを返します。実際のアドレス、ポート、ユーザー情報、転送方式、安全層は対応する出站内に記述します。
VMessプロキシ出站
- tag
- proxy
- protocol
- vmess
- address
- ノードのドメイン名
- port
- 443
- network
- ws
- security
- tls
ユーザーパラメーターはsettings、転送方式と安全層はstreamSettingsに記述します。
ローカル制御用出站
- direct
- freedom
- block
- blackhole
- 参照方法
- outboundTag
- デフォルト出站
- 配列の先頭要素
プライベートアドレスは通常直接接続し、明示的に終了させる宛先はblockへ渡します。
VMessを例にすると、settings.vnextはサーバー一覧、usersはid、alterId、securityなどのユーザーパラメーターを保持します。streamSettingsにはTCPやWebSocketなどの転送方式とTLS設定を記述します。サーバー側が要求する転送方式、パス、ホスト名、ポートは一式で一致させる必要があります。networkをtcpからwsに変更するだけで、pathとサーバー側の入口を合わせなければ、互換性のある通信経路にはなりません。
{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "server.example",
"port": 443,
"users": [
{
"id": "サブスクリプションで提供されたユーザー識別子",
"alterId": 0,
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"wsSettings": {
"path": "/gateway"
},
"tlsSettings": {
"serverName": "server.example"
}
}
}
VLESSはXrayコアの設定でよく使われます。外側にはtag、protocol、settings、streamSettingsが記述されますが、flowやRealityなどの項目は対応するコアと通信経路の機能に依存するため、任意のV2Ray設定へ機械的にコピーすることはできません。v2rayNで使用するコアはクライアント設定により異なり、v2rayNGはXrayコア、v2flyNGはv2flyコアを使用します。サブスクリプションから生成された内容を読むときは、まず現在のコアを確認し、そのコアが対応する項目の範囲を調べてください。
- まずoutbounds内のプロキシ項目のtagが、routingで実際に参照されている名前か確認します。
- 次にaddress、port、ユーザー情報の項目を確認し、ローカルの待受ポートをリモートポートと取り違えないようにします。
- 続いてnetwork、security、path、serverNameなど、転送層の項目が一式で対応しているか確認します。
- 最後にログのハンドシェイク、タイムアウト、接続拒否に関する情報を確認し、パラメーターを無作為に次々と変更するのは避けます。
結論:接続エラーは層ごとに確認する
ローカルポートへ接続できない場合はinbound、リモートでタイムアウトする場合はoutboundのアドレスとネットワーク、特定のドメインだけ出口を誤る場合はroutingを確認します。層ごとに切り分ければ、一度に複数の変数を変更せずに済みます。
routing:照合条件、規則の順序、デフォルト出站
routing.rulesは順序を持つ規則の配列です。typeにはfieldを使うことが多く、条件にはdomain、ip、port、network、inboundTag、protocolなどを指定できます。1つの規則に異なる種類の条件を複数記述した場合は、通常すべてを満たす必要があります。同じ項目に複数の値を指定した場合は候補集合として扱われます。規則は宣言順に確認され、最初に一致した規則がoutboundTagを決めるため、後続の規則で上書きされることはありません。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["domain:intranet.example"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:category-ads-all"],
"outboundTag": "block"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
この規則群では、まずプライベートアドレス、次に指定した内部ドメインを直接接続し、その後に対象を終了させ、最後にtcp,udpをプロキシへ送るフォールバックを置いています。フォールバックのプロキシを先頭に置くと、ほとんどの接続を先に捕捉してしまい、後続の直接接続・遮断規則が実行されません。振り分け設定を確認するときは、「この規則があるか」だけでなく、「前にもっと広い条件がないか」も確認してください。
| 項目 | 照合対象 | 代表的な記述 | 確認ポイント |
|---|---|---|---|
| domain | 宛先ドメイン | domain:example.com | ドメイン名を取得できるか、前段の規則に捕捉されていないか |
| ip | 宛先アドレス | geoip:private | domainStrategyが名前解決を実行するか |
| port | 宛先ポート | 53または80-443 | ここはローカルの入站ポートではありません |
| network | 転送方式 | tcp,udp | 広い条件はフォールバックとして後ろに置く |
| inboundTag | 通信の入口 | socks-in | inboundsのtagと一致させる必要があります |
domainStrategyは、ルーティング段階でドメイン名とIPの条件をどのように処理するかを決めます。AsIsは元の宛先にできるだけ沿って照合し、IP規則のためにドメイン名を自動解決しません。IPIfNonMatchはまずドメイン規則を試し、一致しない場合にアドレスを解決してIP規則の照合を続けます。IPOnDemandはIPによる照合が必要になりそうな場合、より積極的に解決します。これは速度を切り替える設定ではなく、規則の意味を選ぶ設定です。geoip:privateなどのIP規則があり、入口からドメイン名が渡されることが多い場合は、IPIfNonMatchが理解しやすい出発点です。
DNSとルーティングの連携:名前解決の結果が最終的な出口とは限らない
dnsブロックでは、コアが利用する名前解決サーバー、静的hosts、問い合わせ方式を定義し、routingでは接続をどの出站へ渡すかを決めます。両者には関係がありますが、同じ処理ではありません。アプリがDNS問い合わせを独自に送信する場合、その問い合わせは通常のネットワーク通信としてコアに入ります。アプリがすでに宛先IPを指定している場合、ドメイン規則を照合できるかどうかは、sniffingの設定と、接続中に識別可能なドメイン情報があるかどうかに左右されます。
{
"dns": {
"hosts": {
"domain:internal.example": "192.168.10.20"
},
"servers": [
{
"address": "223.5.5.5",
"port": 53,
"domains": ["geosite:cn"]
},
"1.1.1.1"
],
"queryStrategy": "UseIP"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"port": 53,
"network": "udp",
"outboundTag": "proxy"
}
]
}
}
この例ではUDP 53番ポートの通信をproxyへ渡しますが、すべての名前解決方式をカバーするわけではありません。アプリがTCP 53を使うこともあれば、暗号化されたHTTPS接続で名前解決することもあります。まずリクエストがシステムのリゾルバー、アプリ自身、コアのDNSのどれから送られているかを確認し、そのうえでルーティング規則がポート、ドメイン名、特定の入站のどれを照合すべきか判断するのが確実です。DNSアドレスを1つ追加するだけでは、すべてのリクエストが同じ出口を使うとは限りません。
- ドメイン規則にまったく一致しない場合は、入站でsniffingが有効か、ログの宛先がドメイン名とIPのどちらで表示されているかを確認します。
- プライベートドメインを直接接続したいのにプロキシへ送られる場合は、明示的な内部ドメインとgeoip:privateの規則を、広いプロキシ規則より前に置きます。
- DNSを変更しても結果が変わらない場合は、関連アプリを再起動し、OSのDNSキャッシュを消去してから、対象を1つに絞ってテストします。
- 名前解決は成功するのに接続がタイムアウトする場合、DNSの処理は完了しています。次はroutingの選択とoutboundの通信経路を確認してください。
手動調整前の確認手順:変更が上書きされるのを防ぐ
クライアントは通常、サブスクリプションのノード、全体設定、ルーティング設定を実行用設定に統合します。v2rayN 7.13.xでは「設定」→「パラメーター設定」から共通設定を開き、ローカルポート、コアの種類、システムプロキシのモード、DNS関連の項目を先に記録します。ルーティングの変更はクライアントのルーティング設定で行ってください。v2rayNG 1.10.xでは「設定」からローカルプロキシ、DNS、振り分け関連の項目を確認できます。バージョンによって画面上の文言は変わる可能性がありますが、確認の順序は同じです。まず設定の出所を確認し、次に生成された結果を確認します。
- 復元可能なコピーを残す:現在のクライアント設定をエクスポートするか、変更する独立したJSONをコピーし、元のモードと適用範囲を記録します。
- JSON構文を検証する:カンマ、引用符、角括弧、波括弧を確認します。JSONでは行末コメントを使用できず、配列の最後の項目の後に余分なカンマを置くこともできません。
- タグの対応を確認する:すべてのinbound tag、outbound tag、規則からの参照を一覧にし、表記の違いがないことを確認します。
- 一度に1つの層だけ変更する:ポートの問題は入站だけ、ノードの問題は出站だけ、振り分けの問題は規則の順序と条件だけを変更します。
- 最小限のテストセットを作る:直接接続すべき対象、プロキシを通す対象、明確に遮断すべき対象を1つずつテストし、3回分の結果を記録します。
- クライアントの永続設定へ反映する:一時的な変更が有効だと確認できたら、同等の設定をv2rayN、v2rayNG、v2flyNGの正式な設定入口へ書き戻します。
JSONは起動できるのに、すべてのサイトがプロキシ経由になります。どこを疑うべきですか?
まずrouting.rulesの先頭がnetwork: tcp,udp、または広すぎるdomain条件で全接続を捕捉していないか確認します。プライベートアドレス、内部ドメイン、明示的な直接接続規則をフォールバックのプロキシ規則より前へ移し、コアを再起動してテストします。
outboundsのサーバーアドレスを変更したのに、ノードを切り替えると元に戻るのはなぜですか?
そのファイルはサブスクリプションのノードから動的に生成されている可能性があります。クライアントに保存されたノード情報を編集するか、ノード一覧から該当するサーバー項目を更新してください。実行ディレクトリの一時的なJSONを長期的な設定元にしないでください。
規則にdomainを指定したのに、ログにはIPしか表示されません。どうすればよいですか?
対応するinboundのsniffing.enabledがtrueか確認し、destOverrideに実際の通信方式が含まれているか確認します。それでもIPしか表示されない場合は、アプリが事前に名前解決しており、接続中に復元可能なドメイン名が存在しない可能性を調べます。
10808には接続できますが、10809には接続できません。ノードの故障ですか?
まずinboundsに2つのポートが同時に定義されているか、10809に対応するprotocolがhttpか確認します。ローカルポートの片方だけが失敗する場合は、通常は待受設定またはポート競合の問題であり、リモートノードが原因とは限りません。
設定にproxy、direct、blockがすべてあります。実際にどれが使われたか確認するには?
ログレベルを一時的にinfoへ設定し、あらかじめ用意したプロキシ対象、直接接続対象、遮断対象へそれぞれアクセスします。宛先アドレスとエラー結果を規則と照合してください。完了後はwarningに戻し、後日の回帰テスト用に3種類の対象を残します。
V2Ray設定を理解するうえで重要なのは、すべての項目を暗記することではありません。各接続について「どの入站から入り、どの宛先を持ち、どの規則に一致し、どの出站へ送られたか」をたどることです。inboundsは受信、outboundsは送信、routingは選択を担当し、DNSとログが名前解決と状況確認を補います。この経路に沿って確認すれば、サブスクリプションやクライアントが自動生成した設定でも、ポート競合、タグの不一致、規則の遮断、転送パラメーターの不整合をすばやく見つけられます。