配置字段

V2Ray 配置文件参考大全

从 JSON 顶层结构开始,逐段查阅入站、出站、传输层、路由、DNS、策略与日志字段,理解流量如何进入核心、完成匹配并选择出口。

文档定位

快速操作与系统查阅分开使用

使用文档按“导入订阅、选择服务器、启用系统代理、验证连接”的顺序完成基础操作;本页用于理解客户端生成的配置以及手工检查字段关系。初次使用可先走完快速上手流程,遇到路由、解析或启动问题时,再回到对应章节逐项核对。需要重新选择客户端或安装包时,前往安装包页面

章节目录

按流量处理顺序查阅

完整配置通常遵循“入站接收、路由判定、DNS 解析、出站发送”的处理链。目录顺序兼顾字段层级与实际排错路径。

01 / CONFIG

JSON 结构总览:先确认对象层级与处理链

顶层对象负责什么

V2Ray 配置文件是一个 JSON 对象。常见顶层字段包括 logdnsinboundsoutboundsroutingpolicystats。这些字段不是按文件书写顺序依次执行,而是在核心启动时分别解析成对应模块。把 routing 写在 inbounds 前面不会改变实际处理顺序;真正决定流量去向的是入站标签、路由条件、出站标签以及模块间的引用关系。阅读配置时,应当先找出所有 tag,再沿着引用关系检查,而不是仅从第一行顺序读到末尾。

inboundsoutbounds 都是数组,因为同一个核心可以同时监听多个本地端口,也可以准备多个出口。routing.rules 同样是数组,规则通常自上而下匹配。与之不同,dnslogpolicy 一般是对象,它们分别描述一组解析行为、日志行为和会话策略。字段的数据类型必须准确:数组使用方括号,对象使用花括号,布尔值写成 truefalse,不能写成带引号的字符串。

一份最小结构如何建立

下面的骨架包含一个 SOCKS 入站、一个直接连接出站和一条基础路由规则。它适合用来理解层级,不代表完整的远程服务器配置。SOCKS 请求进入本地监听端口后,路由模块检查目标地址;命中私有地址规则时交给 direct 出站。未命中的流量也会使用可用的默认出站,因此生产配置通常还会明确准备主要代理出口,并用规则区分直接连接、代理和阻断三类结果。

{
  "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"]
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      }
    ]
  }
}

JSON 语法与语义错误要分开

语法错误发生在核心还不能理解文件时,常见原因是尾随逗号、缺少引号、括号不成对或把注释写进标准 JSON。JSON 本身不接受 ///* */ 注释;如果客户端界面允许注释,通常是客户端保存前做了额外转换,不能据此判断核心直接读取的文件也支持相同写法。语义错误则是 JSON 可以解析,但字段组合不成立,例如路由规则引用不存在的 outboundTag、端口写成字符串、协议名与 settings 结构不匹配。

客户端生成配置时还会加入运行目录、资源文件位置和核心差异相关字段。v2rayN 适合管理 Windows、macOS 与 Linux 桌面配置,v2rayNG 和 v2flyNG 分别用于 Android 环境中的不同内核路线。图形客户端中的订阅条目并不等于最终运行配置:客户端通常会把节点参数、本地监听设置、路由规则和 DNS 选项合并后,再交给核心。因此,排错时应优先查看客户端实际生成或导出的运行配置,不能只检查订阅链接里的单个节点参数。

tag 是模块之间的连接点

tag 可以理解为配置内部的稳定名称。入站标签供路由规则的 inboundTag 引用,出站标签供 outboundTagbalancerTag 引用,DNS 服务器也可以通过标签与特定出站建立关系。标签区分大小写,改名后必须同步修改所有引用位置。建议使用含义明确的短名称,例如 socks-inproxydirectblock,不要把服务器地址或经常变化的备注直接当作标签。

排查整份配置时可以画出一条简单链路:应用连接哪个本地端口,该端口属于哪个入站标签,路由规则根据哪些域名、IP、端口或协议匹配,命中后转到哪个出站标签,出站再使用哪种协议和传输方式。只要链路中的每个引用都能落到真实对象,结构层面的多数问题就能被发现。后续章节会按这条链路拆开说明每个模块。

02 / INBOUNDS

inbounds 入站:定义本地流量如何进入核心

监听地址、端口和协议

入站负责接收来自浏览器、系统代理、局域网设备或其他程序的连接。一个入站对象通常至少包含 taglistenportprotocolsettingslisten 决定绑定到哪个网络接口。桌面客户端仅供本机使用时,优先监听 127.0.0.1,这样局域网中的其他设备不能直接访问该端口。确实需要共享给局域网时,才考虑监听所有接口,并同时检查系统防火墙、访问控制与 SOCKS 认证设置。

port 是整数,必须避免与其他程序重复。v2rayN 常见的本地 SOCKS 与 HTTP 端口由客户端设置生成,手工配置时不应假设某个端口必然空闲。核心提示地址已被使用时,应先确认是否有另一个客户端实例仍在运行,再决定关闭冲突程序或修改监听端口。相关定位步骤可参阅v2rayN 端口被占用启动失败排查

protocol 决定入站协议结构。本地常见选择是 sockshttp。SOCKS 入站适合支持 SOCKS5 的程序,并可按配置转发 UDP;HTTP 入站适合使用 HTTP 代理设置的应用。透明代理、端口转发等场景涉及系统网络栈与额外权限,不应在基础配置中随意开启。先让明确配置了代理地址的应用成功连接,再逐步扩展接管范围,排错路径会更清楚。

同时提供 SOCKS 与 HTTP 入站

{
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      }
    },
    {
      "tag": "http-in",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ]
}

两个入站必须使用不同端口。应用选择 SOCKS5 时填写 127.0.0.1:10808,选择 HTTP 代理时填写 127.0.0.1:10809。如果操作系统只允许填写一个代理端口,应按客户端的系统代理模式使用其生成值,不要把 SOCKS 端口误填到只接受 HTTP 代理的输入框。端口能够建立 TCP 连接,只能说明本地监听存在,并不能证明远端出站、DNS 与路由全部正确。

流量嗅探的用途与边界

sniffing.enabled 开启后,核心可以从部分连接的应用层信息中恢复目标域名。destOverride 中常见的 httptls 表示允许使用 HTTP Host 或 TLS 握手中的服务器名称覆盖原始目标。这样做有助于域名路由:即使应用先解析出 IP,路由模块仍可能获得域名并匹配 geosite 或完整域名规则。

嗅探不是解密网页内容,也不是所有连接都能恢复域名。没有可识别主机信息的协议仍会保留原始目标;某些应用对目标地址变化敏感,启用覆盖后可能出现与预期不同的连接行为。排查单个应用异常时,可以暂时关闭嗅探进行对照。如果关闭后恢复正常,应检查域名规则、DNS 结果和 destOverride 范围,而不是直接认定出站协议有问题。

UDP、认证和局域网访问

SOCKS 入站的 udp 决定是否接受 UDP 转发请求。开启该字段不代表所有出站传输都自动支持目标 UDP,也不代表应用一定通过 SOCKS 发送 UDP。需要同时确认应用行为、出站协议能力与路由规则。DNS 查询如果交给核心内置 DNS,处理路径又与应用直接向外发送 UDP 查询不同,应分别判断。

监听范围扩大到局域网后,不宜继续把访问控制当作默认本机环境处理。SOCKS 可通过 auth 和账户列表建立用户名密码认证,但不同客户端对这些字段的图形化支持程度不同。更稳妥的做法是只开放确实需要的接口和防火墙来源地址,并确认移动设备不会把该端口暴露到不受信任的网络。若只在本机使用,保持回环地址监听最简单,也能减少端口误开放。

按入站来源进行路由

多个入站不仅用于适配不同代理协议,也可以承担分流入口。例如为日常应用建立 main-in,为需要直接连接的程序建立 direct-in,然后在路由规则中用 inboundTag 区分。此方式比频繁修改全局模式更明确,但要求应用能够分别指定代理端口。设计这类结构时,应把端口用途记录在配置旁,并确保标签不会在客户端重新生成配置时被覆盖。

入站排错可按四层检查:进程是否成功绑定端口,应用是否使用正确代理类型,入站是否接受对应 TCP 或 UDP 请求,嗅探与路由是否改变目标。只有前一层成立后才检查下一层。浏览器提示代理服务器无响应时,首先看监听与端口;核心日志已经出现连接记录但无法访问目标时,再转到出站、路由和 DNS 章节。

03 / OUTBOUNDS

outbounds 出站:定义代理、直连与阻断出口

默认出站与标签引用

出站对象描述核心如何把连接发送到下一跳或最终目标。常见配置至少准备三个逻辑出口:主要代理出口、直接连接出口和阻断出口。代理出口可以使用 VLESS、VMess、Trojan 等协议,具体参数来自服务端配置;直接连接通常使用 freedom;阻断通常使用 blackhole。三者分别配置清晰的 tag,再由路由规则通过 outboundTag 选择。

当路由规则没有命中时,核心会使用默认出站。不同内核及配置组织方式对默认项的处理细节可能存在差异,因此不应依靠模糊的数组位置完成关键分流。更易维护的方法是确保常规流量有明确规则,私有地址、需要直接连接的域名和阻断目标也分别落到确定标签。查看客户端生成的配置时,还要留意客户端是否插入了额外的 DNS 出站或回环出站。

VLESS 客户端出站结构

下面示例展示 VLESS 出站的基本层级。服务器地址使用示例域名,用户标识仅用于展示格式,不能直接用于实际连接。settings.vnext 是服务器数组,每个服务器对象包含地址、端口与用户列表。用户对象中的 id 必须与服务端配置一致,VLESS 常见的 encryption 值为 none。传输方式、TLS 与服务器名称位于 streamSettings,不能误放进用户对象。

{
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "edge.example.com",
            "port": 443,
            "users": [
              {
                "id": "11111111-1111-4111-8111-111111111111",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "serverName": "edge.example.com",
          "allowInsecure": false
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ]
}

address 是核心实际连接的服务器地址,serverName 是 TLS 握手使用的名称,两者可以相同,也可能因部署结构而不同。不能为了“看起来一致”擅自把它们改成同一个值。端口、传输类型、安全层、服务器名称及其他扩展参数必须整体对应服务端;其中任何一项不匹配,都可能表现为连接建立后立即关闭、TLS 握手失败或长时间等待。

freedom 与 blackhole 的实际作用

freedom 让核心从本机网络直接访问目标。它不是绕过核心:流量仍然先经过入站和路由,只是在出站阶段不再发送给远端代理服务器。私有地址、本地开发服务、局域网设备以及明确要求本地出口的站点通常交给该出站。若系统本身无法解析或访问目标,交给 freedom 也不会自动修复本地网络问题。

blackhole 用于丢弃被规则命中的连接,可用于阻断明确不需要的域名、IP 或协议。它与“没有匹配到出站”不同:前者是有意选择阻断出口,后者通常属于配置引用错误。排错时可通过日志中的路由结果辨别。阻断规则宜保持具体,过宽的域名后缀或 IP 范围会同时影响合法子域和共享地址上的其他服务。

多服务器与负载策略

将多个服务器直接塞入同一个出站对象,并不等于自动获得符合预期的切换策略。需要多出口时,通常为每个出口建立独立标签,再通过路由的负载均衡器或客户端提供的选择机制管理。这样可以单独测试每个服务器,也能清楚看到哪条规则选择了哪个出口。图形客户端可能根据当前选中节点动态生成 proxy 出站,因此手工添加的并行出站在下次应用配置时可能被重建。

订阅是节点参数的来源,不应与运行配置混为一层。订阅更新后节点为空或字段解析失败时,应先检查订阅格式与客户端兼容性,可参考订阅失效与解析失败排查。如果节点能够导入但只有某个出口无法连接,则应比较地址、端口、用户标识、传输层与安全层,而不是反复更新整份订阅。

出站排错的分层方法

首先确认路由确实选择了目标出站标签;其次确认服务器地址能够解析,并且本机网络可以到达对应端口;然后检查协议认证字段;最后核对 streamSettings。如果一开始就同时替换节点、关闭 DNS、改路由模式和调整 TLS,得到的结果无法说明哪项修改有效。保留一个已知可工作的直接连接出站也很重要,它可以帮助判断问题位于核心整体启动、路由选择,还是单个代理出口。

04 / STREAM

streamSettings:传输方式与安全层必须成组匹配

协议层、传输层和安全层的区别

出站的 protocol 描述 VLESS、VMess 或 Trojan 等代理协议,streamSettings.network 描述承载连接的传输方式,streamSettings.security 描述 TLS、REALITY 或不启用额外安全层等选择。三层解决的问题不同,但在实际连接中必须与服务端逐项一致。仅知道“使用 VLESS”不足以建立连接,还需要知道 TCP、WebSocket、gRPC 等传输方式,以及对应的服务器名称、路径、服务名或安全参数。

客户端导入分享链接或订阅后,会把这些参数转换为核心认识的字段。不同核心家族对部分字段名、可选值和扩展能力并非完全一致。v2rayNG 常用 Xray 内核,v2flyNG 使用 v2fly 内核路线;v2rayN 可以管理桌面端核心与节点配置。跨客户端迁移时,应根据目标客户端实际使用的内核能力检查,不要只复制一段内部 JSON 后假设所有字段都能被相同解析。

TCP 与 TLS 示例

普通 TCP 传输通常把 network 设为 tcp。启用 TLS 时,security 写为 tls,并提供 tlsSettingsserverName 参与证书名称检查和握手,应使用服务端给出的值。allowInsecure 设为 false 表示执行正常证书验证;把它改为 true 只会绕过部分验证,不能修复错误端口、错误协议或服务端未启动等问题,也不应作为常规排错方案长期保留。

{
  "streamSettings": {
    "network": "tcp",
    "security": "tls",
    "tlsSettings": {
      "serverName": "edge.example.com",
      "allowInsecure": false,
      "alpn": ["h2", "http/1.1"]
    }
  }
}

alpn 用于协商应用层协议。是否需要填写以及值的顺序,应与服务端部署保持一致。并非字段越多越完整;服务端未要求时,客户端自动协商通常更合适。连接失败时也不应随意轮换所有 ALPN 值,因为握手结果还受端口、服务器名称、中间代理和服务端证书配置影响。

WebSocket 的路径与请求头

WebSocket 传输会使用 wsSettings,其中常见字段是 path。路径必须完整匹配服务端,包括开头的斜线和可能存在的查询部分。某些部署还要求特定 Host 请求头,具体字段结构取决于内核支持方式。配置迁移时,最常见的问题是只复制服务器地址和端口,却漏掉路径或主机名,结果表现为 TLS 可以连接,但随后收到普通网页响应或连接被关闭。

{
  "streamSettings": {
    "network": "ws",
    "security": "tls",
    "tlsSettings": {
      "serverName": "edge.example.com",
      "allowInsecure": false
    },
    "wsSettings": {
      "path": "/vless-connect",
      "headers": {
        "Host": "edge.example.com"
      }
    }
  }
}

地址、TLS 服务器名称和 HTTP Host 可能指向同一域名,也可能分别承担连接目标、证书验证和反向代理分流职责。只有在明确知道服务端结构时才能调整。路径中的大小写通常具有意义,末尾斜线也可能导致不同路由结果。若客户端界面把这些字段拆成“地址”“伪装域名”“路径”等输入项,应以导出后的实际 JSON 为准确认映射。

gRPC 与服务名称

gRPC 传输通常使用 grpcSettings,关键字段是 serviceName。它不是普通网页路径,不应机械地添加斜线。不同部署还可能涉及多路复用相关选项,但基础排错仍从服务名称、TLS 服务器名称和端口开始。若服务端使用 gRPC,而客户端选择了 WebSocket,即使两边都启用 TLS,也不会因为证书正确而自动兼容。

{
  "streamSettings": {
    "network": "grpc",
    "security": "tls",
    "tlsSettings": {
      "serverName": "edge.example.com",
      "allowInsecure": false
    },
    "grpcSettings": {
      "serviceName": "vless-grpc"
    }
  }
}

REALITY 配置的核对顺序

REALITY 属于安全层能力,常与 VLESS 配合,但它不是 VLESS 的同义词。客户端参数通常涉及服务器名称、公钥、短标识和指纹等内容,具体字段以目标核心支持为准。核对时先确认当前内核是否支持该安全层,再检查地址与端口,然后逐项比较服务器名称、公钥、短标识和传输方式。把 TLS 配置块与 REALITY 配置块同时混入同一个出站,通常说明导入或手工合并过程出了问题。

传输层排错应避免“逐个猜值”。正确方法是从同一份可靠的服务端参数重新对照,确认协议、网络类型、安全类型三个入口字段,再进入对应的设置对象。日志中若出现证书名称、握手、服务路径或协议响应相关错误,才沿相应分支继续检查。若日志只显示超时,则还要先排除 DNS 解析、目标端口不可达和路由选错出口。

多路复用与性能参数

部分配置支持在出站上设置多路复用,使多个逻辑连接共享底层连接。它可能减少重复握手,也可能因服务端支持、长连接特征或应用流量类型产生相反效果。没有明确问题时,应先使用客户端默认值。遇到单连接正常但并发访问异常、长时间运行后卡住等情况,可以在其余字段不变的前提下关闭多路复用对照。性能参数应建立在连接正确的基础上,不能用于掩盖协议或传输层不匹配。

05 / ROUTING

routing 路由规则:按顺序匹配并选择出口

路由只决定出口,不创建连接能力

routing 模块根据目标域名、目标 IP、端口、来源入站、网络类型或协议等条件,把连接交给指定出站。它不会改变出站本身的协议参数,也不会让不可用的服务器恢复连接。某个域名访问失败而其他域名正常时,路由和 DNS 是重点;所有流量都无法通过同一个代理出口时,应先确认出站连接能力。

rules 数组通常按从上到下的顺序检查,先命中的规则先决定结果。因此,具体规则应放在宽泛规则之前。例如,一个完整域名需要走代理,而其所属的整个域名后缀设置为直连时,完整域名规则应位于后缀规则之前。规则数量较多时,可按“阻断、私有地址、特殊代理、特殊直连、地域分类、兜底”分组维护,并为每组保留清晰说明。

domain、ip 与 port 的写法

域名条件可以使用精确域名、后缀、关键字、正则表达式以及 geosite 分类。不同匹配形式的前缀和含义不同,不能把普通字符串当成精确匹配理解。IP 条件可以填写单个地址、CIDR 网段或 geoip 分类。端口既可以是单个数字,也可以是范围字符串。一个规则中同时填写多个条件类型时,通常需要这些类型共同满足;同一类型数组中的多个值则用于匹配其中任意一个。

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": ["full:updates.example.com"],
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "domain": ["domain:example.net", "geosite:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": ["geoip:private", "geoip:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

full: 适合只匹配一个完整主机名,domain: 通常覆盖该域名及其子域。geosite: 依赖核心能够找到对应的地理分类资源文件;geoip: 同样依赖 IP 数据资源。资源文件缺失、路径错误或客户端更新后未正确加载时,相关规则会在启动阶段报错或无法按预期工作。首页视觉中的“更新 geosite 数据”是一项真实维护操作,但执行频率应由客户端更新机制和规则需求决定。

domainStrategy 如何影响域名与 IP 规则

domainStrategy 决定路由阶段是否为了匹配 IP 规则而解析域名。AsIs 倾向于保持请求中的域名,不主动为 IP 规则解析;IPIfNonMatch 通常在域名规则没有命中时再解析 IP,并尝试 IP 规则;IPOnDemand 会更早触发与 IP 规则相关的解析。具体行为还要结合内核实现与 DNS 配置理解。

选择策略时应先明确规则主体。如果主要依靠 geosite 和明确域名列表,避免不必要解析可以减少路径复杂度;如果大量依赖 geoip,则需要让域名获得可用于路由判断的 IP。解析结果来自哪里同样重要:系统 DNS、核心内置 DNS 和远程解析可能给出不同结果,进而改变 IP 分类命中。因此,调整 domainStrategy 后应同时观察 DNS 日志和路由结果。

按入站、网络和协议分流

inboundTag 可限制规则只处理来自某些入口的流量。例如单独建立直连入口后,可以把该入口全部导向 directnetwork 可区分 TCP 与 UDP,适用于某个出站不处理特定网络类型的情况。部分内核还支持识别特定应用层协议,但前提是流量嗅探能够取得足够信息。依赖协议识别的规则应当作为辅助,不应替代明确的域名或端口条件。

{
  "type": "field",
  "inboundTag": ["direct-in"],
  "network": "tcp,udp",
  "outboundTag": "direct"
}

规则冲突与优先级检查

路由冲突最常见的表现是规则本身都合法,但宽规则提前命中,后面的具体规则永远没有机会执行。检查时从目标连接开始,记录它的域名、解析 IP、端口、网络类型和入站标签,然后从第一条规则逐条判断。不要只搜索预期规则是否存在,还要检查它前面是否已有可命中的规则。可参阅自定义路由规则与匹配优先级详解了解 domain、ip 与 geosite 的组织方法。

另一个常见问题是规则引用了错误标签。客户端切换节点后可能重新生成主要出站标签,手工规则若引用旧标签就会失效或导致启动错误。稳定做法是使用客户端保留的逻辑标签,而不是节点备注。若客户端提供“绕过局域网地址”选项,应确认它生成的是私有地址直连规则,并放在合适优先级,而不是再手工添加一组相互重叠的规则。

兜底规则与可维护性

一条仅指定网络类型并导向主要出口的规则常被用作兜底。它应放在数组末尾,因为它会匹配大多数连接。规则前部保留阻断、私有地址和特殊分流,末尾再处理其余流量,行为最容易预测。若完全依靠默认出站而不写兜底,配置仍可能工作,但阅读者需要额外推断数组位置与核心行为,不利于长期维护。

大型规则集不宜把每个域名都散落在主配置里。可以使用客户端支持的规则集管理方式,但最终仍要确认生成后的 JSON 是否引用正确资源。更新规则数据后如果连接行为突然变化,应比较分类内容、资源加载日志和规则顺序,而不是先修改服务器节点。路由是一套确定的匹配系统,排错重点是找出哪条规则实际命中。

06 / DNS

DNS 配置:控制解析来源、域名匹配与结果范围

核心 DNS 与系统 DNS 的关系

dns 模块为核心内部需要解析的域名提供服务器和匹配规则,但并不保证操作系统中的所有 DNS 请求都会自动进入核心。应用是否直接调用系统解析、是否把域名交给 SOCKS、是否发送独立 DNS 数据包,会决定实际路径。看到配置中存在 dns.servers,不能直接推断浏览器的每次解析都使用了这些服务器。排错时要区分“核心为出站服务器地址做解析”“路由为目标域名做解析”和“应用自行完成解析”三种情况。

核心 DNS 的价值在于让解析选择与路由规则协同。例如特定域名交给指定解析服务器,得到的结果再用于 IP 路由;或为某组域名设置预期 IP 范围,避免接受不符合条件的响应。完整方案需要同时考虑 DNS 查询本身走哪个出站、解析结果用于哪一步,以及应用最终连接时是否仍保留域名。

servers 数组与条件服务器

servers 中既可以写简单服务器地址,也可以写带匹配条件的对象。对象形式可通过 domains 指定适用域名,并通过 expectIPs 约束可接受结果的范围。下面示例把特定分类交给一个本地网络可访问的解析地址,其他域名交给另一个解析服务器。示例地址用于说明结构,实际部署应选择当前网络与出站路径确实能够访问的解析服务。

{
  "dns": {
    "hosts": {
      "router.internal.example": "192.168.1.1"
    },
    "servers": [
      {
        "address": "223.5.5.5",
        "domains": ["geosite:cn"],
        "expectIPs": ["geoip:cn"]
      },
      {
        "address": "1.1.1.1",
        "domains": ["geosite:geolocation-!cn"]
      },
      "localhost"
    ],
    "queryStrategy": "UseIP"
  }
}

domains 的匹配方式与域名规则体系相关,依赖的分类资源也必须能够加载。expectIPs 不是把解析结果改写到某个网段,而是用于筛选或判断响应是否符合预期。条件过窄时,合法但不在分类范围内的地址可能被拒绝,表现为该域名解析失败。排错时应临时使用简单服务器配置对照,再逐步恢复域名条件与结果约束。

hosts 的静态映射

hosts 用于为特定名称提供静态映射,适合固定的本地服务、测试环境或明确需要覆盖的记录。它不适合代替大规模动态 DNS。目标地址发生变化时,静态值不会自动更新;配置中遗留的旧映射还可能让某个域名长期指向错误地址。检查“只有一个域名始终连到旧服务器”这类问题时,应搜索 hosts、系统 hosts 文件和客户端自定义 DNS 映射三处。

静态映射的名称仍可能进入路由模块。应确认路由判断使用原域名还是解析后的 IP,以及该 IP 会命中哪个出口。如果本地域名映射到私有地址,通常还需要私有地址直连规则。否则连接可能被错误送往代理出站,造成局域网服务无法访问。

queryStrategy 与地址族选择

queryStrategy 用于约束查询的地址类型。常见目标是同时使用可用地址、只请求 IPv4 或只请求 IPv6,具体可选值取决于核心实现。选择时要以当前网络是否真正具备对应地址族连通性为依据。网络能返回 IPv6 地址但没有稳定 IPv6 出口时,应用可能优先尝试不可达地址,表现为连接延迟或超时;反过来,强制只用 IPv4 会排除只提供 IPv6 的目标。

地址族问题不应只靠反复切换策略判断。可以分别查看 DNS 返回结果、系统路由表和核心连接日志,确认最终尝试的是哪类地址。若代理服务器本身以域名填写,解析它所用的地址族同样会影响核心能否建立出站连接。目标网站解析正常但服务器域名解析失败时,故障发生在不同环节。

DNS 查询如何选择出站

DNS 服务器是一个目标,查询流量也需要经过网络出口。部分配置可以给 DNS 服务器设置标签或通过专用出站处理,客户端也可能生成专门的 DNS 路由。设计时要避免循环:解析代理服务器地址所需的 DNS 不能依赖尚未建立的代理出站,否则启动阶段可能无法完成第一步连接。常用做法是让服务器地址解析具备可用的本地路径,再让目标域名查询按规则选择直接或代理出口。

当解析服务器写成域名而不是 IP 时,它本身还需要先被解析,这又增加一层依赖。基础配置应优先建立可解释的路径,确认工作后再引入加密 DNS、条件服务器和复杂出站绑定。有关境内外域名分开解析、serversdomainsexpectIPs 的组合,可继续阅读V2Ray DNS 配置详解

缓存与排错顺序

DNS 结果可能存在于应用、操作系统、客户端或核心的缓存中。修改配置后立即重复访问,仍可能使用旧结果。正确步骤是保存配置、重启对应核心、按需关闭并重新打开测试应用,再观察新日志。无需每次都清理整个系统网络状态;应先确认哪一层缓存了结果。若重启核心后日志仍没有新的查询记录,说明应用可能没有把域名解析交给核心。

DNS 排错可以遵循固定顺序:先验证服务器地址可达,再用无条件规则确认能返回结果,然后加入 domains,最后加入 expectIPs 和出站绑定。每一步只增加一个变量。解析成功后仍无法连接,则转到路由与出站检查;不要把所有连接错误都归因于 DNS。

07 / POLICY

policy、stats 与 log:会话策略、统计开关和诊断记录

policy 控制连接会话行为

policy 用于设置用户级别和系统级别的运行策略。常见内容包括握手等待时间、连接空闲时间、上下行只关闭后的延迟以及是否启用用户流量统计。它不负责域名路由,也不改变传输协议。默认策略通常足以满足桌面客户端使用,只有在明确遇到长连接回收、服务端用户等级或统计需求时才需要调整。

用户级别由协议用户对象中的 levelpolicy.levels 对应。若用户未指定等级,通常使用默认等级。等级是策略索引,不是线路质量或权限评分。手工配置时,如果用户写了 level: 1,却只定义等级 0,预期策略就不会按设计应用。客户端节点通常不需要自行增加等级,除非服务端和客户端配置方案明确使用该机制。

{
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "uplinkOnly": 2,
        "downlinkOnly": 5,
        "statsUserUplink": false,
        "statsUserDownlink": false
      }
    },
    "system": {
      "statsInboundUplink": true,
      "statsInboundDownlink": true,
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  },
  "stats": {}
}

handshake 限制连接建立阶段允许等待的时间,设得过短会让网络波动下的正常连接提前终止;设得很长则会让无响应连接占用资源更久。connIdle 用于处理空闲连接,某些需要长期保持但暂时没有数据的应用可能受其影响。uplinkOnlydownlinkOnly 处理半关闭状态下的保留时间。没有充分理由时,不宜为了追求“更快释放”把这些值压得很低。

stats 对象与统计开关的关系

仅写一个空的 stats 对象并不一定产生所有统计数据。需要在 policy.system 或用户等级策略中启用相应方向的统计开关,再由客户端或 API 读取。入站与出站统计用于观察对应标签的总流量,用户统计则与协议用户及等级策略相关。统计功能会增加一定的状态维护工作,若客户端界面不读取这些数据,可以保持关闭。

图形客户端显示的流量信息可能来自核心统计接口,也可能来自客户端自身对连接的汇总。看到界面有流量数字,不代表配置中所有 stats 字段都已启用;反过来,启用统计但没有读取接口,界面也未必出现结果。排查应先确认数据产生位置,再检查读取方式,避免把显示层问题当作转发故障。

log 的访问记录、错误记录与级别

log 常见字段包括访问日志位置、错误日志位置和 loglevel。日志级别可按排错需要调整。日常运行使用警告级别可以减少输出;遇到配置引用、DNS 选择或连接握手问题时,可暂时提高详细程度。问题复现并记录后,应恢复适合长期运行的级别,以免日志持续增长并混入大量无关信息。

{
  "log": {
    "access": "access.log",
    "error": "error.log",
    "loglevel": "warning",
    "dnsLog": false
  }
}

相对日志路径通常相对于核心工作目录,而不是配置文件所在目录。由 v2rayN 等客户端启动核心时,工作目录可能由客户端决定,因此手工查看文件时要先确认实际运行目录。若路径所在目录没有写入权限,核心可能无法创建日志文件,甚至直接启动失败。为了避免路径差异,优先使用客户端提供的日志查看入口;需要自定义路径时,再使用当前系统上的明确可写目录。

访问日志用于记录连接目标和处理结果,错误日志用于记录解析、握手、资源加载与模块异常。日志可能包含目标域名、地址和本地连接信息,分享排错内容前应删除与问题无关的个人配置数据。完整配置中的用户标识、服务器参数和订阅内容也不应直接粘贴到公开环境;通常只需提供错误行、相关模块和经过简化的字段结构。

DNS 日志和路由诊断

部分核心支持通过 dnsLog 或更详细日志观察 DNS 查询。该选项是否存在及具体行为应以当前内核文档和客户端生成配置为准。开启后重点查看查询域名、选中的服务器、返回地址和失败原因。路由诊断则关注入站标签、目标信息、命中规则与最终出站。两类记录结合起来,才能解释“域名解析到了某个地址,随后为何被某条 IP 规则分到特定出口”。

日志中的第一条错误通常比后续连锁错误更有价值。例如资源文件无法加载后,大量 geosite 规则都会失败;端口绑定失败后,应用侧会产生一连串代理不可用提示。应按时间顺序找到核心启动阶段最早的异常,再判断后续内容是否只是结果。若核心启动成功,只在访问特定目标时出错,再按单次连接记录追踪。

API 与管理接口的边界

部分配置通过 API 入站向客户端提供统计、日志或运行控制能力。它通常由图形客户端自动生成,并绑定本地地址。手工修改这类入站标签、服务列表或路由规则,可能导致客户端无法读取核心状态。API 端口不应当作普通 SOCKS 或 HTTP 代理端口使用,也不应随意开放到局域网。若客户端启动核心正常但状态栏无法更新,应比较 API 入站、路由到 API 出站的规则和客户端期望端口。

policystatslog 和 API 都属于运行管理层。它们有助于观察连接,却不能替代对入站、路由、DNS 和出站链路的检查。最小配置应先保证流量能正确通过,再逐项启用统计与管理功能。这样即使管理接口发生问题,也能明确区分“核心无法转发”和“客户端无法显示状态”。

08 / CHECK

组合配置与排错:从语法测试到单连接追踪

先建立可验证的完整链路

组合配置时,不要从一份包含大量规则、多个出口和复杂 DNS 的文件直接开始。先建立一个本地 SOCKS 入站、一个已知参数完整的代理出站、一个直接连接出站以及少量明确路由。确认核心能启动、应用能连接、两个出口都能分别工作后,再加入域名分类、条件 DNS、阻断规则和统计模块。每增加一层都进行一次测试,问题出现时就能锁定最近改动。

图形客户端环境中,配置来源往往有三层:订阅或手工节点提供远端参数,客户端设置提供本地端口与系统代理行为,路由和 DNS 模板提供分流逻辑。最终运行文件是三层合并结果。节点详情正确但运行失败时,应导出或查看实际配置,确认客户端没有覆盖服务器名称、传输方式或出站标签。升级或切换核心后,也要检查旧字段是否仍被当前内核接受。

执行语法与配置测试

核心通常提供只测试配置而不长期运行的命令。命令名称和参数形式随核心程序而异,常见形式如下。执行时应使用客户端实际调用的核心文件和实际配置路径。若图形客户端已经提供“检查配置”或日志入口,优先使用客户端功能,因为它会带上正确的工作目录与资源路径。

v2ray test -c config.json

xray run -test -config config.json

测试通过表示 JSON 可以解析且基础模块能够建立,不代表远端服务器可达,也不代表每条路由都符合预期。测试失败时,从输出中的字段路径和最早错误开始处理。若提示无法加载地理数据,先检查资源文件与工作目录;若提示找不到标签,检查路由引用;若提示地址已被使用,检查入站端口;若提示未知字段,则确认当前核心家族是否支持该配置。

一份用于本地结构验证的组合示例

下面示例不包含远端代理凭据,而是用直接连接和阻断出口展示完整模块关系。它可以用于验证本地入站、DNS、路由与日志层级。实际加入代理出口时,应把服务端提供的协议与传输字段作为完整对象插入,并将兜底规则的 outboundTag 改为对应代理标签。

{
  "log": {
    "loglevel": "warning"
  },
  "dns": {
    "servers": ["localhost"]
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": ["full:block.example"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "direct"
      }
    ]
  }
}

按症状选择排错入口

症状 优先检查 下一步
核心无法启动 JSON 语法、未知字段、资源路径、端口占用 读取启动阶段第一条错误
应用无法连接本地代理 监听地址、端口、代理类型、进程状态 确认入站是否出现连接记录
所有代理目标都超时 路由出口、服务器解析、目标端口、传输层 单独测试 direct 与 proxy 出站
只有部分域名失败 DNS 条件、路由顺序、嗅探、静态映射 记录解析结果与命中规则
局域网地址无法访问 geoip:private、绕过局域网、入站监听范围 验证 private 规则是否先于兜底
客户端状态无法显示 API 入站、统计开关、管理路由 区分转发故障与显示故障

症状分类的作用是减少无关改动。核心无法启动时,服务器是否可达并不重要;应用连不上本地端口时,先检查入站,不必更换远端节点;只有部分域名失败时,重点是该域名与正常域名在 DNS、路由和嗅探上的差异。每次测试都应包含一个对照对象,例如同一出口下的正常域名、同一域名走 direct 的结果,或同一节点关闭复杂路由后的结果。

配置修改后的固定检查清单

保存后先做 JSON 与配置测试,确认没有语法和模块初始化错误。随后检查所有标签引用:每个 outboundTag 都存在,每个 inboundTag 都能找到入口,负载或 API 相关标签也没有改名。再确认本地端口没有冲突,客户端使用的代理类型与入站协议一致。核心启动后,分别测试直接连接规则、代理规则和私有地址规则,最后再测试 UDP 或特殊应用。

DNS 修改需要额外记录查询服务器与返回地址;路由修改需要记录实际命中规则;传输层修改需要对照服务端参数;策略修改需要观察长连接而不是只打开一次网页。把结果按模块记录,比“修改后好像更快”更可靠。如果问题只能在某个应用复现,还应比较该应用是否自行解析域名、是否支持 SOCKS UDP、是否忽略系统代理,以及是否保持旧连接。

客户端配置与手工配置如何共存

v2rayN 是桌面平台的首选管理客户端,适合通过界面维护订阅、节点、路由和 DNS;v2rayNG 与 v2flyNG 用于 Android,分别对应不同内核路线。需要安装或重新选择客户端时,可前往安装包页面。客户端负责生成运行配置时,应尽量通过其自定义配置、路由设置或 DNS 设置入口修改,直接编辑临时生成文件通常会在重启或切换节点后丢失。

确实需要手工维护 JSON 时,应把稳定配置与客户端临时文件分开存放,并明确由谁负责启动核心。不要让两个客户端同时监听相同端口,也不要让系统代理仍指向已经停止的实例。订阅更新只更新节点来源,不会自动证明自定义路由与 DNS 仍然适配;更新后应重新查看合并结果,尤其是出站标签和传输层字段。

形成可重复的排错记录

有效的排错记录应包含发生时间、客户端与核心类型、相关入站标签、目标域名或地址、命中出站、首条错误信息以及本次只改动的字段。无需复制整份包含敏感连接参数的配置。把问题缩减成最小结构后,通常更容易判断是语法、内核兼容、网络可达性还是规则逻辑。

完成基础配置后,可回到使用文档核对客户端操作主线;处理订阅异常、路由优先级、DNS 分流或端口冲突时,可在文章目录按故障类型继续查阅。系统化配置的目标不是堆叠字段,而是让每个入口、匹配条件和出口都有清晰作用,并且能够通过日志与对照测试解释其行为。

按平台选择客户端

桌面平台优先使用 v2rayN;Android 可按内核需求选择 v2rayNG 或 v2flyNG。安装后再依据本页核对生成配置。

查看安装包