读配置先找入口、出口和连接它们的标签,再看路由与 DNS。本文以一份不含远端服务器凭据的 V2Ray 传统 JSON 配置为样本,逐段解释字段、匹配顺序和检查方法。适合已经导入订阅、希望理解 v2rayN 导出文件的用户;示例只演示本地 SOCKS 接入、直连和阻断,不提供远端代理能力。
一、先分清客户端配置与内核运行配置
v2rayN 是管理界面,V2Ray 与 Xray 是实际处理连接的内核。订阅保存的是服务器信息或配置来源,界面还会保存分组、当前选择、路由预设等状态;内核启动时读取的 JSON 则描述监听端口、出站协议和路由规则。这几类文件不能仅凭扩展名相同就互相替换。
本文使用 V2Ray 的传统 JSON 配置结构,不覆盖所有内核的专有字段。v2rayNG 使用 Xray 内核,v2flyNG 使用 v2fly 内核;即使都能看到 inbounds 和 outbounds,也不代表每个协议选项都兼容。尤其是 REALITY、流控与传输相关字段,应按实际运行内核的文档判断。
阅读文件时沿这条链找引用关系即可。log 负责观察过程,dns 提供解析能力,它们不是必须按书写位置依次执行的网络节点。JSON 对象中五个模块的先后排列不决定处理顺序,但数组中的路由规则顺序会影响结果。
- 对象:
{}中保存键值,例如一个入站的监听地址和协议。 - 数组:
[]中保存多个条目,例如多个出站或多条路由规则。 - 类型:
10808是数字,"10808"是字符串,false是布尔值,不能随意互换。 - 语法:本文按标准 JSON 展示,不使用注释和末尾逗号,键名与字符串都用英文双引号。
二、完整示例:本地 SOCKS 入站与两种出站
下面是一份用于理解结构的完整配置。它仅监听本机回环地址,接收 SOCKS 请求;目的端口为 25 的 TCP 连接被阻断,其余未被规则选中的连接默认直连。它不会让应用自动使用代理,也不会建立通往远端代理服务器的连接。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": false
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"inboundTag": ["local-socks"],
"network": "tcp",
"port": "25",
"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"
},
{
"type": "field",
"domain": ["full:localhost"],
"outboundTag": "direct"
}
]
},
"dns": {
"servers": ["localhost"],
"queryStrategy": "UseIP"
}
}
这些数字都是示例配置的确定值,不是客户端所有版本的默认值。若本机已有程序占用 10808,应换一个空闲端口,并同步修改应用里的 SOCKS 地址。示例中的私网直连规则用于展示写法,并不构成完整的本地网络地址清单。
三、log 与 inbounds:先确认请求能否进入内核
log.loglevel 决定日志详细程度。示例使用 warning,适合关注告警和错误;排障时可临时改为 info,必要时再用 debug。没有写 access 或 error 文件路径,不等于日志一定消失,输出仍可能被启动它的客户端接收并展示。
inbounds 是入口数组。示例只接收发往 127.0.0.1:10808 的 SOCKS 连接,所以应用必须显式使用这个地址。把浏览器设置为 HTTP 代理却指向仅提供 SOCKS 的端口,会出现协议不匹配;单纯启动内核也不会改变系统代理。
日志观察项
- loglevel
- warning
- 临时排障
- info 或 debug
- 输出位置
- 由路径配置与启动方式决定
定位问题后降低详细程度,避免长期记录过多连接信息。
本地入口项
- listen
- 127.0.0.1
- port
- 10808
- protocol
- socks
- tag
- local-socks
tag 是路由引用名,不是监听地址,也不是远端节点名称。
auth: "noauth" 表示此 SOCKS 入站不要求认证,因此示例将监听范围限制在本机。不要为了让其他设备连接,直接把监听地址改成所有接口而忽略访问控制。udp: false 表示该入站没有启用 SOCKS UDP 转发,不能用它验证 UDP 应用是否正常。
端口占用属于入口启动问题,连接超时属于后续链路问题。先确认日志中没有监听失败,再判断路由、DNS 或远端服务器,能减少无效修改。
四、outbounds:协议负责连接,tag 负责被引用
outbounds 数组定义连接怎样离开内核。示例中的 freedom 直接连接目标,blackhole 丢弃匹配流量。direct 与 block 只是人为指定的标签;把标签改成其他名字不会改变协议行为,但所有引用它的规则都必须一起修改。
| 字段 | 示例值 | 读取重点 |
|---|---|---|
| outbounds[0].tag | direct | 路由引用名;此处也是默认出站 |
| outbounds[0].protocol | freedom | 直接访问目标,不经过远端代理 |
| outbounds[1].protocol | blackhole | 阻断被路由选中的连接 |
| settings | 空对象 | 本例使用默认行为;代理协议通常需要更多参数 |
在这里使用的传统配置模型中,没有匹配任何规则的连接会交给第一个出站。因此调整数组顺序可能改变默认行为。若把 block 放到第一项,原来默认直连的请求就可能被阻断;不要把排序当成单纯的界面整理。
实际 VMess 或 VLESS 出站还会包含服务器地址、端口、认证信息,以及可能存在的 streamSettings。其中 protocol 指定代理协议,传输与安全层参数另有位置。不能只把 freedom 改成 vless 就期待建立连接,也不能将不同协议的 settings 原样互换。
判断默认行为:先看第一项,再查标签引用
修改配置前记录第一个出站的 tag,并搜索全部 outboundTag。只有同时确认默认路径和显式路径,才能判断一条连接最终会直连、代理还是被阻断。
五、routing:按顺序匹配,不按规则长度猜优先级
routing.rules 从上到下检查,命中后采用对应的出站。它不会自动认为更长的域名或更窄的 IP 网段优先。同一条规则内不同条件通常需要同时满足;同一个条件数组里的多个值则通常是任选其一。配置前应先把“同时满足”与“任一满足”分清。
- 第一条规则:入口标签必须是
local-socks,网络必须是 TCP,目的端口必须是25。三个条件同时满足才交给block。 - 第二条规则:目标 IP 落入列出的任一网段时交给
direct。即使目标是私网地址,若先命中上一条 TCP 25 规则,也仍然会被阻断。 - 第三条规则:
full:localhost表示精确匹配该域名,不是匹配所有包含 localhost 字样的名称。 - 全部未命中:使用第一个出站,即本例的
direct。第二、三条在本例中结果与默认出站相同,保留它们是为了展示规则写法。
inboundTag 要引用入站的 tag;outboundTag 要引用出站的 tag。大小写和拼写都应一致。它们不是内核自动识别的中文分组名称,也不会自动跟随客户端里节点显示名的变化。
domainStrategy: "AsIs" 表示路由阶段不为了 IP 规则主动把域名解析成地址。如果应用提交的是域名,第二条 IP 规则未必能据此匹配;如果提交的本来就是 IP,则可以直接检查网段。改为 IPIfNonMatch 会在域名阶段未匹配时尝试解析后再匹配,不能把它理解成所有 DNS 请求都改走远端。
full:example.com:只匹配该完整域名,适合精确测试。domain:example.com:匹配该域名及其子域名,适合按域名范围分流。port: "25":这里是目标端口,不是本地监听的10808。ip:针对目标地址;不能用来表达“来自某台局域网设备”的来源条件。
六、dns:区分解析策略与流量出口
示例的 dns.servers 仅有 "localhost",表示使用本机系统解析能力,不是在监听本机的 DNS 端口。queryStrategy: "UseIP" 允许查询 IPv4 与 IPv6 地址,实际返回结果仍受域名记录、解析器和网络条件影响。
写了 dns 模块不代表所有应用的 DNS 都进入了内核。应用可能已经自行解析,再把 IP 交给 SOCKS;也可能把域名交给内核处理。前者可能失去直接按域名分流所需的信息,后者才保留了目标域名。入口如何接收请求与 DNS 模块如何解析,是两个不同问题。
| 配置位置 | 控制内容 | 不应混淆为 |
|---|---|---|
| dns.servers | 内置 DNS 模块可用的解析来源 | 操作系统所有程序的 DNS 设置 |
| dns.queryStrategy | 查询地址族的策略 | 选择直连或代理的路由规则 |
| routing.domainStrategy | 路由匹配时是否借助解析结果 | 强制全部解析请求走同一出口 |
| 出站中的解析策略 | 该出站如何处理目标域名 | 所有内核共享的统一字段 |
需要按域名选择解析器时,可以进一步研究 DNS 服务器对象中的 domains 等字段,但还要核对查询流量怎样到达解析器。只换一个 DNS 地址,并不能证明解析请求经过了预期的代理路径。排障时应同时观察请求带入的是域名还是 IP,以及最终选中的出站。
七、导出文件怎么检查:从语法到实际连接
先复制一份配置再编辑,避免直接覆盖客户端自动生成的运行文件。v2rayN 可能在切换节点、更新订阅或重启内核时重新生成配置;如果修改只存在于临时运行文件中,下次启动就可能消失。长期变更应保存到客户端对应的路由、DNS 设置或自定义配置入口,具体入口以当前版本界面为准。
- 检查 JSON 语法:确认双引号、括号和逗号配对。若本机装有 Python,可用下面的命令检查基本语法;通过不代表内核支持所有字段。
- 确认实际内核:在客户端的内核选择与启动日志中核对名称、版本和所读取的配置文件路径,不要只看客户端名称。
- 检查引用关系:逐个搜索
inboundTag与outboundTag,确保都能找到对应定义,并核对第一个出站。 - 检查监听与请求:确认
127.0.0.1:10808能启动,应用也使用 SOCKS 协议和同一端口。 - 单项验证:一次只修改一个模块;先验证普通 TCP 请求,再测试域名规则和阻断规则,避免把多个变量混在一起。
python -m json.tool config.json
若语法通过但内核拒绝启动,继续看日志里的字段路径和错误类型。未知字段、协议选项不兼容、端口占用属于不同问题,不能用更换 DNS 统一解决。分享日志或配置前,应删去服务器认证信息、订阅链接与不必要的个人路径。
JSON 检查通过,为什么还是启动失败?
语法检查只确认文件能被解析。打开客户端启动日志,定位第一个错误,核对协议名称、字段类型和实际内核;若提示地址占用,先停用占用 10808 的程序或同步更换监听端口。
改了 outboundTag,为什么原来的节点不走了?
先检查新标签是否与某个出站的 tag 完全一致,再检查规则顺序。不要只改路由引用而漏改出站定义;也要确认请求是否提前命中了更靠上的规则。
复制这份配置,为什么没有连到订阅里的服务器?
本文只有 freedom 和 blackhole 两种出站。需要使用远端代理时,应由客户端根据有效订阅生成相应出站,再检查路由如何引用它;不要在这份样本中猜填认证参数。
重启 v2rayN 后,手改内容为什么不见了?
通常是运行配置被客户端重新生成。保留修改前后的副本,把需要长期保留的路由或 DNS 调整写入客户端持久化设置,再重启并核对新生成文件,而不是反复修改临时文件。