适合已经导入节点、准备读懂内核配置的用户。先沿请求路径识别四个顶层字段,再拆读一份 VMess + WebSocket + TLS 示例,最后检查标签引用、规则顺序与 DNS。读完能判断该改入站、节点参数还是路由,而不是每次连接失败就把整份 JSON 重写一遍。
1. 配置文件与客户端设置:先分清对象
v2rayN、v2rayNG 是客户端,负责节点管理、订阅更新以及生成内核运行配置。v2rayNG 使用 Xray 内核;v2flyNG 使用 v2fly 内核。v2rayN 可以管理不同内核,但本文讨论的是 V2Ray/Xray 的传统 JSON 配置格式,不能把它当成所有内核通用的字段表。
这里的 config.json 指内核实际读取的配置,不是客户端保存窗口位置、订阅分组等信息的设置文件。文件名也不一定固定:判断依据是启动命令指定了哪个文件,以及内容有没有 inbounds、outbounds 等字段。客户端更新节点或重启内核时,自动生成的文件可能被覆盖。
inbounds:定义内核在哪里接收请求,例如本机 SOCKS 端口。outbounds:定义请求如何离开内核,例如代理节点、直接连接或阻断。routing:根据目标域名、IP、入站标签等条件,选择一个出站。dns:配置内置解析器;它不是自动接管系统 DNS 的开关。
2. 完整 JSON 示例:两个入站、三个出站
下面是用于拆读的完整结构。node.example.invalid 是明确的假域名,UUID 也是演示值,不能连接真实节点。示例使用传统 VMess 的 vnext 结构;真实地址、端口、UUID、传输路径和 TLS 名称必须以服务端配置为准。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": true
}
},
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "node.example.invalid",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000001",
"alterId": 0,
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "node.example.invalid"
},
"wsSettings": {
"path": "/ws",
"headers": {
"Host": "node.example.invalid"
}
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": ["full:blocked.example.invalid"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["full:localhost"],
"outboundTag": "direct"
}
]
},
"dns": {
"servers": ["223.5.5.5"]
}
}
这些端口是本文示例值,不是每个版本都固定使用的默认值。JSON 中的端口是数字,true 是布尔值,不能分别写成带引号的字符串。最后一个成员后面也不能加逗号;为便于验证,示例没有使用注释。
3. inbounds:监听地址、协议与嗅探
listen 决定接收连接的本地地址,port 决定端口,protocol 决定应用应该用什么代理协议访问它。SOCKS 客户端不能直接连 HTTP 入站,端口通了也不代表协议对了。应用手动配置时,示例对应 SOCKS5 的 127.0.0.1:10808,或 HTTP 代理的 127.0.0.1:10809。
SOCKS 入站
- tag
- socks-in
- listen
- 127.0.0.1
- port
- 10808
- protocol
- socks
- settings.udp
- true
仅监听本机;UDP 支持还要求应用使用 SOCKS5 UDP 转发。
HTTP 入站
- tag
- http-in
- listen
- 127.0.0.1
- port
- 10809
- protocol
- http
- settings
- 空对象
适合支持 HTTP 代理的应用;HTTPS 请求通常使用 CONNECT 隧道。
127.0.0.1 把入口限制在本机。改成 0.0.0.0 会监听所有 IPv4 网卡;示例 SOCKS 入站还使用 auth: "noauth",不能照搬后直接暴露到网络。需要共享代理时,应一起检查认证、防火墙和允许访问的来源。
sniffing 可从 HTTP Host 或 TLS 握手里的服务器名称识别目标域名,帮助域名规则匹配。routeOnly: true 表示嗅探得到的名称只用于路由判断,不用它替换原始连接目标。它不解密 HTTPS,也不保证任何流量都能得到域名;本例只在 SOCKS 入站启用了嗅探。
tag是配置内部的引用名称,不是显示给服务端的用户名。settings.udp: true不会把所有 UDP 自动抓进内核,更不等于开启了 TUN。- Android 客户端的 VPN 接管方式不能仅用这两个本地监听端口解释;本文示例主要用于理解手动代理入口。
4. outbounds:节点认证与传输层分别看
代理出站中,protocol: "vmess" 表示节点协议。settings.vnext 保存服务器列表,users 保存认证参数。id 是用户 UUID;alterId: 0 对应现代 VMess 的常用配置,不要拿旧教程里的非零值试运气。users[].security: "auto" 是 VMess 的加密选项,和 TLS 开关不是一回事。
| 字段 | 示例值 | 实际作用 |
|---|---|---|
vnext[].address | node.example.invalid | 内核连接的节点地址 |
vnext[].port | 443 | 服务端监听端口,不是本地入站端口 |
streamSettings.network | ws | 使用 WebSocket 传输 |
streamSettings.security | tls | 在传输层启用 TLS |
tlsSettings.serverName | node.example.invalid | TLS 服务器名称,通常用于 SNI 与证书名称验证 |
wsSettings.path | /ws | WebSocket 请求路径,需要与服务端对应 |
wsSettings.headers.Host | node.example.invalid | WebSocket 握手的 HTTP Host |
示例里地址、SNI 和 Host 相同,只是为了减少变量;真实配置中三者可以不同。连接一个 IP 地址时,TLS 仍可能要求指定域名。路径也必须完整匹配,/ws 与 /proxy 不是可以互换的装饰文本。
freedom 表示直连出站,blackhole 表示阻断出站。direct、block、proxy 则是本文选用的标签,名字可以更改,但所有 outboundTag 引用必须一起改。VLESS 出站的用户字段与 VMess 不完全相同,不能只把 protocol 换成 vless 就认为迁移完成。
判断:连接失败先核对两层参数
先比对地址、端口与 UUID,再比对 network、TLS 名称、Host 和 path。不要用关闭证书验证来替代修正 serverName;错误配置不会因为跳过检查就自动变成正确节点。
5. routing:规则顺序与默认出站
rules 按数组顺序检查,首条匹配的规则决定出站。示例先阻断一个演示域名,再让私有地址和 localhost 直连。没有规则匹配时,传统 V2Ray/Xray 配置使用 outbounds 数组中的第一个出站,因此这里默认走 proxy。这个默认行为与标签是否叫「proxy」无关。
- 确认标签:
outboundTag: "direct"必须能找到tag: "direct"的出站。 - 检查顺序:具体例外通常放在宽泛规则之前;末尾兜底规则一旦提前,会遮住后面的规则。
- 检查条件:同一条规则里不同字段通常需要同时满足;一个字段数组内的多个候选项通常按任一命中处理。
- 检查数据:
geoip:private依赖 GeoIP 数据文件可用,使用geosite条目时也要检查对应域名数据。
域名匹配语法有区别:full:example.com 只匹配完整域名,domain:example.com 匹配该域名及其子域名。没有前缀的字符串通常按关键词匹配,容易比预期覆盖更多目标。写精确例外时,优先把匹配范围写明白。
| domainStrategy | 解析时机 | 排查重点 |
|---|---|---|
AsIs | 路由判断不主动把域名解析为 IP | 域名请求不应指望自动命中 IP 规则 |
IPIfNonMatch | 域名未匹配规则时,再尝试解析并进行 IP 匹配 | 解析结果可能改变最终出站 |
IPOnDemand | 匹配过程需要 IP 条件时触发解析 | 检查解析开销及 DNS 返回结果 |
本例的 AsIs 特意保持判断过程简单。目标本来就是私有 IP 时,可以匹配私有地址规则;目标是某个解析到私有 IP 的域名时,却不保证命中该规则。内网域名应增加明确的直连域名规则,或在理解解析行为后调整策略。
6. dns:内置解析器不等于系统 DNS
dns.servers 指定内核内置解析器使用的服务器。本例只有 223.5.5.5 一个上游,方便说明结构,不代表已经实现了完整的 DNS 分流。应用可能在发请求前自行解析;系统、浏览器与内核各自的解析路径,需要分别检查。
- 应用传入域名:内核有机会用域名规则判断;若路由策略要求 IP,再调用内置 DNS 获取地址。
- 应用先解析再传入 IP:路由看到的可能只有 IP。嗅探能补充部分域名线索,但不能保证恢复全部请求。
- 直连出站解析:
freedom的域名策略也会影响解析方式;本例空设置不代表所有解析都会经过上述内置上游。 - 远端代理解析:域名通过代理协议送到服务端后,可能由服务端完成解析,具体取决于实际请求与配置。
因此,配置了 dns 并不能单独证明所有解析都按预期走代理。需要核对应用是否启用独立解析、路由的 domainStrategy、出站解析策略,以及 DNS 查询本身的可达性。特别是依赖域名才能连接的节点,别让解析节点域名的路径又依赖这个尚未建立的节点连接。
7. 从导出配置到排错:每次只改一个变量
排错时先保留一份能运行的配置,再检查内核版本和当前实际读取的文件。v2rayN 的「设置」→「参数设置」可以查看或调整本地监听相关参数,具体分页与选项名称会随版本变化。界面中的节点表单、路由设置与运行时 JSON 要相互对应,不能只盯着一个被客户端重新生成的文件。
- 检查语法:使用本地编辑器检查括号、逗号与类型。UUID、订阅地址及节点信息不应提交到公开的在线格式化服务。
- 检查内核兼容性:确认读取配置的是 V2Ray 还是 Xray。新字段和传输方式必须以当前内核支持范围为准。
- 检查入口:确认进程已经监听实际配置的端口。出现
address already in use时,先处理端口占用,不要先改节点 UUID。 - 检查出站:暂时减少规则变量,核对地址、认证和传输。超时、认证失败、TLS 错误需要按不同方向排查。
- 检查分流:增加一条范围明确的测试规则,观察请求是否选中了目标出站,再恢复完整规则集。
- 收回调试日志:必要时把
loglevel临时改成debug;完成后恢复warning,避免持续记录过多连接信息。
独立运行内核时,可使用其配置测试命令。下面针对当前采用子命令形式的 V2Ray/Xray 可执行文件,路径要替换为实际文件位置;旧版命令行参数可能不同,先查看本机 help 输出。
v2ray test -c config.json
xray run -test -config config.json
测试成功主要说明配置能被当前内核解析和加载,不代表节点在线、证书正确或所有规则都符合意图。最后还要用一个明确支持代理的应用发起真实请求。检查日志时重点找入站标签、目标地址和选中的出站;分享日志前移除认证信息与个人访问记录。
操作结论:按入口、出站、路由、DNS 分层验证
先证明请求进入正确端口,再证明代理节点可用,最后加入分流与解析策略。每一步留一个可恢复的配置副本,避免四层同时改动后只剩一句「还是不通」。