适合已经能导入节点、但还分不清配置字段作用的读者。先用一份只包含本地监听、直连与阻断的完整配置建立请求路径,再拆解端口、tag 和规则顺序,最后说明如何接入实际代理出站,以及怎样避免修改 v2rayN 临时生成文件后被覆盖。
1. config.json 的请求路径
config.json 是内核读取的配置文件,不等同于订阅链接,也不等同于客户端设置文件。订阅通常提供节点信息;客户端根据节点、路由和本地监听设置生成内核配置。理解这层关系,才能判断某个修改应放在节点编辑、路由设置,还是自定义配置中。
inbounds 回答“请求从哪里进入”,outbounds 回答“请求怎样离开”,routing 回答“这次请求选哪条出口”。浏览器必须先把请求送到本地代理端口,路由规则才有机会处理;只修改路由,不会自动让所有应用接入代理。
本文采用 V2Ray 常见的 JSON 配置结构。V2Fly 与 Xray 有共同字段,但协议能力、字段选项与命令行参数仍需按实际内核区分。v2rayNG 使用 Xray 内核,v2flyNG 使用 V2Fly 内核;v2rayN 桌面端则应先确认当前配置实际调用的内核,不能仅凭客户端名称判断。
2. 完整配置:双入站、直连与阻断
下面是一份结构完整的教学配置:SOCKS 监听 127.0.0.1:10808,HTTP 监听 127.0.0.1:10809。访问示例域名 example.org 及其子域名时阻断,其他请求默认直连。它不包含远程代理节点,因此不是可用于远程代理的节点配置。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "blocked",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": [
"domain:example.org"
],
"outboundTag": "blocked"
},
{
"type": "field",
"ip": [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"127.0.0.0/8",
"::1/128"
],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": [
"http-in"
],
"outboundTag": "direct"
}
]
}
}
这是严格 JSON:键名和字符串使用双引号,没有注释,也没有末尾多余逗号。数组可包含多个对象,但每个对象必须遵守对应协议的字段定义。不要把界面上显示的“节点名称”直接当成内核配置键,也不要给顶层随意增加一个 subscription 字段;订阅管理属于客户端功能。
3. inbounds:监听地址、端口与入站 tag
listen 是本机绑定地址,不是远程节点地址;port 是应用连接的本地端口,不是服务端端口。将监听限制为 127.0.0.1,表示只接受本机 IPv4 回环连接。改为所有网卡监听会扩大可访问范围,涉及局域网访问控制,不能当作连接失败时的通用修复方法。
SOCKS 入站
- protocol
socks- listen
127.0.0.1- port
10808- tag
socks-in
应用必须使用 SOCKS 协议接入;UDP 还取决于应用和后续出站链路。
HTTP 入站
- protocol
http- listen
127.0.0.1- port
10809- tag
http-in
HTTPS 目标通常通过 CONNECT 隧道访问,不需要把入站协议改为 https。
tag 是配置内部的标识。入站的 socks-in 可以被路由规则的 inboundTag 引用;它不会决定协议,也不会自动生成一个同名出站。建议每个入站和出站分别使用唯一、稳定的 tag,修改名称时同步检查所有引用。
示例中的 udp: true 仅表示 SOCKS 入站允许 UDP。应用需要支持 SOCKS UDP ASSOCIATE,出站也需要承载该流量;开启这一项并不等于系统全部 UDP 都会经过内核,更不等于普通 HTTP 系统代理可以捕获游戏流量。
4. outbounds:协议实现与默认出口
示例的 freedom 表示直连,blackhole 表示阻断;direct 和 blocked 只是人为指定的 tag。把 direct 改名为 office-direct 不会改变其行为,但所有引用它的 outboundTag 都必须一起修改。
| 字段或位置 | 示例值 | 实际作用 |
|---|---|---|
protocol | freedom | 选择直连出站实现 |
tag | direct | 供路由规则引用的标识 |
settings | {} | 该出站协议的配置对象 |
| 数组第一项 | direct | 没有规则命中时使用的默认出站 |
普通路由规则全部未命中时,内核使用 outbounds 数组的第一项。示例将直连放在首位,因此没有匹配到阻断或指定入站规则的流量仍会直连。若把阻断出站移动到首位,大量未命中请求就会被阻断;这不是“节点突然失效”,而是默认出口改变。
判断顺序:先找默认出口,再读例外规则
检查配置时先圈出 outbounds[0].tag,再逐条核对 routing.rules。这样能先确定未命中流量的去向,避免只盯着某一条域名规则而遗漏整体行为。
5. routing:顺序匹配、字段组合与域名解析
routing.rules 按数组顺序从上到下检查,第一条命中的规则决定出口,不会继续寻找“更精确”的后续规则。通常将具体例外放在前面,将范围更大的规则放在后面。如果第一条就是匹配全部 TCP 和 UDP 的出口规则,后面的域名规则便没有机会生效。
- 先查目标域名。当请求携带
example.org或其子域名时,第一条规则选择blocked。domain:匹配该域名及子域名;只匹配一个完整域名时可使用full:。 - 再查目标 IP。示例列出的私有地址和回环地址走
direct。这是地址段匹配,不会因为域名最终可能解析到私有地址就必然触发。 - 再查来源入站。第三条规则匹配来自
http-in的请求,并选择直连。但此前已命中域名阻断的请求不会再执行这一条。 - 最后使用默认出站。来自
socks-in、且未命中前两条的请求,使用数组第一项direct。
同一条规则中,不同条件字段通常需要同时满足。例如同时写入 inboundTag 和 domain,表示指定入站中的指定域名;同一个域名数组内的多个条目则是候选项。将“或”关系误写成一条含多个条件字段的规则,是分流不生效的常见原因。
domainStrategy 位于 routing 内,控制路由匹配阶段如何处理域名。AsIs 不为匹配 IP 规则而主动解析域名;IPIfNonMatch 在域名未匹配时尝试解析后再匹配;IPOnDemand 在匹配需要 IP 信息的规则时触发解析。它不是“所有 DNS 一律走代理”的开关。
6. 接入代理出站:先确认上游,再修改引用
远程代理需要真实的服务端参数。VMess、VLESS 等出站的地址、端口、身份信息和传输安全设置必须与服务端一致,不能只把 protocol 改一个名称便完成转换。对已有节点,优先通过客户端导入并检查生成配置,避免手动拼接不同内核的协议字段。
为了单独演示“新增出站再引用”的过程,下面使用一个本机 SOCKS 上游。前提是另一个独立服务确实监听 127.0.0.1:10810,并且不要求认证。此对象应加入 outbounds 数组;它只是配置片段,不是一份完整文件。
{
"tag": "proxy",
"protocol": "socks",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": 10810
}
]
}
}
- 仅添加该对象不会自动改变已有流量;还需要让规则的
outboundTag引用proxy,或将其作为首个出站承担未命中流量。 - 如果希望所有未命中请求使用上游,可把
proxy放在出站数组首位,同时保留必要的直连例外。示例原有的http-in直连规则也要按目标调整。 - 上游端口不能填回自己的
10808,否则可能形成回环。即使使用不同端口,上游也不能再把相同请求转回本实例。 - SOCKS 本身不提供传输加密。这里的回环上游只是结构教学;连接远程服务时,应按实际协议和网络边界设计传输方式。
7. 验证配置与 v2rayN 的保存位置
验证分成三层:JSON 能否解析、内核能否接受字段、真实请求是否符合规则。三层不能互相替代。文本格式正确并不表示引用的 tag 存在,内核启动成功也不表示系统代理已经指向正确端口。
- 备份原文件。保留一个能正常启动的副本,每次只修改一个类别,例如只改端口或只改路由,便于回退。
- 使用匹配内核检查。先运行随包内核的帮助命令,确认该版本的配置测试参数。测试工具必须与实际运行内核一致,不要用另一种内核的检查结果代替。
- 读取启动日志。若日志提示监听失败,先处理地址或端口;若提示配置加载失败,先核对字段类型和协议设置。定位问题时可临时将
loglevel改为info,排查后恢复。 - 发起两组明确请求。先验证直连出口,再验证阻断规则;测试时显式指定端口,避免混入其他应用的代理设置。
curl --proxy socks5h://127.0.0.1:10808 --connect-timeout 5 https://example.com/
curl --proxy socks5h://127.0.0.1:10808 --connect-timeout 5 https://example.org/
curl --proxy http://127.0.0.1:10809 --connect-timeout 5 https://example.com/
socks5h 要求把目标主机名交给代理处理,适合验证本例的域名规则。在外网可达的前提下,第一和第三条应通过直连出站尝试访问;第二条应被阻断。具体错误提示取决于内核与 curl 版本,不能仅凭某个错误码判定命中了哪条规则,应同时查看日志。Windows 若命令被终端别名接管,可显式运行 curl.exe。
在 v2rayN 中,先通过「设置」→「参数设置」核对本地监听端口,再通过「设置」→「路由设置」检查启用的路由配置;不同版本的分组或名称可能略有变化,以当前界面为准。普通节点运行时使用的配置往往由客户端重新生成,切换节点、更新订阅或重启内核后,直接修改生成文件的内容可能被覆盖。
保存位置:常用规则留在客户端设置
要长期保留端口与分流规则,应修改客户端对应设置;要完整控制一份 JSON,则使用客户端的自定义配置功能,并确认该条目调用的内核。不要同时维护一套界面规则和一份临时文件,再假设二者会自动合并。
8. 常见配置问题
节点已经选中了,为什么示例还是直连?
本例第一出站是 freedom,没有远程代理参数。客户端中选中节点,并不会自动改写一份独立运行的 JSON。先确认实际加载的文件,再检查 outbounds[0] 和命中规则的 outboundTag。
把 tag 改名后,规则为什么不工作了?
在文件中搜索旧 tag,逐个核对 outboundTag 与 inboundTag。引用需要与对应对象的 tag 完全一致,包括大小写。修改后重新测试并重启内核,不能只保存文本而继续使用旧进程。
开了系统代理,为什么某些应用仍不经过 10809?
系统代理只对遵循该设置的应用有效。先用上面的 HTTP 测试命令验证监听,再检查应用是否有独立代理设置。不要通过扩大监听地址来处理应用未使用代理的问题,两者属于不同层次。
能把订阅内容直接粘贴到 config.json 吗?
不能把任意订阅文本当成内核 JSON。先在 v2rayN 的订阅管理中导入并更新,确认节点协议与所选内核支持情况;需要研究结构时再查看客户端生成的配置,并注意隐藏地址和身份信息后再分享。
继续阅读字段定义时,可使用JSON 手册核对监听、出站与路由各段。实际排查仍按同一顺序进行:应用是否接入、入站是否监听、规则是否命中、出站是否能连接。每次只验证一层,比同时修改 DNS、端口与协议参数更容易找到原因。