适合已经导入过订阅、希望读懂内核运行配置的用户。先分清应用入口、连接出口和路由选择,再用一份仅含本地监听、直连与阻断的完整配置验证字段关系。读完可以定位端口冲突、标签写错、规则顺序失效,以及 DNS 设置改了却没有生效的原因。
先定边界:config.json 是内核配置,不是订阅列表
v2rayN 是桌面客户端,V2Ray 与 Xray 是处理连接的内核。客户端保存订阅、节点和界面设置,再按所选内核生成运行配置。因此,订阅里的一条 VMess 或 VLESS 分享链接,并不等于一份完整的 config.json:它通常只描述远端连接参数,缺少本地入口、日志、DNS 和分流规则。
本文采用 V2Ray 传统 JSON 配置结构,展示 V2Ray 与 Xray 中常见的字段关系。V2Ray v5 还提供另一套配置格式,不能仅凭文件扩展名判断格式,更不能把两套字段混在一起。具体协议和传输字段还要以实际运行的内核版本为准。
阅读时沿着这条链找问题。网页请求必须先进入某个入站,才有机会参与路由;路由选中的是出站标签,不是订阅分组名称。DNS 则为域名解析及部分路由判断提供支持,并不是所有流量必经的一个“代理出口”。
- 先看运行内核:确认客户端当前使用的是 Xray 还是 V2Ray,不要只看客户端窗口标题。
- 再看实际文件:启动日志中的配置路径,比在磁盘里搜索同名文件可靠。文件名可以不同,
config.json只是常见名称。 - 保留原始配置:客户端自动生成的文件可能在切换节点、更新订阅或重启时被覆盖;长期调整应通过客户端支持的设置或自定义配置入口完成。
log:先确定能看到什么,再调整连接参数
log 位于顶层,用于控制日志输出。排障时先用 info,问题解决后通常可改回 warning。直接开启 debug 容易产生大量细节,反而让一条简单的端口冲突淹没在输出里。
{
"log": {
"loglevel": "info"
}
}
这是字段片段,不是完整运行配置。常见日志级别包括 debug、info、warning、error 和 none。这里不设置日志文件路径,便于先从终端或客户端日志面板观察启动结果;若配置 access、error 文件,必须确认目标目录存在且运行账户可写。
address already in use:优先检查本地监听端口,不要先更换远端节点。permission denied:检查日志目录、配置文件和监听端口的访问权限。- 提示找不到出站标签:对照
routing.rules[].outboundTag与outbounds[].tag的拼写。 - 分享日志前,移除订阅地址、用户标识、服务端地址以及不希望公开的访问域名。
inbounds:应用从哪个地址、哪个端口进入
inbounds 是数组,一份配置可以同时接受 SOCKS 和 HTTP 代理请求。listen 指定监听地址,port 指定本地端口,protocol 决定应用应该用什么代理协议连接。它们不是远端节点的地址和端口。
以上是本文明确选用的端口,不代表所有客户端版本的默认值。若 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。
- VMess 出站:需要服务端地址、端口、用户标识及匹配的传输、安全参数,不能只填一个 UUID。
- VLESS 出站:服务端认证参数与传输安全设置必须对应;特定扩展能力还取决于所选内核。
- 订阅参数:应从有效订阅或服务端配置取得。不能把 HTTP 入站的
10809当作远端服务端口照抄。 - 数组顺序:把阻断出站放在第一项,可能让所有未命中规则的请求都被阻断。
结论:改出口前先确认标签指向的协议
排查“规则已命中但仍走本地网络”时,先找到对应出站的 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 行为、相关路由以及出站的域名解析策略。
- 先确认应用交付了什么:HTTP 代理的 CONNECT 请求通常携带域名;SOCKS 请求既可能携带域名,也可能携带应用已解析好的 IP。
- 再看路由是否解析:
routing.domainStrategy决定路由何时需要把域名转换为 IP。 - 最后看出口如何连接:
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,键名和字符串使用英文双引号,最后一项之后不要添加逗号,也不要把解释性注释复制进文件。
port是数字,所以写10808。udp是布尔值,所以写false,不是字符串"false"。inbounds、outbounds、rules都是数组,不能改成单个对象。tag是内部标识,不要在重命名后遗漏对应的outboundTag引用。
验证顺序:语法、启动、入站、路由分开检查
将完整示例保存为当前目录下的 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 和节点造成新的干扰。
- 连接被拒绝:核对进程是否启动、监听地址与端口是否一致。远端节点参数暂时不是排查重点。
- 入站有请求但出口不对:检查规则顺序、请求携带的是域名还是 IP,以及默认出站是否放错位置。
- 规则正确但连接失败:再检查解析结果、目标可达性、远端认证与传输安全参数。
- 重启后修改消失:确认修改的是手工维护配置,还是客户端生成的临时运行文件。使用客户端时,可按使用指南回到对应设置入口调整。
掌握这套结构后,再看 v2rayN 生成的配置会直接得多:先找入站端口,再找默认出口,接着读规则,最后检查 DNS 的实际参与位置。需要确认平台安装和内核准备步骤时,可继续查看完整文档,不必先把全部高级字段塞进一份文件。