· Networking · About 10 minutes

V2Ray DNS Split Tunneling: Separate Resolvers for China and Overseas Domains

Learn how dns.servers, domains, and expectIPs work. Configure local DNS for mainland China domains and remote DNS for overseas domains, with practical tips to prevent DNS poisoning.

At a glance

This guide is for users who can already connect to a proxy node and want to fine-tune DNS routing. First, identify whether DNS queries are handled by the app, the operating system, or the core. Then route mainland China domains to a preferred local resolver and other queries to remote DoH, and verify the path in the logs. These examples are configuration snippets to merge into your existing setup; they do not take over system DNS or replace a working proxy outbound.

1. DNS routing vs. connection routing

DNS routing determines which resolver looks up a domain; connection routing determines which outbound carries the site connection. They’re related, but they aren’t the same rule. Routing a mainland China site directly doesn’t guarantee it uses a mainland China DNS resolver. Routing a DNS server through a proxy doesn’t automatically send the site connection through that proxy.

Domain reaches the core Resolution rules are matched Resolver is queried Address results are filtered Connection outbound is selected

This sequence describes a typical flow when the core handles DNS; not every request passes through every step. If a browser resolves a domain to an IP using its own secure DNS before passing the IP to the proxy, the core may never see the original DNS query. Conversely, when an app passes a domain to a SOCKS proxy, the domain may be forwarded to the proxy server for resolution there.

2. What servers, domains, and expectIPs do

dns.servers is the list of DNS resolvers available to the core. Entries can be simple addresses or objects with domain-matching conditions. An object’s domains field selects a preferred resolver for matching domains; expectIPs checks whether returned addresses fall within the expected ranges. It is not a connection-routing rule or proof that a DNS response is authentic.

FieldValue used hereWhat it does
serversMainland China UDP DNS and remote DoHDefines the resolvers available to the core.
address223.5.5.5In this example, a plain IP address is used for a UDP DNS query.
domainsgeosite:cnPrefer this resolver for matching domains; the corresponding domain data file must be available.
expectIPsgeoip:cnFilters results against an address set. A mismatch may reject the result and trigger another attempt.
skipFallbacktrueThis resolver is excluded from ordinary fallback queries but can still be selected by its own domain rules.
queryStrategyUseIPv4This example requests IPv4 addresses only, making it easier to rule out IPv6 as a variable.

geosite:cn is a domain category in a data set, not a catch-all for domains ending in .cn. geoip:cn also depends on the IP data file in use. Cross-region CDNs, corporate networks, and data file updates can all affect the result. So a domain associated with mainland China returning an overseas IP does not, by itself, mean the response was poisoned.

Bottom line: verify the domain category before tightening address filters

If a mainland China site stops resolving after you add expectIPs, temporarily remove the restriction and compare the returned addresses. If they’re legitimate CDN results, set a resolver specifically for that domain rather than repeatedly switching nodes to work around a classification issue.

3. Configuration: prefer mainland China DNS, use remote DoH for other queries

The basic setup below prefers a mainland China resolver for domains in the mainland China category and uses remote DoH for other queries. The first entry is a public resolver in mainland China, not a home router address. If you need to resolve internal ISP domains, specify the actual DNS server for that network. The second entry uses an IP-based DoH address, avoiding a separate bootstrap lookup for the DoH server’s hostname.

{
  "dns": {
    "queryStrategy": "UseIPv4",
    "servers": [
      {
        "address": "223.5.5.5",
        "port": 53,
        "domains": [
          "geosite:cn"
        ],
        "expectIPs": [
          "geoip:cn"
        ],
        "skipFallback": true
      },
      "https://1.1.1.1/dns-query"
    ]
  }
}

This is not a complete config.json. Merge the dns object into your existing top-level configuration; don’t add duplicate keys to a JSON object. If DNS settings already exist, edit that section instead of pasting both snippets in sequence. JSON does not allow explanatory comments.

  1. Make sure you’re running a V2Fly or Xray core that supports these fields, and check the current core startup log. The client name and core version are not the same thing.
  2. Make sure the core can read domain and IP data files that include the cn category. If data is missing, resolve the loading error first.
  3. Keep your existing inbounds and outbounds, merge in the DNS settings, reload the configuration, and check the error log.
  4. Start by testing a few known domains, then expand the matching rules gradually. If your network needs IPv6, adjust the query strategy only after verifying dual-stack connectivity.

4. Route DNS queries through the right outbound

Adding a DoH address specifies the query protocol, not the network route. Built-in DoH using a standard https:// URL follows the core’s routing rules. If the default outbound is direct, remote DoH may connect directly. Don’t confuse this with local resolution modes that bypass normal routing, or assume that encryption means traffic is already going through a proxy.

53
Destination port for the example mainland China DNS server
443
Destination port for HTTPS in the DoH example
10808
Local SOCKS port assumed by the tests below

The routing snippet below assumes you already have outbounds tagged direct and proxy. Replace these with the actual tag values in your configuration, or define the corresponding outbounds first. The example matches exact IPs and ports for DNS connections, so it won’t route all traffic to those addresses through the same rule.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": ["223.5.5.5"],
        "port": "53",
        "network": "udp",
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": ["1.1.1.1"],
        "port": "443",
        "network": "tcp",
        "outboundTag": "proxy"
      }
    ]
  }
}

Merge these two rules into your existing routing.rules, placing them before any broad rule that could match first. Rules are evaluated in order; once an earlier rule matches, later DNS-specific rules won’t apply. This snippet routes resolver connections only; it does not configure full site routing.

5. Verify the setup in v2rayN and Android clients

In v2rayN, the client often generates the standard node configuration for you. Direct edits to a temporary config in the runtime directory may be overwritten when you switch nodes or restart. Use the DNS settings or custom configuration entry point provided by your version, then inspect the config it generates. v2rayNG uses the Xray core, while v2flyNG uses the V2Fly core. Client options for remote DNS, VPN, and routing don’t necessarily map directly to native JSON fields.

  1. Record a baseline: Save your current configuration and note the active node, local listening ports, system DNS, and browser secure DNS status. Change one DNS setting at a time.
  2. Check the proxy entry: These commands assume a SOCKS inbound is listening at 127.0.0.1:10808. If the client shows a different port, update the commands first; don’t assume this is the default for every version.
  3. Compare the paths: Test both local app-level resolution and requests that pass the domain to the proxy. Different results mean you should investigate where resolution is happening.
  4. Check the logs: Temporarily set log.loglevel to info and compare DNS and outbound entries against the request timestamps. Log details vary by core; use debug briefly if needed, then restore the original level.
curl --socks5 127.0.0.1:10808 -I https://www.qq.com
curl --socks5-hostname 127.0.0.1:10808 -I https://www.qq.com
nslookup www.qq.com 223.5.5.5

The first command usually has curl resolve the site domain locally. The second passes the domain to the SOCKS proxy, and where it’s resolved depends on core routing and the outbound. So a successful second command alone doesn’t prove the local built-in DNS was used. The third queries a specified public DNS server; it’s only a resolver connectivity check and doesn’t prove that dns.servers is working. In Windows PowerShell, use curl.exe if you run into command alias differences.

Bottom line: verify the configuration by checking the query path, not just whether a site opens

After making changes, restart the relevant apps and wait for or clear the appropriate caches, then test again. If the logs don’t show the expected DNS activity, first confirm that the request reaches the core. A site opening or a one-off change in latency isn’t proof that DNS routing is working.

6. DNS poisoning prevention and common issues

Preventing DNS poisoning depends on how queries are transmitted, whether you trust the resolver, where results are used, and how fallback works. DoH can protect traffic between the client and the DoH resolver, but it won’t fix incorrect domain classification, an unreachable proxy outbound, or app-level DNS. expectIPs only restricts address ranges; it neither encrypts DNS traffic nor detects every false response.

Why can’t I reach mainland China sites after adding expectIPs?

Temporarily remove expectIPs from that resolver, reload the configuration, and look up the same domain again. If it returns a legitimate overseas CDN address, adjust the domain’s resolution strategy or check the IP data file instead of forcing every result to fall within mainland China address ranges.

Why do I still see local DNS requests after setting up remote DoH?

First identify which process is making the request. Browsers, system services, and apps that don’t use the proxy may resolve domains independently; proxy node hostnames may also need bootstrap resolution. Check system DNS, browser secure DNS, and the client’s DNS takeover settings—not just the dns section.

Web pages load slowly. Do I need more DNS servers?

First separate DNS lookup time from TCP connection and TLS handshake time. Use one preferred mainland China resolver and one reachable remote DoH server as a baseline, then check timeouts and fallback logs. Adding several unreachable resolvers can increase delays and spread queries across more servers.

Why did my JSON changes disappear after switching nodes?

The client probably regenerated its runtime configuration. Save your changes through the DNS settings or custom configuration entry point supported by the client, then check the generated config after switching nodes. A subscription updates node details; it doesn’t automatically preserve manual edits to a temporary config.

Can I use IPv4 only long term?

UseIPv4 is useful for ruling out dual-stack issues, but it disables IPv6 address lookups. If both your network and proxy outbound have reliable IPv6 connectivity, try UseIP and check IPv4 and IPv6 routing and app behavior separately.

Keep three verifiable details: where each domain is resolved, which outbound carries the DNS connection, and where queries fall back if resolution fails. For an overview of how top-level settings fit together, see the configuration reference. If you have questions about proxy, core, or routing terminology, start with the glossary.

Download client