CONFIGURATION REFERENCE
V2Ray JSON 配置手册
配置结构、字段边界与逐段验证。
本页面向需要阅读、调整或排查配置文件的用户。首次连接先按入门指南完成订阅导入与连接验证,再回到本页查阅具体字段。桌面端首推 v2rayN;Android 可使用 v2rayNG,或按内核需求选择 v2flyNG。安装入口集中在客户端下载页。
阅读约定:示例采用常见的传统 JSON 配置结构。字段是否可用,以实际运行的 V2Fly 或 Xray 内核及其对应文档为准。片段用于说明所在层级,不能把不同章节的对象直接首尾拼接。
一、JSON 结构与配置生效范围
先区分客户端与内核
v2rayN、v2rayNG 和 v2flyNG 是管理配置的图形客户端;实际接受连接、匹配规则并转发数据的是内核。客户端界面的订阅、配置列表、系统代理和路由预设,并不一定与文件中的某个对象一一对应。阅读 JSON 前,应先从客户端运行信息或启动日志确认内核名称,再确定当前条目使用自动生成配置,还是自定义配置文件。
传统配置顶层通常是一个对象,内部按职责划分为 log、inbounds、outbounds、routing、dns 与 policy。其中入站和出站是数组,因为一个进程可以提供多个本地入口,也可以选择多个转发出口。不要把数组的方括号改成花括号,哪怕数组里暂时只有一个成员。
最小配置用于建立基线
下面是一份本机 SOCKS 入站转直连出站的基线配置。它能帮助验证内核启动、本地监听和应用接入,但不会建立远程代理连接。测试时让应用明确使用本机 SOCKS 端口,并选择允许直接访问的目标。基线通过后再加入远程出站、路由和 DNS,才能判断新增字段造成的变化。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
}
]
}
JSON 的字符串和键名使用双引号,布尔值写成 true 或 false,数字端口不要写成带单位的文字。标准 JSON 不支持注释,也不允许最后一个成员后保留逗号。某些内核读取器可能接受扩展语法,但配置经过客户端导入、订阅转换或其他工具处理时,仍可能按严格 JSON 解析,因此手写文件宜保持标准格式。
顶层对象中同名键重复,是另一类隐蔽问题。部分解析器会保留最后一个值,部分工具会拒绝读取;无论哪种行为,都不适合用来叠加配置。例如写两个 routing 对象并不表示两组规则会自动合并。需要增加规则时,应修改同一个 rules 数组,并明确新规则在数组中的位置。
编辑入口决定修改能否保留
自动生成配置通常由客户端根据当前节点、路由预设和设置项重新组装。直接修改运行目录中的临时文件,可能只在当前启动周期生效;切换节点、更新订阅或重启服务后,文件便会被覆盖。长期使用的调整应写入客户端支持的自定义入口,或者保存为独立配置,再通过相应的自定义配置功能加载。
自定义配置也有边界。客户端界面显示的本地端口、路由模式或 DNS 选项,不一定能覆盖自定义文件中的字段。反过来,某些界面功能可能仍会生成外围运行参数。判断依据不是设置页是否勾选,而是当前内核最终读取的配置以及日志表现。首次切换配置模式,应暂停原连接,记录入口,再重新启动确认。
| 对象 | 主要职责 | 不负责的事项 |
|---|---|---|
inbounds | 接受应用连接 | 自动设置浏览器代理 |
outbounds | 定义出口和远程协议 | 决定全部路由顺序 |
routing | 为连接选择出口 | 修改系统 DNS 设置 |
dns | 提供内核域名解析配置 | 自动接管所有应用查询 |
不同内核共享部分字段名,不代表完整配置可以无条件互换。扩展协议、传输方式、DNS 选项和策略默认值都可能不同。迁移时应先保留入站、直连与阻断等基础部分,再逐项增加目标内核确认支持的能力。解析错误优先按字段路径处理,不要在尚未启动成功时同时更换服务器或订阅。
二、inbounds:本地监听与应用接入
监听地址和端口先于协议判断
入站描述内核从哪里接受连接。对单机使用而言,最先核对的字段是 listen 与 port:前者决定绑定的本地地址,后者决定应用需要连接的端口。配置写得正确,不代表端口一定能绑定成功;另一个客户端、旧内核进程或其他服务占用同一地址和端口时,启动仍会失败,日志通常会给出监听错误。
127.0.0.1 只供本机访问,适合作为默认选择。将监听地址改成 0.0.0.0 会扩大到所有 IPv4 网络接口,但是否能从其他设备访问,还取决于防火墙和网络环境。扩大监听范围不是修复本机连接问题的常规步骤。如果确实需要局域网接入,应同步考虑认证、允许来源和设备所在网络的可信程度。
SOCKS 与 HTTP 是不同的入口协议
SOCKS 入站适合能够明确填写 SOCKS 代理的应用,HTTP 入站则供读取 HTTP 代理设置的程序使用。应用设置中选择的协议必须与端口对应。把 HTTP 代理地址填到 SOCKS 端口,可能表现为连接刚建立就断开,而不是清晰的“协议不匹配”提示;因此不能仅凭端口能连通就判断应用接入正确。
{
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"tag": "local-http",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
]
}
示例提供两个独立入口,端口只是本文的配置选择,并非所有客户端固定使用的端口。实际操作应读取当前客户端的本地监听设置,再填写应用代理。浏览器的扩展设置、系统代理页面和终端环境变量也可能各自指向不同端口;排查时应记录正在测试的应用读取哪一处设置,避免只修改了未被使用的入口。
SOCKS 的 udp 表示允许相应的 UDP 接入能力,不意味着所有应用的 UDP 都会自动进入内核。应用本身需要支持并实际使用 SOCKS UDP,后续出站和网络路径也要能承载它。仅打开该字段,通常不能解决依赖系统级流量接管的场景。Android 的 VPN 接入与桌面应用手动填写本地代理,也不是同一种入口机制。
tag 与 sniffing 的作用范围
tag 是入站的逻辑名称,可供路由中的 inboundTag 引用。它不是监听端口,也不应通过更改标签期待连接方式发生变化。建议用能体现职责的名称,并保持唯一。若把 local-socks 改名为其他字符串,所有按该名称筛选连接的规则也要同步修改,否则相关规则会悄然失去匹配对象。
{
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
上面的对象属于单个入站内部。嗅探会尝试从受支持的初始流量中获取目标域名,例如 HTTP 主机信息或 TLS 握手中的服务器名称,辅助后续分流。它不等同于解密 HTTPS,也不能保证恢复每条连接的域名。数据没有相应特征、应用使用不同握手形式,或者连接尚未提供足够信息时,都可能无法得到预期结果。
嗅探相关选项在内核之间存在差异,某些选项还会影响目标地址是否被替换。不要为了让域名规则生效就一次开启所有字段。先确认应用是否已经向代理提交域名,再决定是否需要嗅探;如果原本已提交域名,问题更可能在规则顺序或出口选择。涉及仅用于路由的嗅探行为,应核对当前内核是否支持对应设置。
| 现象 | 优先检查 |
|---|---|
| 内核启动后立即退出 | 端口占用、监听地址是否存在、字段格式 |
| 内核正常但应用没有访问记录 | 应用代理来源、协议与端口是否对应 |
| 网页可用而部分应用失败 | 应用是否读取系统代理、是否使用 UDP |
验证入站时,先使用单一测试应用和单一入口,暂时关闭该应用自己的其他代理插件。若日志没有出现连接,先不要改远程出站;流量没有到达内核,服务器参数再准确也不会改善结果。更详细的浏览器与终端分离检查,可参阅系统代理不生效排查。
三、outbounds:出口标签与远程协议
出站是动作,不是规则
出站定义连接离开内核时采用的方式。常见类型包括直接连接目标的 freedom、拒绝连接的 blackhole,以及使用远程服务器的协议出站。路由负责挑选出站,出站负责执行转发;两者不能互相替代。创建一个名为 proxy 的出站,并不会让全部连接自动选择它,最终仍取决于默认出口和路由规则。
在常见传统配置中,未命中路由规则的连接会使用出站数组的第一项。因此数组顺序具有实际意义,不只是展示顺序。整理配置时若把 direct 移到首位,原本依赖首项代理的兜底行为就会改变。建议在编辑记录中写清默认出口,并在每次增加规则后,用未被规则覆盖的测试目标检查兜底路径。
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
]
}
该片段只有直连和阻断,适合用于理解出口选择,不包含远程服务。阻断出站可用于明确拒绝某类连接,但不应把“请求失败”一律视为远程网络故障。若路由误把目标送入 block,更换服务器并不能解决。排错时应先看连接实际选择了哪个标签,再观察该出口的拨号或握手信息。
远程字段需要成组核对
远程出站的协议、地址、端口、身份字段、传输方式与安全层是一组相互关联的参数。分享链接可以携带其中多数信息,但导入过程仍可能受格式差异影响。若导入后不通,应将客户端编辑页与原始提供信息逐项比较,尤其检查是否把传输路径、服务器名称或流控选项遗漏,而不是只看地址和端口。
下面是传统 VLESS 出站的结构教学示例。域名 example.com 与全零标识仅用于说明字段位置,并不对应可连接服务。实际远程配置应通过可信的服务配置导入;不要把示例身份字段或示例服务器名称用于日常连接,也不要把其他协议的用户字段直接搬进该对象。
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "example.com",
"port": 443,
"users": [
{
"id": "00000000-0000-0000-0000-000000000000",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "example.com"
}
}
}
encryption 的取值不能脱离协议解释。示例中的 none 是该 VLESS 结构使用的字段,不表示可以关闭外层 TLS 后仍获得同样的传输保护。VMess、Trojan 与 VLESS 的认证方式和字段层次不同,不能仅替换 protocol 就完成转换。协议选择的首要条件是与远程服务一致,其次才是本地内核是否支持。
标签引用与客户端更新边界
出站标签需要与路由中的 outboundTag 精确对应,包括大小写。把配置列表里的显示名称改成“代理”,不一定会改变内核出站标签;客户端可能始终生成固定标签。手写路由应以最终运行配置为依据。引用不存在的标签可能导致配置报错或转发失败,不宜依靠内核猜测目标出口。
订阅更新会刷新节点参数,手工改动的远程地址、用户标识或传输字段可能被覆盖。需要长期保留的独立条目,应先了解客户端复制配置和订阅归属的行为,再保存副本。分享链接与订阅地址的更新机制并不相同,可结合单节点分享链接与订阅地址的区别判断应在哪一层修改。
当基础连接已建立而某个目标仍失败,应保持当前远程参数不动,转而比较直连与代理的路由选择。只有日志显示拨号、认证或安全握手失败时,才优先回到出站字段。把“所有访问都失败”和“单一目标失败”分开记录,可以避免在局部路由问题上反复重建整条节点配置。
四、streamSettings:传输与安全层
把协议、传输与安全拆开阅读
阅读节点时应分清三层:代理协议定义双方如何认证和表达目标,传输层决定数据以何种连接形式承载,安全层处理握手与加密。protocol、streamSettings.network 和 streamSettings.security 分别处在这些不同位置。它们需要组合兼容,但不能因为远程端口是四百四十三就推断传输必定为 WebSocket 或安全方式必定为 TLS。
传输参数必须与远程入口一致。原本使用 TCP 的服务,不能只在客户端把 network 改成 ws 就获得 WebSocket 能力;反向代理是否转发相应请求、路径是否匹配、上游服务是否监听,都是服务侧条件。客户端只能使用已有的接入方式,不能通过本地字段替远程服务创建新的传输入口。
TLS 的域名与服务器地址
address 是拨号目标,serverName 是 TLS 握手使用的服务器名称,二者在某些部署中可能不同。证书验证通常要与有效的服务器名称匹配。若地址可以连接而 TLS 握手失败,应检查系统时间、服务器名称和证书状态,而不是先取消验证。忽略验证会改变信任边界,也容易掩盖原本应修复的配置错误。
{
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "example.com"
},
"wsSettings": {
"path": "/tunnel",
"headers": {
"Host": "example.com"
}
}
}
}
这是传输对象的教学片段,路径和域名不代表实际服务。path 应与服务端路由完全对应,前导斜杠和大小写都值得核对。HTTP 的 Host 与 TLS 的服务器名称处于不同阶段:前者参与 HTTP 请求路由,后者参与安全握手。某些部署要求两者相同,但不能因此认为修改一个字段会自动同步另一个。
路径还可能包含查询参数。通过文本复制配置时,注意完整保留原始内容;若分享链接把某段内容进行 URL 编码,客户端编辑页展示的可能是解码后的形式。排查时应比较语义和最终运行字段,不要把编码后的百分号序列与解码后的字符混为一谈,也不要重复编码导致远程服务看到不同路径。
| 阶段 | 典型字段 | 常见检查方向 |
|---|---|---|
| 目标拨号 | address、port | 地址解析、网络可达性 |
| 安全握手 | security、serverName | 名称匹配、时间、服务端配置 |
| 传输接入 | network、path | 传输类型、反向代理路径 |
| 协议认证 | 用户标识、协议专用字段 | 身份信息、协议与内核支持 |
REALITY 与流控不要混写
REALITY 属于 Xray 生态中的安全握手方案,不是一个可任意替换的代理协议名称。常见组合仍以 VLESS 作为协议,并在传输安全层配置相应字段。服务器名称、公开参数和短标识需要与服务端允许值对应;这些字段的命名也可能随内核演进发生变化,迁移配置时应采用当前内核文档中的写法。
XTLS Vision 的流控选项与 REALITY 不是同一字段,也不是所有传输都能随意搭配。是否填写 flow,必须由服务端协议组合与客户端实际内核共同决定。出现认证或流控相关错误时,先恢复服务提供的完整参数,再确认组合支持,避免把某篇文章中的局部字段叠加到另一种传输配置上。
需要理解两者的分工,可阅读REALITY 与 XTLS Vision 原理说明。实际排错仍以日志中的失败阶段为主:拨号失败先看地址,握手失败再看安全参数,接入路径不匹配再看传输设置。按阶段定位,比同时修改传输、端口和服务器名称更容易得出可靠结论。
五、routing:匹配顺序与分流边界
先确定默认出口,再添加例外
路由规则通常按数组顺序从前向后检查,第一条满足条件的规则决定连接去向。它不是按文字长度自动寻找“最具体规则”,也不会把多条结果综合评分。因此面向单个域名的例外一般应放在较宽泛的分类规则之前。编写分流前,先用一句话写出兜底策略,再按优先级列出例外,可以减少规则顺序反复调整。
同一条规则中,不同条件字段通常需要同时满足;同一个域名或 IP 列表中的多个项目则用于匹配其中任意一项。比如同时写 inboundTag 和 domain,表达的是来自指定入口且目标域名匹配,不是两组条件任选其一。这一区别很容易造成“单独测试都能匹配,合在一起却不命中”的现象。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": ["full:example.com"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:cn"],
"outboundTag": "direct"
}
]
}
}
示例仅展示路由片段,要求完整配置已经定义 direct 和 block,并安装可读取的域名及 IP 分类数据。若希望未命中连接交给代理,还需要将实际远程代理设为默认出站;本段本身没有创建代理。第一条把文档示例域名送入阻断出口,用于说明精确例外如何覆盖后面的通用策略。
域名形式与分类数据
full: 用于精确域名匹配,domain: 用于域名及其子域范围,regexp: 用于正则表达式。裸字符串可能采用关键词匹配语义,不宜凭直觉把它当作完整域名。需要匹配一个明确站点时,优先使用表达意图清楚的前缀,再通过实际连接记录验证;正则应保持简单,避免难以维护的宽泛表达式。
geosite 和 geoip 引用不同类型的数据:前者提供域名分类,后者提供 IP 范围。它们不是内核凭目标实时判断所属地区的能力。数据文件缺失、分类名称不存在、路径错误或资源过旧,都可能影响加载与匹配。客户端更新节点订阅,也不必然意味着这两类资源同步更新,应分别检查对应的资源管理入口。
domainStrategy 决定何时补做解析
AsIs 通常按连接现有目标形式匹配,不为路由额外把域名解析成 IP。IPIfNonMatch 会在域名未匹配适用规则时尝试解析,再检查 IP 规则;IPOnDemand 则在匹配过程需要 IP 条件时触发解析。不同内核对细节的实现应以对应文档为准,但三者共同影响的是路由阶段,而不是系统中所有域名查询。
启用解析后,某些连接会增加一次查询过程,也会受解析结果影响。若把宽泛的 IP 规则放在前面,可能改变原本希望依据域名分类的行为。排查时先检查内核收到的是域名还是 IP,再看规则顺序,最后看解析策略。只修改 domainStrategy 而不检查入口信息,往往不能解释为何同一站点在不同应用中走向不同出口。
| 误判 | 实际边界 |
|---|---|
| 域名规则能识别全部 IP 请求 | 需要入口提供域名或通过受支持的嗅探获得信息 |
| 路由模式会改变应用代理设置 | 规则只处理已经进入内核的连接 |
| 分类数据永远覆盖完整 | 分类是维护的数据集合,可能存在遗漏或变化 |
已有连接还可能继续使用调整前的路径,浏览器也会复用连接。修改规则后应重新建立测试连接,必要时重启被测应用,而不是只刷新页面。如果日志结果与预期不一致,先用单条精确域名规则验证入口和出口,再逐步恢复分类规则。完整的分流写法见geosite 与 geoip 路由规则实战。
六、dns:解析来源与连接路径
先确认是谁发起域名查询
配置内核 DNS,并不表示操作系统、浏览器和所有应用都会改用该配置。应用可能先在本地解析,再把 IP 交给代理;也可能把域名直接提交给 SOCKS 或 HTTP 入口,由后续环节处理。浏览器自身的安全 DNS、系统解析缓存和应用内解析库,都可能形成不同路径。排错的第一步是确认目标以域名还是 IP 的形式进入内核。
顶层 dns 为内核需要域名解析的功能提供服务,例如路由补做 IP 判断,以及某些出站策略的目标解析。它不是自动监听本机 DNS 端口的声明。若应用始终绕过内核独立查询,单独增加这个对象不会改变应用行为;需要通过客户端支持的接管方式或应用设置处理,不能把两种职责混为一谈。
基础服务器与查询策略
下面片段采用普通 DNS 服务器地址,并将查询策略限定为 IPv4。地址只是明确的示例选择,不代表所有网络环境都适合使用。测试时应选择当前网络可达、符合使用需求的解析服务;如果服务器本身不可达,调整域名路由不会让查询自动成功,也不应在缺少依据时不断堆叠更多服务器。
{
"dns": {
"hosts": {
"manual.example": "192.0.2.10"
},
"servers": [
"1.1.1.1",
"8.8.8.8"
],
"queryStrategy": "UseIPv4"
}
}
hosts 中的示例使用保留的文档地址,只用于说明静态映射,不应当作真实服务访问。静态映射适合受控测试,但会绕过正常地址更新;目标迁移后若忘记删除旧映射,可能长期指向失效地址。检查解析异常时,应把内核中的映射与系统 hosts 文件分开查看,两者不属于同一配置来源。
UseIPv4、UseIPv6 与 UseIP 用于控制内核查询的地址族倾向或范围。限制为 IPv4 可以帮助验证是否存在 IPv6 路径问题,但不是所有环境的永久最优配置。若目标只有 IPv6,强制 IPv4 自然无法得到可用地址;若网络完整支持双栈,则应根据实际连通性和业务需求决定,而不是固定照抄示例。
分域解析与回退要一起设计
传统配置可以用服务器对象为特定域名选择解析服务。需要注意,域名优先选择、未命中时的默认查询、查询失败后的回退,往往受多个字段共同影响。只写一个 domains 列表,未必意味着其他服务器永远不会参与。尤其在对解析路径有明确要求时,应阅读当前内核的回退选项,并验证失败场景而不只验证成功查询。
{
"dns": {
"servers": [
{
"address": "1.1.1.1",
"domains": ["domain:example.com"]
},
"8.8.8.8"
],
"queryStrategy": "UseIP"
}
}
示例表达的是域名选择关系,不承诺查询一定走代理。DNS 请求是否进入路由、采用直连还是受特定出口控制,取决于服务器地址形式、内核实现及相关设置。普通 UDP 查询、经 HTTPS 的查询和带本地处理语义的地址写法,可能具有不同路径。配置时要把“选择哪台解析服务器”和“怎样到达它”分开核对。
使用域名形式的加密 DNS 服务时,还要考虑引导解析。内核需要先知道解析服务本身的地址,才能连接该服务;若这一步又依赖同一个尚未建立的解析路径,就可能形成循环。服务器出站本身也是域名时,循环会更难辨认。应为启动阶段保留可解释的解析路径,并用日志确认服务地址先被成功解析。
| 字段位置 | 控制内容 |
|---|---|
dns.queryStrategy | 内核 DNS 查询的地址族策略 |
routing.domainStrategy | 路由匹配时是否需要把域名解析为 IP |
| 出站协议内部的解析策略 | 该出站如何处理目标域名,具体字段随协议和内核而异 |
修改后还需考虑缓存。应用、系统和内核可能分别保留解析结果,仅重启其中一个环节不一定立即改变行为。测试时记录查询对象、地址族和返回结果,重新建立连接,并区分“没有得到地址”与“得到地址但连接失败”。后者应继续检查路由及出口,不能因为涉及域名就始终归因于 DNS。
七、policy 与 log:连接策略和可观察性
策略级别不等于连接优先级
policy 用于配置连接处理策略及部分统计开关。常见传统结构通过 levels 按用户级别组织参数。这里的级别不是速度等级,也不是给某条连接分配更高带宽的承诺;只有协议和用户配置实际引用相应级别,相关策略才会作用到对应连接。没有使用的级别即使写得完整,也不代表运行中会自动启用。
不要把策略当作“通用加速参数”批量套用。握手时限、空闲超时、单向数据等待与缓冲设置解决的是不同问题。调小等待时间可能更快清理失效连接,也可能误伤较慢的握手或长时间无数据的应用。调大数值可能保留更多连接状态,却不能修复远程认证失败、DNS 解析失败或本地入口协议错误。
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5
}
}
}
}
示例使用级别零来展示结构,键名仍是字符串,内部各时间值采用相应字段约定的秒数。它是说明用参数集合,不代表所有网络的推荐组合。若当前内核默认策略已经满足需求,可以不写这一段。对没有测量依据的环境而言,减少自定义字段比复制大量来历不明的策略更便于后续维护。
超时字段需要结合连接状态
handshake 约束相应连接的握手等待,connIdle 关注连接处于空闲状态的时间,uplinkOnly 和 downlinkOnly 则对应一侧结束后另一方向继续处理的等待。具体适用协议与状态转换应查当前内核文档。它们不能简单理解成“访问网页最多等待几秒”,更不能代替应用自身的请求超时。
例如长连接在没有业务数据时,可能依赖应用心跳保持活跃。若空闲时限过短,会表现为连接周期性重建;这时应同时检查应用心跳、服务端超时和中间网络设备,而不是仅把客户端数值无限调大。修改前记录原始值,修改后测试空闲和持续传输两种情况,才能判断影响发生在哪个状态。
| 设置 | 应观察的现象 | 不应据此推断 |
|---|---|---|
| 握手等待 | 建立连接阶段是否过早终止 | 远程身份参数一定正确 |
| 空闲等待 | 无业务数据时连接是否重建 | 持续传输速度一定变化 |
| 统计开关 | 对应统计功能是否具备所需条件 | 客户端界面必然显示全部计数 |
日志级别与统计是两条配置线
日志用于解释发生了什么,统计用于汇总特定连接或用户的计数,两者并不是同一功能。某些统计能力除了策略开关,还需要顶层统计对象、受支持的协议标识以及相应的读取接口。仅开启一个 statsUserUplink 字段,不意味着图形客户端就会出现对应界面;客户端可能使用另一套采集路径,也可能根本不读取该统计项。
{
"log": {
"loglevel": "warning"
}
}
日常可以保留适度日志级别,排错时再按内核支持范围临时提高详细程度。warning 适合关注警告与错误,但不一定包含每条连接的完整去向;需要定位路由时,可能还需查看访问日志或客户端提供的连接记录。日志缺少成功连接信息,不等于流量没有经过内核,应先确认当前记录范围。
若指定日志文件路径,要检查目录是否存在、运行身份是否有写入权限,以及客户端是否允许该位置。桌面系统和 Android 应用的可写目录不同,不能直接复制另一平台的绝对路径。没有必要为了排错让服务获得更高权限;优先使用客户端现有日志窗口,导出确实需要的片段,再决定是否配置独立文件。
日志也可能包含目标域名、远程地址和认证相关上下文。共享前应按内容逐项隐藏敏感信息,保留错误类型、发生阶段及必要的字段路径。测试结束后恢复常规记录范围,避免持续积累大量文件。若需要进一步核对症状,可从FAQ 故障排查分类查找对应入口,而不是只根据一行警告重建全部配置。
八、整体验证、迁移与故障定位
按层验证,不以单次测速代替检查
完整验证应覆盖文件能否读取、内核能否启动、应用能否进入入站、连接选择哪个出口、远程握手是否完成,以及目标是否真正返回数据。客户端的测试功能通常只覆盖其中一部分。某次测试成功,不代表浏览器代理已经设置;测试失败,也不一定代表节点完全不可用,可能只是测试目标或测试方式与实际业务不同。
第一步只检查结构和启动。保存文件后,通过客户端的配置检查功能或启动日志确认解析结果,重点寻找对象层次、字段类型和不支持字段。出现错误时,从最早的一条有效错误开始处理;后续报错可能只是前一项失败的连锁结果。尚未启动成功前,不必更换 DNS 或路由分类,因为这些功能还没有进入运行阶段。
第二步验证入站。确认监听端口与应用设置一致,让单一应用发起新的请求,观察是否产生对应记录。若完全没有连接,检查系统代理、应用内代理与插件覆盖关系。桌面终端通常不会自动继承浏览器设置,Android 应用也可能受按应用代理范围影响。此时应先修复接入路径,而不是继续调整远程身份字段。
用最小闭环恢复可用状态
第三步验证出口。先保留一个明确的远程条目和简单路由,确认出口标签正确,再观察拨号、传输握手和认证阶段。每次只改一组相关参数,并重新建立连接。若本来可用的配置在加入分流后失败,应优先回退新增规则;若更换内核后才失败,应优先检查扩展字段与协议支持,不要同时怀疑所有网络条件。
第四步验证 DNS 与规则覆盖。分别选择一个精确域名规则、一个需要 IP 判断的目标和一个不命中规则的目标,确认三者去向。测试目标应来自实际使用需求,并记录预期出口;不要只看页面能否打开。连接成功但出口与设计不符,同样说明规则需要调整,否则后续业务可能在不同路径上暴露问题。
| 失败阶段 | 主要检查项 | 暂不改动 |
|---|---|---|
| 文件读取 | JSON 语法、对象层次、字段支持 | 服务器选择 |
| 本地接入 | 监听、端口、应用代理来源 | 远程传输路径 |
| 出口拨号 | 地址解析、端口、网络路径 | 策略超时集合 |
| 安全或协议握手 | 服务器名称、身份、传输组合 | 无关域名分类 |
| 部分目标失败 | 规则顺序、解析结果、目标状态 | 已经验证的基础入口 |
跨客户端迁移要验证最终产物
迁移不是把文件复制到另一设备后直接判定完成。先确认目标客户端实际运行的内核,再核对自定义配置入口、资源数据路径、日志路径和本地监听地址。桌面端可从 v2rayN 开始,Android 根据需求选择 v2rayNG 或 v2flyNG;对应安装入口见客户端页面,客户端职责差异见选型指南。
从分享链接或订阅转换成原生 JSON 时,导入成功只表示客户端接受了输入,并不证明每个扩展字段都被保留。应打开条目编辑页,检查协议、传输、安全层和流控,再查看最终运行配置。转换过程尤其要注意路径编码、缺失默认值和字段名称变化;相关格式边界可参阅订阅格式与原生 JSON 对比。
同一设备上并行运行多个客户端,也会干扰验证。它们可能争用端口,反复设置系统代理,或者留下仍在运行的内核进程。切换测试对象前,应先正常停止原连接,再确认新客户端接管了预期入口。不要仅通过关闭窗口判断服务已经退出,也不要在尚未记录现状时批量结束不明进程。
测试记录宜包括配置来源、当前内核、修改字段、发生时间、测试应用和错误阶段,不需要记录完整凭据。若无法确定问题来自哪层,回到第一章的直连基线,再逐项恢复远程出站、传输、路由和 DNS。每恢复一层都留一个可用副本,这样后续出现问题时可以回到最近的可靠状态,而不是重新从零拼接配置。