本文速览
本文适合已经能导入节点、但看不懂核心配置与日志字段的用户。读完可以分清本地监听、远端连接和规则分流各自位于哪个区块,并能沿着 tag 找到“请求从哪里进入、经过哪条规则、最终由哪个出口发送”。
先看全局:配置文件不是一条节点
V2Ray 5.x 使用 JSON 描述核心的运行方式。一个完整客户端配置通常不只保存服务器地址和用户 ID,还要定义本机接受流量的入口、向外发送流量的出口、DNS 行为、日志级别以及路由规则。图形客户端里看到的“一条节点”,主要对应代理出站中的一组服务器参数,并不等于整份运行配置。
读取配置时,可以先忽略协议细节,把数据流理解为三段:应用把请求交给本地监听端口,
inbounds 接收并识别请求,routing 根据域名、IP、端口或协议选择目标,最后由某个 outbounds 项发送。入站和出站通过 tag 取名,路由规则再引用这些名称。应用请求入站接收嗅探域名规则匹配选择出站发往目标
顶层字段没有固定的书写顺序,JSON 解析器不会因为
routing 写在 outbounds 前面就改变执行结果。但数组内部的顺序可能有意义:路由规则通常从上到下匹配,而没有命中规则的流量通常交给首个出站。因此,阅读时既要看 tag,也要看数组位置。inbounds
- 方向
- 应用到核心
- 常见协议
- SOCKS、HTTP
- 关键字段
- listen、port、tag
- 典型端口
- 10808
决定本机哪些地址和端口可以把流量交给核心。
outbounds
- 方向
- 核心到目标
- 代理协议
- VMess、VLESS
- 辅助出口
- freedom、blackhole
- 识别方式
- tag
节点服务器信息、传输层与 TLS 参数主要集中在这里。
routing
- 规则类型
- field
- 匹配对象
- 域名、IP、端口
- 执行结果
- outboundTag
- 检查顺序
- 从上到下
负责选择出口,不负责建立远端协议连接。
dns 与 log
- dns
- 解析策略
- log
- 日志级别
- 常用级别
- warning
- 排错级别
- info
不是每份配置都显式写出,但会直接影响解析与排错。
inbounds:流量从本机哪里进入
inbounds 是数组,每个对象代表一个本地入口。桌面客户端常见做法是同时建立 SOCKS 与 HTTP 入站,例如把 SOCKS 放在 127.0.0.1:10808,把 HTTP 放在 127.0.0.1:10809。浏览器、命令行工具或系统代理把请求发到对应端口后,核心才开始处理这条连接。listen 决定监听地址。写成 127.0.0.1 时,只接受本机连接;写成 0.0.0.0 会监听所有网络接口,局域网设备可能因此访问该端口。除非明确需要局域网代理,否则本机回环地址更符合桌面使用场景。port 必须没有被其他程序占用,重复占用时日志常出现 bind 或 address already in use。10808
示例 SOCKS 端口
10809
示例 HTTP 端口
127.0.0.1
仅本机监听
53
标准 DNS 端口
protocol 表示入口协议,不是远端节点协议。一个 SOCKS 入站完全可以把请求转给 VLESS 或 VMess 出站,两者没有“协议必须相同”的关系。settings 保存该入站协议专属的参数;SOCKS 入站常见的 udp: true 表示允许接收 UDP 请求。sniffing 用于从连接内容中恢复目标域名。应用有时先把域名解析成 IP,再向本地代理发起连接;如果核心只能看到 IP,按域名编写的路由规则就无法命中。启用嗅探并设置 destOverride 后,核心可以在适用的 HTTP、TLS 流量中识别域名,再交给 routing 判断。{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
tag只需在当前配置内保持唯一,名称可以是socks-in、lan-in等可读短语。- 系统代理只会把支持系统代理设置的流量送进 HTTP 或 SOCKS 入口,不等于捕获所有程序流量。
- 端口修改后,调用方也必须同步修改;只改核心配置而不改系统代理,会表现为立即拒绝连接。
- UDP 是否能正常工作,还取决于应用、入站协议、出站协议和服务端配置。
outbounds:节点、直连与阻断出口
outbounds 同样是数组。代理节点通常只是其中一项,实际客户端还会生成直连出口和阻断出口。代理出口使用 VMess 或 VLESS 等协议连接远端服务;freedom 让核心直接访问目标;blackhole 则终止被规则选中的连接。代理出站可以再拆成两层。
settings 描述协议身份与服务器端口,例如 VMess 的地址、端口、用户 ID 和安全参数;streamSettings 描述底层传输与安全层,例如 TCP、WebSocket、TLS 或 Reality。协议字段正确但传输路径、SNI 或安全层不一致时,连接仍然会失败。VMess + WebSocket + TLS
- protocol
- vmess
- network
- ws
- security
- tls
- 远端端口
- 443
- 路径
- /v2ray
用户身份放在 settings,传输路径和 TLS 放在 streamSettings。
VLESS + TCP + Reality
- protocol
- vless
- network
- tcp
- security
- reality
- flow
- xtls-rprx-vision
- 指纹
- chrome
Reality 参数必须与服务端对应,不能只把 security 字段改名。
直连出口
- tag
- direct
- protocol
- freedom
- 远端节点
- 不需要
- 用途
- 本地与直连规则
命中 direct 后,由本机网络直接连接目标。
阻断出口
- tag
- block
- protocol
- blackhole
- 远端连接
- 不建立
- 用途
- 阻断指定流量
路由规则引用 block 后,请求不会继续发往目标。
出站的
tag 是排查配置时最重要的索引。看到路由规则写着 "outboundTag": "direct",就回到 outbounds 查找 tag 为 direct 的对象。若规则引用了不存在的 tag,核心通常会在启动阶段报告配置错误,而不是自动猜测目标出口。订阅提供的通常是节点连接参数,不会完整决定本地端口、日志级别和所有分流规则。v2rayN、v2rayNG 或 v2flyNG 导入订阅后,会把节点字段与客户端自己的设置合并,再生成交给核心的运行配置。因此,同一条订阅在不同客户端里生成的完整 JSON 可能不同。
结论:先按层定位出站错误
认证失败先核对 settings 中的地址、端口和用户信息;TLS、Reality 或 WebSocket 握手失败再检查 streamSettings。把两层参数混在一起修改,最容易造成字段看似齐全但连接仍然超时。
routing:按顺序把请求交给指定出口
routing.rules 是规则数组。常用规则类型为 field,可以按照 domain、ip、port、network、protocol、inboundTag 等条件匹配。规则本身不转发数据,只通过 outboundTag 指定由哪个出站处理。规则顺序会改变结果。假设第一条把某个域名交给代理,第二条把更宽泛的域名集合交给直连,那么该域名会在第一条命中后停止继续匹配。更具体的阻断或强制代理规则应放在前面,覆盖面较大的直连规则和最终兜底规则放在后面。
| 匹配字段 | 匹配对象 | 典型用途 | 执行结果 |
|---|---|---|---|
domain |
完整域名、后缀或域名集合 | 按站点类别分流 | 交给指定 outboundTag |
ip |
单个 IP、CIDR 或 IP 集合 | 局域网与目标网段分流 | 直连、代理或阻断 |
port |
单端口或端口范围 | 控制特定服务流量 | 选择对应出口 |
network |
tcp、udp 或两者 | 最终兜底规则 | 覆盖剩余连接 |
inboundTag |
一个或多个入站 tag | 不同本地入口使用不同出口 | 实现入口级分流 |
domainStrategy 决定路由器何时为域名解析 IP。AsIs 优先按原始域名匹配,不主动为了 IP 规则解析;IPIfNonMatch 会先检查域名规则,未命中时再解析 IP 并尝试 IP 规则;IPOnDemand 在遇到可能需要 IP 的规则时更早触发解析。选择哪一种取决于规则设计,不是数值越激进越好。如果没有任何规则命中,V2Ray 通常使用第一个出站。为避免依赖隐含顺序,可以在末尾增加覆盖 TCP 与 UDP 的兜底规则,并明确写出目标
outboundTag。这样调整 outbounds 排序时,不会意外改变默认流量方向。{
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"protocol": ["bittorrent"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
结论:路由排错从第一条规则开始
先确认目标域名或 IP 实际命中了哪条规则,再检查该规则引用的 outboundTag。节点连通性正常但访问方向错误,通常是规则顺序、域名嗅探或 DNS 结果造成,而不是代理协议本身损坏。
一份可读的最小客户端配置
下面的示例把日志、一个 SOCKS 入站、三个出站和四条路由规则放在同一文件中。示例地址与用户 ID 仅用于展示结构,不能作为实际节点使用。配置文件采用标准 JSON,键名和字符串必须使用双引号,末尾不能保留多余逗号,也不能直接插入注释。
从数据流看,应用先连接
127.0.0.1:10808。核心检查路由:BitTorrent 流量进入 block,私有地址和指定域名集合进入 direct,其余 TCP 与 UDP 请求进入 proxy。proxy 再使用 VMess、WebSocket 与 TLS 连接示例服务器的 443 端口。{
"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"]
}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "server.example.com",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000000",
"alterId": 0,
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "server.example.com"
},
"wsSettings": {
"path": "/v2ray"
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"protocol": ["bittorrent"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
- 先检查 JSON 语法,尤其是双引号、逗号和方括号是否成对。
- 再核对所有 tag 是否唯一,routing 引用的 outboundTag 是否真实存在。
- 确认入站端口未被占用,并让系统代理或应用指向相同端口。
- 核对代理出站的协议、服务器端口、传输方式与安全层是否成套对应。
- 最后检查规则顺序,确认兜底规则位于更具体的规则之后。
图形客户端与核心 JSON 怎么对应
v2rayN、v2rayNG 与 v2flyNG 都把常用字段拆成表单。节点编辑页里的地址、端口、用户 ID、传输方式和安全设置,主要映射到代理 outbound;本地 SOCKS 端口、允许局域网连接等选项映射到 inbounds;路由模式、规则集和自定义规则则映射到 routing。
以 v2rayN 为例,本地端口与基础行为通常从「设置」→「参数设置」进入调整,节点参数则在服务器编辑界面修改。客户端启动核心时,会把节点、全局参数和路由设置组合成运行配置。直接修改临时生成的核心 JSON,下一次切换节点、更新订阅或重启核心时可能被重新生成。
Android 上的 v2rayNG 与 v2flyNG 也采用相似分层,但两者使用的核心不同:v2rayNG 使用 Xray 内核,v2flyNG 使用 v2fly 内核。部分高级字段和默认值会有差异,不能把某个客户端导出的完整配置原样当作另一客户端的界面配置文件。
为什么界面里只有一条节点,运行配置却有三个出站?
节点只对应 proxy 出站。客户端会额外生成 direct 与 block,供直连和阻断规则引用,因此 outbounds 数量通常多于节点数量。
修改生成的 JSON 后,重启为什么又恢复了?
生成文件属于运行产物。应回到「设置」→「参数设置」、节点编辑或路由设置修改来源数据,再重启核心验证。
导入订阅后,本地端口为什么没有跟着变化?
订阅主要提供节点连接参数,本地监听端口属于客户端设置。检查 SOCKS 端口是否仍为 10808,并同步更新系统代理。
路由规则写了域名,为什么还是走错出口?
先开启适用的域名嗅探,再检查 domainStrategy、DNS 结果和规则顺序。日志级别临时调到 info,可观察实际目标与出站 tag。
按日志顺序排查启动失败与分流错误
配置问题可以分为启动阶段和运行阶段。启动阶段失败通常与 JSON 语法、字段类型、重复端口或无效 tag 有关,核心甚至不会建立入站监听。运行阶段才出现的问题,则更多与节点参数、DNS、规则命中和目标网络有关。
排错时不要一次修改多个区块。先把
loglevel 从 warning 临时调整为 info,重现一次问题并记录时间。确认是入站未监听、规则选错出口,还是 proxy 出站连接失败,再回到对应区块修改。问题解决后可恢复 warning,减少常规日志量。- 出现 JSON 解析错误:检查报错行附近的逗号、双引号、数组与对象闭合符号。
- 核心启动但端口未监听:检查
listen、port以及端口占用,确认没有两个入站使用同一地址和端口。 - 应用立即提示拒绝连接:核对应用代理地址是否为
127.0.0.1,端口是否与实际入站一致。 - 节点可连接但分流错误:按 routing.rules 从上到下检查,确认目标先命中了哪条规则。
- 域名规则始终不命中:检查 sniffing 是否启用、DNS 是否返回预期结果,以及规则使用的是域名还是 IP 条件。
- 只有部分 UDP 应用失败:确认 SOCKS 入站允许 UDP,并检查出站协议、服务端与网络是否共同支持该流量。
{
"log": {
"loglevel": "info"
}
}
日志中的 inbound tag、目标地址和 outbound tag 可以串起一条完整路径。例如请求由
socks-in 进入,目标显示为某个域名,最终选择 direct,说明节点本身并未参与这次连接;若预期应该代理,就应检查 routing,而不是反复修改 VMess 或 VLESS 身份参数。反过来,如果日志已经显示规则选择
proxy,随后才发生 TLS 握手或连接超时,路由基本完成了职责。此时应把注意力转向代理 outbound 的地址、端口、SNI、传输路径、系统时间和远端可达性。结论:用 tag 追踪完整链路
把排错过程固定为“入站 tag → 目标域名或 IP → 命中规则 → 出站 tag → 传输连接”。每一步只对应一个配置区块,能够避免把端口占用、分流错误和节点握手失败混成同一个问题。