V2Ray config.json 结构详解:inbounds、outbounds 与 routing 逐段拆读

按 log、inbounds、outbounds、routing、dns 的顺序逐段拆解 config.json,说明每个字段的作用与常见写法。

本文速览

适合已经导入过订阅、希望读懂内核运行配置的用户。先分清应用入口、连接出口和路由选择,再用一份仅含本地监听、直连与阻断的完整配置验证字段关系。读完可以定位端口冲突、标签写错、规则顺序失效,以及 DNS 设置改了却没有生效的原因。

先定边界:config.json 是内核配置,不是订阅列表

v2rayN 是桌面客户端,V2Ray 与 Xray 是处理连接的内核。客户端保存订阅、节点和界面设置,再按所选内核生成运行配置。因此,订阅里的一条 VMess 或 VLESS 分享链接,并不等于一份完整的 config.json:它通常只描述远端连接参数,缺少本地入口、日志、DNS 和分流规则。

本文采用 V2Ray 传统 JSON 配置结构,展示 V2Ray 与 Xray 中常见的字段关系。V2Ray v5 还提供另一套配置格式,不能仅凭文件扩展名判断格式,更不能把两套字段混在一起。具体协议和传输字段还要以实际运行的内核版本为准。

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

阅读时沿着这条链找问题。网页请求必须先进入某个入站,才有机会参与路由;路由选中的是出站标签,不是订阅分组名称。DNS 则为域名解析及部分路由判断提供支持,并不是所有流量必经的一个“代理出口”。

log:先确定能看到什么,再调整连接参数

log 位于顶层,用于控制日志输出。排障时先用 info,问题解决后通常可改回 warning。直接开启 debug 容易产生大量细节,反而让一条简单的端口冲突淹没在输出里。

{
  "log": {
    "loglevel": "info"
  }
}

这是字段片段,不是完整运行配置。常见日志级别包括 debug、info、warning、error 和 none。这里不设置日志文件路径,便于先从终端或客户端日志面板观察启动结果;若配置 access、error 文件,必须确认目标目录存在且运行账户可写。

inbounds:应用从哪个地址、哪个端口进入

inbounds 是数组,一份配置可以同时接受 SOCKS 和 HTTP 代理请求。listen 指定监听地址,port 指定本地端口,protocol 决定应用应该用什么代理协议连接。它们不是远端节点的地址和端口。

10808
本文 SOCKS 入站端口
10809
本文 HTTP 入站端口
127.0.0.1
仅本机可连接的监听地址

以上是本文明确选用的端口,不代表所有客户端版本的默认值。若 v2rayN 已经占用其中一个端口,测试内核就无法再次绑定;应先停止占用进程,或同时修改配置与测试命令中的端口。不要只改其中一处。

SOCKS 入站

tag
local-socks
listen
127.0.0.1
port
10808
protocol
socks
settings
auth 为 noauth,udp 为 false

本例只测试 TCP;关闭 UDP 转发不妨碍普通 HTTPS 连接。

HTTP 入站

tag
local-http
listen
127.0.0.1
port
10809
protocol
http
settings
空对象,使用该入站默认设置

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": {}
    }
  ]
}

这两个出站不需要远端账号:freedom 使用本机网络建立目标连接,blackhole 丢弃匹配流量。在本文没有负载均衡器等额外设置的配置里,路由没有选中任何规则时,使用数组中的第一个出站,所以这里的默认出口是 direct。

结论:改出口前先确认标签指向的协议

排查“规则已命中但仍走本地网络”时,先找到对应出站的 protocol;若它是 freedom,就应修正出口配置,而不是反复调整域名匹配条件。

routing:从上往下匹配,标签必须能找到

routing.rules 按顺序检查,首个匹配规则决定流量去向。常用条件包括域名 domain、目标 IP ip、端口 port 和入站标签 inboundTag。一条规则包含不同类型的条件时,通常需要同时满足;同一域名列表中的多个条目则是候选匹配项。

{
  "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 规则,但访问一个解析到私网地址的域名,不会仅因这条规则就触发路由解析。最终直连建立连接仍可能需要解析域名,这是出口连接阶段的工作,不能与路由策略混为一谈。

dns:内置解析器不等于接管所有 DNS 请求

顶层 dns 配置内置解析器。路由需要域名对应 IP、或某个出站配置要求使用内置解析结果时,它才会参与对应过程。仅仅写入 dns.servers,不会自动接管浏览器的加密 DNS、系统的所有解析,也不会凭空创建一个本地 DNS 监听端口。

{
  "dns": {
    "servers": ["localhost"]
  }
}

localhost 在这里是调用系统解析能力的特殊值,不表示必须在 127.0.0.1:53 运行 DNS 服务。本文使用它保持示例简单,但不把它当作 DNS 隔离方案。若目标是指定解析出口,需要一并检查内核 DNS 行为、相关路由以及出站的域名解析策略。

  1. 先确认应用交付了什么:HTTP 代理的 CONNECT 请求通常携带域名;SOCKS 请求既可能携带域名,也可能携带应用已解析好的 IP。
  2. 再看路由是否解析:routing.domainStrategy 决定路由何时需要把域名转换为 IP。
  3. 最后看出口如何连接:freedom 的解析策略属于出站设置,与路由层的同名概念分属不同位置;不要把字段复制到错误层级。

例如使用 curl 时,socks5://127.0.0.1:10808 通常由 curl 在本地解析目标;socks5h://127.0.0.1:10808 则把域名交给 SOCKS 代理端处理。测试域名分流时优先采用后一种,否则内核只看见 IP,域名规则就可能没有匹配机会。

完整配置:用直连和阻断验证五个顶层字段

下面是一份完整的传统 JSON 格式配置。它只提供本机 HTTP、SOCKS 入口和直连、阻断出口,不包含远端代理节点,也不会让本机原本无法直连的网站自动可达。它的用途是先验证配置结构、端口监听与规则引用,再逐步加入真实节点参数。

{
  "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 对象的顶层字段书写顺序不决定执行顺序;本文按阅读逻辑排列。真正影响行为的是规则数组顺序、默认出站位置,以及字段间的引用关系。保存时使用 UTF-8,键名和字符串使用英文双引号,最后一项之后不要添加逗号,也不要把解释性注释复制进文件。

验证顺序:语法、启动、入站、路由分开检查

将完整示例保存为当前目录下的 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

两条内核检查命令按实际使用的内核二选一,不要为了测试而同时运行两套服务。旧版可执行文件的子命令可能不同,先执行 xray help 或 v2ray help 确认。检查通过后,使用该版本支持的运行命令加载同一文件,例如 Xray 的 xray run -config config.json。

# 在另一个终端检查 TCP 监听
ss -lntp 'sport = :10808 or sport = :10809'

# 通过 HTTP 入站测试直连出口
curl --noproxy "" --proxy http://127.0.0.1:10809 --max-time 15 -I https://example.org/

# 将域名交给 SOCKS 入站,测试阻断规则
curl --noproxy "" --proxy socks5h://127.0.0.1:10808 --max-time 5 -I https://blocked.example/

第一条 curl 是否成功仍取决于本地网络、系统解析和目标站点;它不是代理节点测速。第二条请求预期无法取得目标 HTTP 响应,因为目标域名命中 block。具体报错文本会随内核和连接阶段不同而变化,应结合日志确认,不能单凭一次超时就认定路由生效。

结论:每次只验证一个环节

先确认监听存在,再用显式代理参数确认请求进入内核,最后对照日志判断出口。这样能把“应用没走代理”和“进入代理后规则不对”拆成两个问题,避免同时修改端口、DNS 和节点造成新的干扰。

  1. 连接被拒绝:核对进程是否启动、监听地址与端口是否一致。远端节点参数暂时不是排查重点。
  2. 入站有请求但出口不对:检查规则顺序、请求携带的是域名还是 IP,以及默认出站是否放错位置。
  3. 规则正确但连接失败:再检查解析结果、目标可达性、远端认证与传输安全参数。
  4. 重启后修改消失:确认修改的是手工维护配置,还是客户端生成的临时运行文件。使用客户端时,可按使用指南回到对应设置入口调整。

掌握这套结构后,再看 v2rayN 生成的配置会直接得多:先找入站端口,再找默认出口,接着读规则,最后检查 DNS 的实际参与位置。需要确认平台安装和内核准备步骤时,可继续查看完整文档,不必先把全部高级字段塞进一份文件。

下载v2rayN