この記事の概要

ノードをインポート済みで、コアの設定を理解したい方向けです。まずリクエストの流れに沿って4つのトップレベル項目を確認し、VMess + WebSocket + TLSの例を読み解きます。最後にタグ参照、ルールの順序、DNSを確認します。読み終えると、接続に失敗するたびにJSON全体を書き直すのではなく、inbounds、ノード設定、routingのどこを見直すべきか判断できます。

1. 設定ファイルとクライアント設定の違い

v2rayNとv2rayNGはクライアントで、ノード管理やサブスクリプション更新、コアが実行する設定の生成を担います。v2rayNGはXrayコア、v2flyNGはv2flyコアを使用します。v2rayNでは複数のコアを管理できますが、この記事で扱うのは従来のV2Ray/XrayのJSON設定形式です。すべてのコアに共通するフィールド一覧ではありません。

ここでいうconfig.jsonは、コアが実際に読み込む設定ファイルです。ウィンドウ位置やサブスクリプションのグループなどを保存するクライアント設定ファイルではありません。ファイル名も固定とは限りません。起動コマンドで指定されたファイルか、またinboundsやoutboundsなどの項目が含まれているかで判断します。クライアントがノードを更新したりコアを再起動したりすると、自動生成されたファイルが上書きされる場合があります。

アプリのリクエストローカルのinboundルール判定outboundの選択接続先サービス

2. JSON全体の例:2つのinboundsと3つのoutbounds

以下は構造を読み解くための完全な例です。node.example.invalidは実在しないドメインで、UUIDもサンプル値のため、実際のノードには接続できません。従来のVMessで使われるvnext構造を使用しています。実際のアドレス、ポート、UUID、伝送パス、TLS名はサーバーの設定に合わせてください。

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"],
        "routeOnly": true
      }
    },
    {
      "tag": "http-in",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "node.example.invalid",
            "port": 443,
            "users": [
              {
                "id": "00000000-0000-4000-8000-000000000001",
                "alterId": 0,
                "security": "auto"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "tlsSettings": {
          "serverName": "node.example.invalid"
        },
        "wsSettings": {
          "path": "/ws",
          "headers": {
            "Host": "node.example.invalid"
          }
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": ["full:blocked.example.invalid"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["full:localhost"],
        "outboundTag": "direct"
      }
    ]
  },
  "dns": {
    "servers": ["223.5.5.5"]
  }
}
10808
サンプルのSOCKS inboundポート
10809
サンプルのHTTP inboundポート
443
サンプルのリモートTLSポート

ポート番号はこの記事の例で使用する値で、すべてのバージョンに共通する既定値ではありません。JSONのポート番号は数値、trueは真偽値です。どちらも引用符で囲んだ文字列にしてはいけません。最後の項目の後ろにカンマを付けることもできません。検証しやすいよう、例ではコメントを使っていません。

3. inbounds:待ち受けアドレス、プロトコル、スニッフィング

listenは接続を受け付けるローカルアドレス、portはポート番号、protocolはアプリが接続に使うプロキシプロトコルを指定します。SOCKSクライアントからHTTP inboundへ直接接続することはできません。ポートに接続できても、プロトコルが正しいとは限りません。アプリに手動設定する場合、この例ではSOCKS5なら127.0.0.1:10808、HTTPプロキシなら127.0.0.1:10809を指定します。

SOCKS inbound

tag
socks-in
listen
127.0.0.1
port
10808
protocol
socks
settings.udp
true

ローカルホストのみで待ち受けます。UDPを使うには、アプリ側でSOCKS5 UDP転送を利用する必要もあります。

HTTP inbound

tag
http-in
listen
127.0.0.1
port
10809
protocol
http
settings
空のオブジェクト

HTTPプロキシ対応アプリ向けです。HTTPSリクエストでは通常CONNECTトンネルを使用します。

127.0.0.1を指定すると、ローカルホストからの接続だけを受け付けます。0.0.0.0に変更すると、すべてのIPv4ネットワークインターフェースで待ち受けます。サンプルのSOCKS inboundではauth: "noauth"も指定しているため、そのままネットワークに公開しないでください。プロキシを共有する場合は、認証、ファイアウォール、接続を許可する送信元をあわせて確認してください。

sniffingを使うと、HTTP HostやTLSハンドシェイクのサーバー名から接続先ドメインを特定し、ドメインルールの判定に利用できます。routeOnly: trueは、スニッフィングで取得した名前をルーティング判定だけに使い、元の接続先を置き換えない設定です。HTTPSを復号する機能ではなく、すべての通信でドメインを取得できるわけでもありません。この例ではSOCKS inboundだけでスニッフィングを有効にしています。

4. outbounds:ノード認証と伝送方式を分けて確認

プロキシoutboundのprotocol: "vmess"はノードのプロトコルを表します。settings.vnextにサーバー一覧、usersに認証情報を設定します。idはユーザーUUIDです。alterId: 0は現在のVMessで一般的な設定です。古い解説にある0以外の値を試すのは避けてください。users[].security: "auto"はVMessの暗号化オプションで、TLSの有効・無効とは別の設定です。

項目例の値役割
vnext[].addressnode.example.invalidコアが接続するノードのアドレス
vnext[].port443サーバーの待ち受けポート。ローカルのinboundポートではありません。
streamSettings.networkwsWebSocketで通信
streamSettings.securitytls伝送レイヤーでTLSを有効化
tlsSettings.serverNamenode.example.invalidTLSのサーバー名。通常はSNIと証明書名の検証に使用
wsSettings.path/wsWebSocketリクエストのパス。サーバー側の設定と一致させる必要があります。
wsSettings.headers.Hostnode.example.invalidWebSocketハンドシェイクで使用するHTTP Host

この例では変数を減らすため、アドレス、SNI、Hostに同じ値を使っています。実際の設定では、3つが異なる場合もあります。IPアドレスに接続するときも、TLSでドメイン名の指定が必要なことがあります。パスも完全に一致させてください。/wsと/proxyは、入れ替え可能な飾りの文字列ではありません。

freedomは直接接続するoutbound、blackholeは通信をブロックするoutboundです。direct、block、proxyはこの記事で付けたタグ名なので変更できますが、すべてのoutboundTag参照もあわせて変更してください。VLESSのユーザー項目はVMessと完全には同じではありません。protocolをvlessに変えるだけでは移行できません。

確認ポイント:接続できないときは2段階で確認

まずアドレス、ポート、UUIDを照合し、次にnetwork、TLS名、Host、pathを確認します。証明書検証を無効にしてserverNameの誤りを回避しないでください。設定を間違えたまま検証を省略しても、ノードが正しくなるわけではありません。

5. routing:ルールの順序と既定のoutbound

rulesは配列の先頭から順に評価され、最初に一致したルールでoutboundが決まります。この例では、まずサンプルのドメインをブロックし、次にプライベートアドレスとlocalhostを直接接続します。どのルールにも一致しない場合、従来のV2Ray/Xray設定ではoutbounds配列の先頭にあるoutboundが使われます。そのため、この例では既定でproxyを使用します。タグ名が「proxy」かどうかは関係ありません。

  1. タグを確認:outboundTag: "direct"に対応するtag: "direct"のoutboundが必要です。
  2. 順序を確認:具体的な例外ルールは、通常、範囲の広いルールより前に置きます。末尾に置くフォールバックルールを先に置くと、後続のルールに到達できません。
  3. 条件を確認:1つのルール内にある異なるフィールドは、通常すべて満たす必要があります。同じフィールドの配列にある複数の候補は、通常いずれかに一致すれば対象になります。
  4. データを確認:geoip:privateを使うにはGeoIPデータファイルが利用できる必要があります。geositeの項目を使う場合も、対応するドメインデータを確認してください。

ドメインのマッチ方法には違いがあります。full:example.comは完全一致、domain:example.comはそのドメインとサブドメインに一致します。接頭辞のない文字列は通常キーワードとして扱われ、想定以上に広い範囲に一致することがあります。対象を絞りたい場合は、マッチ範囲を明示してください。

domainStrategy名前解決のタイミング確認ポイント
AsIsルーティング判定では、ドメインを自動的にIPアドレスへ名前解決しません。ドメイン宛てのリクエストがIPルールに自動一致するとは限りません。
IPIfNonMatchドメインルールに一致しない場合、名前解決してからIPルールを試します。名前解決の結果によって、最終的なoutboundが変わる場合があります。
IPOnDemand判定にIP条件が必要になった時点で名前解決します。名前解決の負荷とDNSの応答内容を確認してください。

この例では、判定の流れをシンプルにするためAsIsを指定しています。接続先がもともとプライベートIPなら、プライベートアドレスのルールに一致します。一方、名前解決の結果がプライベートIPになるドメインが、そのルールに一致するとは限りません。LAN内のドメインには、明示的な直接接続ルールを追加するか、名前解決の挙動を理解したうえで方針を調整してください。

6. dns:組み込みリゾルバーとシステムDNSの違い

dns.serversでは、コアの組み込みリゾルバーが使用するサーバーを指定します。この例では構造を説明するため、上流サーバーを223.5.5.5だけにしています。DNSの振り分けを完全に設定した例ではありません。アプリがリクエスト前に独自に名前解決することもあります。システム、ブラウザー、コアそれぞれの名前解決経路を個別に確認してください。

したがって、dnsを設定しただけでは、すべての名前解決が想定どおりプロキシを経由するとは限りません。アプリが独自に名前解決していないか、routingのdomainStrategy、outboundの名前解決方針、DNSクエリ自体の到達性を確認してください。特に、ドメイン名で接続するノードを使う場合は、ノードへの接続がまだ確立していないのに、そのノードに依存してノードのドメイン名を解決する構成にならないよう注意してください。

7. エクスポートした設定からトラブルシューティングまで:変更は1つずつ

トラブルシューティングでは、まず動作する設定を1つ保存し、コアのバージョンと実際に読み込まれているファイルを確認します。v2rayNの「設定」→「パラメータ設定」では、ローカルの待ち受けに関する項目を確認・変更できます。画面のタブや項目名はバージョンによって異なります。クライアント画面のノード設定やルーティング設定と、実行時のJSONが対応しているか確認してください。クライアントが再生成したファイルだけを見ても不十分です。

  1. 構文を確認:ローカルのエディターで括弧、カンマ、値の型を確認します。UUID、サブスクリプションURL、ノード情報を公開オンラインフォーマッターに送信しないでください。
  2. コアとの互換性を確認:設定を読み込んでいるのがV2RayかXrayかを確認します。新しいフィールドや伝送方式は、使用中のコアが対応している範囲に合わせてください。
  3. 入口を確認:プロセスが実際に設定されたポートで待ち受けているか確認します。address already in useが表示された場合は、まずポートの競合を解消してください。ノードのUUIDを先に変更する必要はありません。
  4. outboundを確認:ルールの条件を一時的に減らし、アドレス、認証情報、伝送方式を確認します。タイムアウト、認証失敗、TLSエラーは、それぞれ異なる観点から調べてください。
  5. 振り分けを確認:対象を絞ったテストルールを1つ追加し、リクエストが意図したoutboundを選ぶか確認してから、ルール一式を元に戻します。
  6. デバッグログを元に戻す:必要に応じてloglevelを一時的にdebugへ変更します。確認後はwarningに戻し、接続情報が過剰に記録され続けないようにしてください。

コアを単独で実行する場合は、設定ファイルのテストコマンドを使用できます。以下はサブコマンド形式を採用しているV2Ray/Xray実行ファイル向けです。パスは実際のファイルの場所に置き換えてください。古いバージョンではコマンドライン引数が異なる場合があるため、まずローカルのhelp出力を確認してください。

v2ray test -c config.json
xray run -test -config config.json

テストに成功しても、現在のコアで設定を解析・読み込みできたことがわかるだけです。ノードの稼働状況、証明書の正しさ、すべてのルールが意図どおりかどうかまでは確認できません。最後に、プロキシ対応を明示しているアプリから実際にリクエストを送信してください。ログではinboundのタグ、接続先アドレス、選択されたoutboundを確認します。共有する前に認証情報や個人のアクセス履歴を削除してください。

確認のまとめ:入口、outbound、routing、DNSを個別に検証

まずリクエストが正しいポートに届くことを確認し、次にプロキシノードの接続を検証します。その後、振り分けと名前解決の方針を追加してください。各段階で元に戻せる設定を保存し、4つのレイヤーを同時に変更して「まだつながらない」だけが残る事態を避けましょう。