本文速览

适合已经导入节点、准备读懂内核配置的用户。先沿请求路径识别四个顶层字段,再拆读一份 VMess + WebSocket + TLS 示例,最后检查标签引用、规则顺序与 DNS。读完能判断该改入站、节点参数还是路由,而不是每次连接失败就把整份 JSON 重写一遍。

1. 配置文件与客户端设置:先分清对象

v2rayN、v2rayNG 是客户端,负责节点管理、订阅更新以及生成内核运行配置。v2rayNG 使用 Xray 内核;v2flyNG 使用 v2fly 内核。v2rayN 可以管理不同内核,但本文讨论的是 V2Ray/Xray 的传统 JSON 配置格式,不能把它当成所有内核通用的字段表。

这里的 config.json 指内核实际读取的配置,不是客户端保存窗口位置、订阅分组等信息的设置文件。文件名也不一定固定:判断依据是启动命令指定了哪个文件,以及内容有没有 inbounds、outbounds 等字段。客户端更新节点或重启内核时,自动生成的文件可能被覆盖。

应用请求本地入站路由匹配选定出站目标服务

2. 完整 JSON 示例:两个入站、三个出站

下面是用于拆读的完整结构。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 入站端口
10809
示例 HTTP 入站端口
443
示例远端 TLS 端口

这些端口是本文示例值,不是每个版本都固定使用的默认值。JSON 中的端口是数字,true 是布尔值,不能分别写成带引号的字符串。最后一个成员后面也不能加逗号;为便于验证,示例没有使用注释。

3. inbounds:监听地址、协议与嗅探

listen 决定接收连接的本地地址,port 决定端口,protocol 决定应用应该用什么代理协议访问它。SOCKS 客户端不能直接连 HTTP 入站,端口通了也不代表协议对了。应用手动配置时,示例对应 SOCKS5 的 127.0.0.1:10808,或 HTTP 代理的 127.0.0.1:10809。

SOCKS 入站

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

仅监听本机;UDP 支持还要求应用使用 SOCKS5 UDP 转发。

HTTP 入站

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 入站还使用 auth: "noauth",不能照搬后直接暴露到网络。需要共享代理时,应一起检查认证、防火墙和允许访问的来源。

sniffing 可从 HTTP Host 或 TLS 握手里的服务器名称识别目标域名,帮助域名规则匹配。routeOnly: true 表示嗅探得到的名称只用于路由判断,不用它替换原始连接目标。它不解密 HTTPS,也不保证任何流量都能得到域名;本例只在 SOCKS 入站启用了嗅探。

4. outbounds:节点认证与传输层分别看

代理出站中,protocol: "vmess" 表示节点协议。settings.vnext 保存服务器列表,users 保存认证参数。id 是用户 UUID;alterId: 0 对应现代 VMess 的常用配置,不要拿旧教程里的非零值试运气。users[].security: "auto" 是 VMess 的加密选项,和 TLS 开关不是一回事。

字段示例值实际作用
vnext[].addressnode.example.invalid内核连接的节点地址
vnext[].port443服务端监听端口,不是本地入站端口
streamSettings.networkws使用 WebSocket 传输
streamSettings.securitytls在传输层启用 TLS
tlsSettings.serverNamenode.example.invalidTLS 服务器名称,通常用于 SNI 与证书名称验证
wsSettings.path/wsWebSocket 请求路径,需要与服务端对应
wsSettings.headers.Hostnode.example.invalidWebSocket 握手的 HTTP Host

示例里地址、SNI 和 Host 相同,只是为了减少变量;真实配置中三者可以不同。连接一个 IP 地址时,TLS 仍可能要求指定域名。路径也必须完整匹配,/ws 与 /proxy 不是可以互换的装饰文本。

freedom 表示直连出站,blackhole 表示阻断出站。direct、block、proxy 则是本文选用的标签,名字可以更改,但所有 outboundTag 引用必须一起改。VLESS 出站的用户字段与 VMess 不完全相同,不能只把 protocol 换成 vless 就认为迁移完成。

判断:连接失败先核对两层参数

先比对地址、端口与 UUID,再比对 network、TLS 名称、Host 和 path。不要用关闭证书验证来替代修正 serverName;错误配置不会因为跳过检查就自动变成正确节点。

5. routing:规则顺序与默认出站

rules 按数组顺序检查,首条匹配的规则决定出站。示例先阻断一个演示域名,再让私有地址和 localhost 直连。没有规则匹配时,传统 V2Ray/Xray 配置使用 outbounds 数组中的第一个出站,因此这里默认走 proxy。这个默认行为与标签是否叫「proxy」无关。

  1. 确认标签:outboundTag: "direct" 必须能找到 tag: "direct" 的出站。
  2. 检查顺序:具体例外通常放在宽泛规则之前;末尾兜底规则一旦提前,会遮住后面的规则。
  3. 检查条件:同一条规则里不同字段通常需要同时满足;一个字段数组内的多个候选项通常按任一命中处理。
  4. 检查数据:geoip:private 依赖 GeoIP 数据文件可用,使用 geosite 条目时也要检查对应域名数据。

域名匹配语法有区别:full:example.com 只匹配完整域名,domain:example.com 匹配该域名及其子域名。没有前缀的字符串通常按关键词匹配,容易比预期覆盖更多目标。写精确例外时,优先把匹配范围写明白。

domainStrategy解析时机排查重点
AsIs路由判断不主动把域名解析为 IP域名请求不应指望自动命中 IP 规则
IPIfNonMatch域名未匹配规则时,再尝试解析并进行 IP 匹配解析结果可能改变最终出站
IPOnDemand匹配过程需要 IP 条件时触发解析检查解析开销及 DNS 返回结果

本例的 AsIs 特意保持判断过程简单。目标本来就是私有 IP 时,可以匹配私有地址规则;目标是某个解析到私有 IP 的域名时,却不保证命中该规则。内网域名应增加明确的直连域名规则,或在理解解析行为后调整策略。

6. dns:内置解析器不等于系统 DNS

dns.servers 指定内核内置解析器使用的服务器。本例只有 223.5.5.5 一个上游,方便说明结构,不代表已经实现了完整的 DNS 分流。应用可能在发请求前自行解析;系统、浏览器与内核各自的解析路径,需要分别检查。

因此,配置了 dns 并不能单独证明所有解析都按预期走代理。需要核对应用是否启用独立解析、路由的 domainStrategy、出站解析策略,以及 DNS 查询本身的可达性。特别是依赖域名才能连接的节点,别让解析节点域名的路径又依赖这个尚未建立的节点连接。

7. 从导出配置到排错:每次只改一个变量

排错时先保留一份能运行的配置,再检查内核版本和当前实际读取的文件。v2rayN 的「设置」→「参数设置」可以查看或调整本地监听相关参数,具体分页与选项名称会随版本变化。界面中的节点表单、路由设置与运行时 JSON 要相互对应,不能只盯着一个被客户端重新生成的文件。

  1. 检查语法:使用本地编辑器检查括号、逗号与类型。UUID、订阅地址及节点信息不应提交到公开的在线格式化服务。
  2. 检查内核兼容性:确认读取配置的是 V2Ray 还是 Xray。新字段和传输方式必须以当前内核支持范围为准。
  3. 检查入口:确认进程已经监听实际配置的端口。出现 address already in use 时,先处理端口占用,不要先改节点 UUID。
  4. 检查出站:暂时减少规则变量,核对地址、认证和传输。超时、认证失败、TLS 错误需要按不同方向排查。
  5. 检查分流:增加一条范围明确的测试规则,观察请求是否选中了目标出站,再恢复完整规则集。
  6. 收回调试日志:必要时把 loglevel 临时改成 debug;完成后恢复 warning,避免持续记录过多连接信息。

独立运行内核时,可使用其配置测试命令。下面针对当前采用子命令形式的 V2Ray/Xray 可执行文件,路径要替换为实际文件位置;旧版命令行参数可能不同,先查看本机 help 输出。

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

测试成功主要说明配置能被当前内核解析和加载,不代表节点在线、证书正确或所有规则都符合意图。最后还要用一个明确支持代理的应用发起真实请求。检查日志时重点找入站标签、目标地址和选中的出站;分享日志前移除认证信息与个人访问记录。

操作结论:按入口、出站、路由、DNS 分层验证

先证明请求进入正确端口,再证明代理节点可用,最后加入分流与解析策略。每一步留一个可恢复的配置副本,避免四层同时改动后只剩一句「还是不通」。