JSON 结构总览
V2Ray 生态中的配置文件描述一条完整的数据处理路径:应用连接本地监听端口,入站把请求交给内核,路由根据目标和来源选择出站,出站再建立实际连接。dns 提供内置解析能力,policy 控制部分连接阶段的时间限制。文件名常见为 config.json,但真正决定含义的是文件内容及加载它的内核,而不是文件名。阅读时先确认使用 Xray 还是 V2Fly,再对照该内核支持的配置格式。
对象、数组与字段类型
顶层是一个 JSON 对象。inbounds 和 outbounds 是数组,因为同一进程可以提供多个监听入口,也可以准备多个出口。routing、dns 和 policy 则是对象,各自在内部保存规则、服务器或策略映射。字段名和字符串使用英文双引号,端口通常使用数字,开关使用布尔值 true 或 false。数字与字符串不能随意互换;路径、标签和协议名称也需要保留准确拼写。
严格 JSON 不接受注释、尾随逗号或中文引号。部分内核工具可能提供额外的配置读取能力,但跨客户端传递时应保留严格 JSON。示例中的缩进用于阅读,不影响执行;括号、逗号和数据类型才影响解析。一个文件能够被 JSON 解析器读取,只证明语法成立,不能证明协议字段、出站引用或运行环境正确。遇到启动失败,应先区分语法错误和内核配置错误,避免同时改动多个层次。
下面是完整的本地 SOCKS 入口与直连出口示例。它用于理解数据路径,不包含远端代理连接。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": []
},
"dns": {
"servers": ["localhost"]
}
}
配置段之间的引用关系
tag 是配置内部的名称,不是显示给服务器的认证信息。路由规则中的 outboundTag 必须指向已有出站;inboundTag 可以限定规则只处理某个入口的请求。标签建议使用短而稳定的英文名称,并在各自数组中保持唯一。修改出站标签时,需要同时修改所有引用它的规则,否则文件看似完整,实际连接却可能无法按预期分发。默认出口通常是出站数组的第一项,因此排序本身也是配置行为的一部分。
顶层段落的书写先后不等于处理顺序。把 dns 写在 routing 前面,不会让所有请求先经过内置解析;把某条规则移到数组顶部,却确实可能改变匹配结果。查阅配置应把对象字段顺序与数组元素顺序分开理解。前者通常用于组织文本,后者在路由、出站默认选择等位置具有实际意义。合并两段配置前,也要确认它们没有重复的顶层键,重复键可能被读取器覆盖而难以察觉。
建议先保存一份能够启动的基线,然后按入站、出站、路由、DNS、策略的顺序逐项增加内容。每次增加一个配置段,就重新加载并观察日志。这样可以把错误限定在最近一次变更内,而不是在复杂文件里反复猜测。图形客户端生成的文件还可能包含辅助入口和内部标签,阅读时应先画出主要数据路径,再判断哪些部分由客户端自动维护。
inbounds 入站监听
inbounds 定义内核从哪里接收流量。本地客户端常用 SOCKS 或 HTTP 入口,应用通过对应代理协议访问该端口。入站并不等于远端服务器,也不负责决定最终走哪个代理出口。排查时,首先确认应用是否真的连接到这个入口:只有请求已经进入内核,后面的路由和出站设置才可能生效。浏览器使用系统代理,和某个程序单独填写 SOCKS 地址,是两条不同的接入方式。
监听地址、端口与协议
listen 决定监听哪个本机地址。个人设备上的本地代理优先绑定 127.0.0.1,让入口仅接受本机连接。绑定所有接口会扩大可访问范围,不能把它当作解决连接问题的通用方法。port 必须与应用端填写的端口一致,且不能被其他进程占用。protocol 决定客户端如何与入口对话,把 HTTP 请求交给 SOCKS 端口,通常会得到握手失败,而不是自动转换协议。
| 字段 | 作用 | 检查重点 |
|---|---|---|
tag | 入站标识 | 与路由中的来源标签一致 |
listen | 绑定地址 | 本机使用优先绑定回环地址 |
port | 监听端口 | 应用设置相同,端口未被占用 |
protocol | 入口协议 | 与应用代理类型对应 |
settings | 协议专属选项 | 不能在不同协议间直接照搬 |
sniffing | 流量目标识别选项 | 区分识别结果与原始连接目标 |
SOCKS 与 HTTP 入口的差别
SOCKS 入口适合显式支持 SOCKS 代理的应用。启用 settings.udp 只是允许入口处理 SOCKS UDP 转发,应用还必须使用相应协议,后续出口和远端链路也必须能够承载该流量。HTTP 入口通常用于支持 HTTP 代理或 CONNECT 的应用,不是一个任意 UDP 入口。系统代理开关只会影响遵循系统设置的程序,不能据此推断设备上所有连接都进入了内核。
{
"inbounds": [
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
]
}
这个片段只增加一个 HTTP 入口。若与前章基线组合,应把该对象追加到已有的 inbounds 数组中,而不是再写一个同名顶层键。端口号是示例约定,不是所有客户端固定使用的值。v2rayN 或 Android 客户端可能根据设置生成不同端口,因此实际操作应读取客户端当前配置。修改监听端口后,应用代理设置也要同步,否则旧连接仍会尝试访问原端口。
目标识别与接入边界
sniffing 可根据支持的流量特征提取域名,用于改善域名路由的可用信息。它不是解密所有流量的功能,也不能保证从任意连接恢复域名。目标覆盖、仅用于路由等选项在不同内核中的支持情况需要分别确认。初次定位问题时,可先保持客户端默认识别设置,确认普通请求能进入,再逐步判断域名信息是否影响分流,避免把入口错误和识别行为混在一起。
允许局域网访问时,需要同时考虑绑定地址、认证、主机防火墙和可信网络范围。只修改 listen 不代表其他设备就一定能访问,也不代表这个入口适合暴露到公网。对于个人本机使用,保留回环监听通常更容易控制边界。如果日志出现地址占用,应先停止旧客户端或改用空闲端口;如果完全没有接入记录,则检查应用代理地址、代理类型以及是否启用了绕过本地代理的规则。
TUN 接管与普通 SOCKS、HTTP 监听属于不同的接入层。客户端可以通过虚拟网卡把流量转交给内核,但虚拟网卡名称、权限申请和系统路由往往由客户端维护,不能简单归结为一个通用入站字段。相关操作见v2rayN TUN 模式设置笔记。查阅本节时,应先明确当前是在诊断应用代理入口,还是在诊断虚拟网卡接管链路。
outbounds 出站与默认出口
outbounds 保存内核可以使用的出口。出口可以直接连接目标、拒绝连接,也可以通过远端代理转发。路由规则最终选择的是某个出站标签,而不是订阅界面上的显示名称。客户端切换节点时,往往会重新生成代理出站的地址与认证参数,因此“选中节点”和“编辑出站 JSON”是同一条路径上的不同操作层。阅读导出的配置时,应确认选中节点对应哪个出站,以及哪些规则实际引用它。
协议配置与传输配置分层
protocol 指定出口使用的协议,settings 保存该协议需要的内容。对于 VMess 等远端协议,服务器地址、端口、用户标识等参数必须与服务端一致。streamSettings 则描述底层传输与安全层,例如使用何种传输方式、是否建立 TLS、采用哪个服务器名称。协议认证成功与传输建立成功是不同阶段,不能把所有失败都归为节点地址错误。
在界面里看到的服务器地址、TLS 服务器名称和 HTTP 类传输的 Host,可能具有不同职责。服务器地址用于定位连接端点,TLS 服务器名称参与握手和证书身份判断,传输层 Host 则属于相应协议的请求参数。它们有时相同,但不能因此强行统一。需要修改时,应依据服务端提供的连接资料逐项填写;随意关闭证书验证会掩盖身份与链路问题,不是合理的常规排错步骤。
直连、拒绝与代理出站
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
]
}
此片段使用 freedom 直接连接目标,用 blackhole 拒绝被分配到该出口的流量。第一项是直连,因此没有规则命中的请求会以直连作为默认选择。若将拒绝出口移到第一项,未命中规则的请求可能全部被拒绝。这里没有代理出口,不能用它检验远端代理是否可用。加入真实代理出站时,应明确默认流量应该走代理还是直连,再安排数组顺序或末尾兜底规则。
| 配置层 | 主要内容 | 典型错误 |
|---|---|---|
tag | 出口名称 | 路由引用不存在的标签 |
protocol | 出站协议 | 内核不支持所选协议 |
settings | 协议认证与目标参数 | 字段结构与协议不对应 |
streamSettings | 传输及安全层 | 传输类型、路径或服务器名称不一致 |
内核差异与连接能力
Xray 与 V2Fly 共享部分配置习惯,但不是可以任意互换的字段集合。同名功能也可能具有不同的取值、默认值或支持条件。尤其涉及新协议、传输、安全层和域名解析策略时,应以当前使用内核的能力为准。把一份配置交给另一个内核前,先检查协议和传输,再检查扩展字段;不要仅凭文件同样叫 config.json 就认定能够直接运行。
UDP 能否通过某个出站,需要整条链路共同支持。入口允许 UDP、出站协议具备相应承载能力、服务端允许转发,以及网络路径可达,缺少任意一环都可能失败。网页能够打开只说明相关 TCP 请求可用,不能代表语音、游戏或其他 UDP 应用已经具备同样的路径。遇到部分应用异常时,先判断其实际网络协议,再决定检查入口、出站还是远端转发设置。
首次配置建议由 v2rayN 的节点编辑或订阅导入功能生成远端出站,再对照本节阅读,不建议凭片段补齐认证信息。Android 端的 v2rayNG 与 v2flyNG 对应不同内核选择,相关边界见Xray 与 V2Fly 内核选型笔记。分享诊断材料时,只保留必要字段和错误类型,隐藏订阅地址、用户标识与其他认证内容,避免完整连接参数随日志扩散。
routing 路由规则与匹配顺序
routing 决定每个请求交给哪个出口。它处理的是已经进入内核的流量,不能代替操作系统路由,也不能让忽略代理设置的应用自动接入。最常见的结构是 rules 数组,每条字段规则检查请求的域名、IP、端口、网络类型或入站标签。规则从前向后检查,匹配后执行对应选择,因此一条过宽的规则可能遮住后面的精细规则。
规则条件如何组合
对于字段规则,同一个列表内的多个候选通常表示满足其中之一,例如一个 domain 数组可以列出多个域名;同一规则中不同条件字段则需要共同满足。例如同时填写 inboundTag 和 domain,表示来自指定入口且目标域名符合列表的请求。误把这种组合写成任选关系,会让规则比预期更窄。排查时可先只保留一个条件,确认命中后再逐项增加限制。
{
"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", "192.168.0.0/16"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "direct"
}
]
}
}
该片段可与前章的直连、拒绝出口组合。保留域名 blocked.example 仅用于展示精确匹配语法;其余未被拒绝的请求最终直连。末条规则是明确的兜底,不演示代理分流。若要改为代理兜底,应先存在真实代理出站,再将末条规则指向它的准确标签。把一个没有定义的 proxy 写进规则,不会自动创建可用出口。
域名、IP 与解析策略
full: 用于完整域名匹配,domain: 用于域名及其子域匹配;普通字符串与正则表达式各有不同语义,不能混用后凭表面文字判断范围。IP 条件可以使用单个地址或 CIDR 网段。使用地理分类数据时,还要确保运行环境具有对应数据文件,类别名存在,且更新来源可信。为便于隔离问题,最初测试应先使用明确的单个域名或地址,再引入大型分类集合。
domainStrategy 决定路由阶段如何使用域名解析。AsIs 保留请求现有目标信息;IPIfNonMatch 可在域名规则未能选出结果时尝试解析并继续 IP 匹配;IPOnDemand 则可在匹配需要 IP 信息时触发解析。具体执行边界仍应对照所用内核。选择策略时,应考虑解析开销、DNS 可达性和兜底规则的位置,不能认为更积极解析就必然更准确。
如果原始请求仅提供 IP,域名规则未必有机会命中。应用可能已经在系统侧完成解析,也可能通过自身的加密解析获取了地址;入口目标识别只能在支持的流量中补充部分域名信息。相反,域名请求也不一定立即具备可供 IP 规则使用的地址。诊断某条规则时,应从日志确认内核实际看到了什么目标,而不是仅根据浏览器地址栏推测。
规则维护与回归检查
建议把拒绝规则、特定业务规则、内网规则和兜底规则按明确层次组织。每次添加规则,都记录期望目标和期望出口,然后检查是否被更早的规则截获。对规则文件进行整理时,不要把排序当作纯粹的美化操作;移动位置可能直接改变行为。若客户端提供预设路由模式,应先确认预设会不会覆盖自定义列表,以及模式切换是否会重新生成整个配置段。
关于三个主要配置段的衔接,可继续阅读inbounds、outbounds 与 routing 逐段拆解。如果只是希望改变常用应用的接管范围,先在客户端确认系统代理或 TUN 状态,再编辑内核分流。应用尚未接入时,增加更多域名规则不会改变它的实际连接路径。
dns 解析服务器与域名分流
dns 配置内核的内置解析器,但不自动接管设备上所有 DNS 请求。系统解析、应用自己的解析、内核为路由执行的解析,以及远端出口侧的解析,可能同时存在。阅读配置之前,先问清是哪一层需要地址结果。应用已经传入 IP 时,修改内置服务器不一定改变该连接;路由需要把域名转换成 IP 时,内置解析器才可能直接影响规则选择。
servers 列表与服务器对象
servers 可以使用简单服务器条目,也可以使用带有域名范围等条件的服务器对象。localhost 表示使用本机系统解析路径,适合建立最小诊断基线,但结果仍受系统 DNS、网络和本机设置影响。填写一个公共解析地址,只是指定查询目标,并不能保证查询一定走代理或结果一定满足预期。是否能访问该服务器,以及查询如何发出,都需要结合具体内核和相关路由设置判断。
{
"dns": {
"servers": [
{
"address": "1.1.1.1",
"port": 53,
"domains": ["domain:example.com"],
"expectIPs": ["93.184.216.0/24"]
},
"localhost"
]
}
}
这里用保留示例域名展示限定查询与结果筛选。expectIPs 中的地址段只是筛选语法示例,不代表该域名当前应返回这个网段;域名地址会变化,照抄可能造成筛选失败。实际部署前应根据自己管理的解析范围填写,不能确定预期地址时先移除该条件。此示例也没有声称首个服务器的查询会走代理,诊断时应单独检查查询路径。
domains、expectIPs 与回退
domains 用于描述某个服务器优先处理的域名范围,不应简单理解为路由的最终出口选择。expectIPs 则对解析结果施加期望范围,帮助识别与预期不符的地址;它不是一个凭空修正解析答案的功能。过窄或过时的地址范围可能拒绝合法结果,使原本可以访问的域名解析失败。配置这类条件之前,需要明确域名的实际托管方式以及地址是否稳定。
匹配服务器、非匹配服务器和查询失败后的回退行为,会受到所用内核及相关开关影响。不要仅凭服务器在数组中的位置,认定所有查询都严格串行执行。需要禁止某个服务器参与普通回退时,应先核实该内核对应字段的意义,再做局部测试。对于复杂分流,先分别验证各服务器能够解析目标域名,再把它们放入同一个策略中,比一次堆叠多个限制更容易定位问题。
| 现象 | 优先检查 | 容易混淆的层次 |
|---|---|---|
| 所有域名解析失败 | 解析服务器可达性与查询路径 | 内置 DNS 与系统 DNS |
| 只有部分域名失败 | 域名条件和结果筛选范围 | 解析筛选与连接拒绝 |
| 改配置后结果不变 | 缓存、重载和应用自身解析 | 旧连接与新查询 |
| 域名可用但地址直连异常 | 出口选择和目标服务要求 | 解析成功与服务可达 |
解析循环、缓存与地址族
使用加密 DNS 端点时,端点主机名本身也可能需要解析。如果解析这个主机名又依赖尚未建立的同一条解析链,就会出现启动依赖循环。解决时应先梳理引导解析与查询传输的出口,而不是连续更换服务器名称。不同内核对本地查询、远端查询和 DNS 路由标签的支持不同,跨内核迁移时尤其要重新核对,不能把传输方式名称当作完整行为说明。
还应区分 IPv4 与 IPv6 结果。获得 IPv6 地址并不代表当前出口具备可用的 IPv6 路径;只查 IPv4 也不一定适合所有网络。测试时记录解析结果的地址族,并与实际连接失败的地址对应。修改 DNS 后,应重新加载配置并建立新连接;操作系统、应用和内核可能各有缓存,旧结果仍可在短时间内影响观察。不要仅刷新页面一次就判断配置未生效。
DNS 的目标是让解析位置、查询路径和连接出口保持一致,而不是单纯增加服务器数量。需要按域名范围拆分解析时,可对照DNS 分流解析设置笔记逐项检查。保留少量已验证的规则,并为每条规则说明适用范围,比维护没有测试依据的长列表更稳妥。
policy 连接阶段与用户等级
policy 不是路由规则,也不是客户端的全局接管模式。它主要为连接阶段、空闲状态和部分统计行为提供策略。最容易误解的是把策略中的时间限制当作网络加速参数:缩短等待时间通常只是让失败更快显现,并不会减少真实链路延迟;过于激进的限制还可能中断本来能够恢复的连接。没有明确问题时,应优先保留内核默认值。
levels 与 level 的对应关系
levels 使用用户等级作为键,每个等级包含一组策略。由于 JSON 对象的键必须是字符串,示例写作 "0",而在支持用户等级的协议用户对象中,level 通常是数字。两者是关联关系,不是同一个字段。定义了一个等级,并不意味着所有连接都会自动采用它;是否生效取决于相关协议是否产生对应用户上下文,以及该用户使用哪个等级。
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5
}
}
}
}
这个片段只展示策略对象的结构,数值单位为秒,不代表适合所有网络的推荐值。它不会创建用户、出站或监听入口,也不能保证任意协议都应用这些限制。若客户端没有暴露相关用户等级设置,应先确认生成配置中的实际映射,再考虑修改。尤其不能把 levels 当作节点优先级列表,数字越大并不代表节点越快或拥有更高的路由优先权。
握手、空闲与单向连接
handshake 控制相关连接建立阶段允许等待的时间。某些网络存在较慢的认证或握手过程,设置过短可能导致持续重试。connIdle 描述连接没有数据活动时的空闲限制,但实际行为还会受到协议、应用保活以及中间网络设备影响。即使内核允许较长空闲,路由器或远端服务也可能提前关闭连接,因此单独延长这个值无法保证长连接一直存在。
uplinkOnly 与 downlinkOnly 用于一侧数据流结束后的剩余等待阶段,不是上传和下载速度上限。这里的上下行以连接处理方向理解,不能按网速测试界面的含义套用。某些应用会先结束发送,再等待服务端返回结果;把剩余等待压得过短,可能使响应在到达前被关闭。分析这类问题时,需要结合连接何时半关闭,而不是只看页面是否报超时。
| 字段 | 关注阶段 | 不应当作 |
|---|---|---|
handshake | 连接握手等待 | 降低物理延迟的开关 |
connIdle | 无数据活动时的空闲 | 固定的连接存活保证 |
uplinkOnly | 仅剩上行阶段 | 上传速度限制 |
downlinkOnly | 仅剩下行阶段 | 下载速度限制 |
统计开关与客户端展示
部分策略可以控制用户或系统级流量统计,但开启策略字段本身不一定形成完整的统计链路。内核可能还需要统计模块、管理接口及客户端读取逻辑;用户统计也可能依赖协议用户标识。界面能显示流量,不代表所有统计都来自 policy;界面没有数据,也不能直接断定连接没有经过内核。排查统计问题应与排查连接问题分开,先确认请求能被正常处理。
不需要远程管理时,不应为了显示统计而随意开放管理监听。若客户端已经维护内部接口,保持其默认访问范围,并确认自定义配置没有覆盖相关入口。不同内核在统计字段、内存相关选项和默认策略上存在差异,复制一段包含许多扩展字段的策略,可能只是增加无法启动的风险。应逐项核对用途,删除自己无法解释且没有实际需求的设置。
回归测试至少包含短请求、持续传输和空闲后恢复三种情况。一次普通网页访问不足以说明策略适合长连接。记录修改前后的字段值、实际等待过程与错误类型,若没有稳定改善就恢复默认。这种小范围调整比同时改变握手、空闲和多种客户端开关更容易形成可验证的结论。
客户端生成配置与重载流程
图形客户端保存的设置,不完全等同于内核最终读取的 JSON。订阅分组、节点备注、界面主题、系统代理和自动启动等,通常属于客户端层;入站、出站、路由和 DNS 则可能由客户端根据这些设置生成。直接编辑运行目录中的文件,有时会在下一次启动或切换节点时被覆盖。修改前先确认配置来源,才能决定应该在界面中调整,还是使用客户端明确提供的自定义配置入口。
订阅、节点与完整配置的区别
订阅通常提供多个连接条目及相关信息,客户端负责解析、保存并生成出站。节点分享内容主要描述单个远端连接,不一定包含本地监听和完整路由。完整内核配置则需要描述运行所需的各个部分。把节点字符串保存成 config.json 并不会自动变成 JSON 配置;把一个只有 dns 的片段导入“完整配置”,也可能缺少必要入口和出口。应使用与内容类型对应的导入功能。
v2rayN 适合桌面环境的节点管理与配置查阅。Android 端优先根据内核需求选择 v2rayNG,已有 V2Fly 配置需求时再考虑 v2flyNG。三款客户端的菜单名称和支持字段不必完全一致,不能把某一款的界面路径写成通用内核规范。下载入口与平台选择见客户端页面;首次导入到连接验证的连续操作见入门指南。
| 设置 | 主要归属 | 检查位置 |
|---|---|---|
| 订阅更新与分组 | 客户端 | 订阅管理界面 |
| 系统代理状态 | 客户端与操作系统 | 客户端开关及系统设置 |
| 虚拟网卡接管 | 客户端接入层 | TUN、权限及系统路由 |
| 出站与路由字段 | 内核 | 实际生成或载入的配置 |
| DNS 服务器策略 | 内核与客户端模板 | DNS 界面及运行配置 |
变更前保存可恢复状态
先记录当前客户端、操作系统、选用内核、接管方式和可复现的问题。保存已有设置或导出必要配置,并把订阅地址与认证内容作为敏感资料单独保管。诊断备份不应随意上传到公开位置。若只想测试一个 DNS 规则,保留节点和路由不变;若要更换内核,则暂时不要同时更新订阅和调整传输。单变量变更可以让失败原因更明确,也便于回滚。
使用自定义配置时,要确认客户端是否仍会补充内部入口、统计设置或路由内容。有的入口读取完整配置,有的入口只是覆盖特定字段,两者合并方式不同。最可靠的检查对象是最终交给内核的运行配置,而不是编辑窗口里的局部文本。若导出功能只提供节点信息,则不能把它当作整个运行配置的快照;应同时对照当前模式和全局设置。
保存、加载与新建连接
- 先检查 JSON 语法及标签引用,确认修改只涉及计划中的配置段。
- 在客户端保存设置,使用其提供的重新加载、重启服务或重新连接操作。
- 观察启动日志,确认新内核进程成功加载,监听端口没有占用错误。
- 重新建立测试连接,检查请求是否进入预期入口并选择预期出口。
- 如果结果不符,恢复上一步配置,确认基线仍可使用,再分析差异。
保存不一定代表已加载,加载也不一定让旧连接立即迁移到新出口。浏览器和其他应用可能复用已有连接,DNS 也可能命中缓存。因此测试路由变更时,应建立新的请求会话,必要时关闭应用后重试,而不是仅在原页面继续操作。客户端日志应显示与本次测试时间相对应的事件,否则看到的可能是旧连接活动。
Windows、macOS 与 Linux 的系统代理遵循方式和后台运行机制不同,不能只依靠相同按钮名称推断效果。Linux 桌面自启动还可能受桌面会话和安装方式影响,可参考Linux 安装与自启动笔记。Android 的系统 VPN 授权、应用分流和后台限制也属于接入环境,应与 JSON 路由分别检查。
最后确认恢复路径:保留可用节点、原始模式和修改前设置,不让诊断变更直接替代日常配置。若客户端更新后某个字段不再被接受,先恢复生成配置的默认模板,再核对内核支持情况。不要通过不断叠加旧字段维持一个难以解释的配置文件;能明确说明每个自定义字段的用途,才便于后续维护。
配置验证与故障定位顺序
配置排错应沿数据路径逐层推进:先确认文件能够加载,再确认入口接到请求,然后确认路由选中正确出口,最后检查解析、握手和目标响应。一次只验证一个判断。直接更换节点、DNS、路由和超时参数,可能偶然恢复连接,却无法说明是哪项修改有效。保留一组稳定的测试目标、相同接入方式和对应日志,才能比较修改前后的实际差异。
启动失败:先读第一条错误
文件不能加载时,优先查看最早出现的明确错误,而不是后续连锁退出信息。括号或逗号错误属于 JSON 语法;未知协议、字段类型不符或必要参数缺失属于配置语义;地址占用、权限不足和文件路径不可读属于运行环境。三类问题的处理位置不同。编辑器显示语法正确后,仍需要让实际选用的内核验证,不能拿另一个内核的成功结果代替。
若错误指向某个配置段,先恢复该段最近一次变更。对于合并文件,检查是否出现重复顶层键、数组被错误替换或数字变成字符串。端口占用则检查是否同时启动了多个客户端实例,停止旧实例后再试。权限问题应确认具体资源与操作,例如创建虚拟网卡需要的权限不同于监听本地高位端口;不应因为普通配置错误就让所有操作长期以更高权限运行。
能启动但不能连接:逐段缩小范围
入口没有任何请求时,检查应用代理地址、端口、类型和系统代理是否生效。入口有请求但出口不对时,检查规则顺序、目标是否带有域名以及标签引用。出口正确但连接失败时,再看域名解析、远端可达性、认证与传输参数。若只有某个目标失败,还应考虑目标服务自身状态,不要据此直接推断整份配置损坏。内网资源异常则先检查是否被兜底规则送到了不合适的出口。
| 观察结果 | 下一步 | 暂不优先修改 |
|---|---|---|
| 内核未成功启动 | 语法、字段与监听错误 | 目标域名路由列表 |
| 应用请求未进入入口 | 应用及系统接入设置 | 远端协议认证参数 |
| 路由选错出口 | 规则顺序与实际目标信息 | 连接空闲时间 |
| 出口握手失败 | 协议、传输和安全层参数 | 本地分类规则数量 |
| 仅 UDP 应用异常 | 入口与整条链路的 UDP 支持 | 网页缓存设置 |
日志级别与最小复现
诊断阶段可以临时提高日志详细程度,以便观察入站、路由和连接错误。日志可能包含目标域名、地址和使用行为,收集时应控制范围,问题结束后恢复日常级别。分享日志前隐藏敏感连接信息,只保留足以说明错误的数据。不要把完整订阅或认证字段贴进求助文本;多数配置问题可以通过字段结构、错误类型和经过处理的目标信息说明。
{
"log": {
"loglevel": "info"
}
}
这个片段只调整日志级别。实际日志位置可能由客户端接管,未填写文件路径时应在客户端日志界面查阅。提高级别后,重新发起一次目标请求,记录相邻事件,再恢复原级别。不要长时间收集所有应用活动来寻找单个错误。若信息级别仍无法区分阶段,再根据内核支持情况使用更详细级别,并缩短收集窗口。
最小复现可以从本页第一章的直连基线开始,确认本地入口及一般网络可用,再恢复真实代理出站。基线直连成功并不能证明代理链路正常,它只排除了部分本地接入问题。之后按顺序恢复路由、DNS 和策略,每一步都重新加载并建立新连接。对于不适合直连测试的业务,不应强行更改访问路径,可改用自己管理的测试目标验证相同配置阶段。
常见问题与查阅入口
JSON 能解析,为什么内核仍然启动失败?
JSON 解析只检查文本结构。内核还会检查协议名称、字段类型、必要参数和运行资源。先读取第一条明确错误,再按对应配置段或端口、权限等环境因素处理。
修改 routing 后为什么仍然走旧出口?
确认保存后已重载,且客户端没有覆盖自定义规则。然后建立新连接,检查更早规则是否已命中,以及内核实际看到的是域名还是 IP。旧连接可能继续使用原出口。
配置了 dns,为什么应用还是使用系统解析?
内置 DNS 不会自动替代所有应用的解析。应用可能在接入前已经得到 IP,也可能使用自己的解析方式。先确认查询发起方和请求进入内核时的目标形式,再调整解析策略。
本页承担字段参考与分层诊断,首次操作仍以入门指南为主线;协议和生态名词可查名词解释。排错结束后,应保留一份简短变更记录:修改了哪个配置段、观察到什么结果、是否需要重载,以及怎样恢复。可解释、可复现、可恢复,比堆叠更多参数更有维护价值。