V2Ray DNS Configuration Guide: Split DNS for Mainland China and Overseas Domains

Trace V2Ray split DNS from domain lookups and upstream selection to routing and outbound connections, with practical DoH configuration checks and DNS pollution troubleshooting steps.

At a glance

This guide is for users who can already import subscriptions but experience failed lookups, slow first connections, or inefficient routes to sites in mainland China. The focus is separating DNS resolution paths from proxy traffic paths: send mainland domains to a local resolver, overseas domains to DoH, then use logs, lookup results, and routing rules to isolate problems.

Understand the two decisions: DNS and routing

When accessing a domain, the client usually needs an IP address first, then establishes a TCP or UDP connection to that address. DNS decides “which address the domain resolves to,” while routing rules decide “which outbound sends the connection.” These decisions are related but not identical. Configuring domain-based routing does not mean DNS queries will automatically use the same path.

The dns object in a V2Ray or Xray configuration selects upstream resolvers, caches results, and controls query policies; the routing object matches domains, IPs, ports, protocols, and inbound tags. If an application resolves the domain locally, the core may receive only the destination IP, so a domain-only rule may not match.

Application requests a domainSelect DNS upstreamReturn destination IPMatch routing rulesSelect outbound connection

System proxy and TUN mode also affect the path. When a browser sends a domain through a SOCKS or HTTP proxy, the core can usually still see the original domain; TUN mode requires the client to take over system traffic and DNS requests. v2rayN, v2rayNG, and v2flyNG expose different options, but the principle is the same: identify who sends the query, then determine which path it takes.

53
Common port for traditional DNS
443
Common port for DoH
A / AAAA
Common address record types
2 times
Resolution and outbound routing are decided separately

Why split DNS for mainland China and overseas domains?

Services in mainland China often use region-aware CDN routing. The same domain may return different data-center addresses when queried through resolvers in different regions. Using a nearby local upstream for mainland domains usually helps obtain a suitable edge node; sending overseas domains to a reliably reachable DoH upstream reduces connection problems caused by incorrect responses, query timeouts, or altered results.

The goal is not to send every query to one public resolver, but to align the DNS path with the intended destination. A typical setup uses geosite:cn to match mainland domains and geoip:cn to verify returned addresses; all other domains go to a designated DoH upstream. Keep the rule database updated with the client or core, or new domains may fall through to the default rule.

Mainland domain resolution

Domain set
geosite:cn
Upstream address
223.5.5.5
Port
53
Result scope
geoip:cn

Prioritize CDN addresses suited to networks in mainland China.

Overseas domain resolution

Domain set
geolocation-!cn
Upstream protocol
DoH
Service address
1.1.1.1
Connection port
443

Carry queries over HTTPS and let the existing routing rules determine the outbound path.

expectIPs filters results; it does not force a domain to resolve to a particular region. If a mainland upstream returns an address outside geoip:cn, the core can try a subsequent resolver. If a mainland site genuinely uses an overseas address, an overly strict condition can trigger repeated lookups. Add a precise exception for that domain instead of removing all validation.

A readable split-DNS configuration

The example below uses common Xray DNS field syntax to illustrate the structure. Supported fields may vary slightly between V2Ray and Xray core versions, so follow the format generated by the current client before importing. In v2rayN, open “Settings” → “Parameter Settings” to confirm the core type, then use “Servers” → “Add Custom Configuration Server” to load the complete JSON.

{
  "dns": {
    "hosts": {
      "domain:router.local": "192.168.1.1"
    },
    "queryStrategy": "UseIPv4",
    "servers": [
      {
        "address": "223.5.5.5",
        "port": 53,
        "domains": [
          "geosite:cn"
        ],
        "expectIPs": [
          "geoip:cn"
        ]
      },
      {
        "address": "https://1.1.1.1/dns-query",
        "domains": [
          "geosite:geolocation-!cn"
        ]
      },
      "localhost"
    ]
  }
}

The list order and domain conditions together determine resolver selection. The first entry handles mainland domains, the second handles explicitly classified overseas domains, and localhost serves as the fallback when no category matches. If all unknown domains should use DoH, first confirm how the current core handles fallback and domain matching, then adjust the fallback order instead of swapping array entries blindly.

  1. Back up the currently working configuration before making changes; do not repeatedly overwrite your only usable configuration.
  2. Add just one mainland DNS upstream and test whether commonly used mainland websites resolve and open normally.
  3. Then add the DoH upstream, test overseas domains that previously failed, and watch the core log for query errors.
  4. Finally add expectIPs, the IPv4 strategy, and hosts rules, changing only one item at a time.
  5. When finished, restart the core or reload the configuration so stale connections and DNS caches do not affect the results.

Split DNS still needs matching routing rules

A correct DNS response only solves “where to connect.” To send mainland connections directly and everything else through the proxy, you also need routing rules with a clear match order. A common structure handles LAN and reserved addresses first, then mainland domains and IPs, and finally sends unmatched traffic to the proxy outbound.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

IPIfNonMatch means that when no domain rule matches, the core may resolve the destination domain and then try IP rules. It is not a switch that resolves every domain in advance, nor does it create mainland and overseas DNS upstreams automatically. With AsIs, the core tends to preserve domain matching; only an IP target can directly match an IP rule.

Conclusion: check DNS and traffic rules together

After sending mainland domains to a local upstream, confirm that geosite:cn and geoip:cn ultimately point to the direct outbound. When overseas domains use DoH, confirm that both the DoH HTTPS connection and the destination-site connection can be established through the intended outbound.

Symptom Check first How to interpret it
Domain rules match intermittently Whether the application resolves domains in advance Logs show only the IP, not the domain
Mainland websites load slowly The CDN address returned by DNS The address is geographically far from the current network
DoH queries keep timing out Port 443 and outbound routing Logs show connection timeouts or handshake failures
The connection stalls for several seconds before succeeding AAAA records and IPv6 reachability IPv6 fails before falling back to IPv4

DoH configuration is more than just changing an endpoint

DoH places DNS messages inside HTTPS requests and commonly uses port 443. This reduces the chance that traditional plaintext UDP queries will be observed or altered in transit, but it cannot replace routing configuration or fix incorrect results returned by the upstream itself. Upstream reachability, the exit path, and caching policy still determine real-world behavior.

After changing a custom configuration in v2rayN, open “Settings” → “Parameter Settings” to check the log level, then open the log panel in the main window and watch the core startup messages. On Android, when using v2rayNG or v2flyNG, first review the routing and DNS pages for the current profile, then reconnect so the VpnService session loads the new configuration.

Conclusion: verify one DoH upstream before adding backups

Using several resolvers with unknown status at once mixes timeouts, fallbacks, and cached results. Start with one clearly reachable upstream on port 443, then add backup resolvers so the logs remain easy to interpret.

Choose three types of targets for testing: a stable mainland CDN domain, an overseas domain that requires proxy access, and a LAN name. Test each target twice in succession to distinguish first-lookup time from cached-connection time. If the first request is slow but later requests are fast, focus on DNS and the handshake; if every request is slow, continue checking routing, node latency, and packet loss.

Troubleshooting order for DNS pollution and connection failures

DNS pollution commonly appears as an address unrelated to the target service, clearly conflicting results for the same domain across different resolution paths, or a successful lookup followed by an immediate connection reset. Do not assume DNS is at fault simply because a webpage will not open: a failed node, disabled system proxy, incorrect routing, or unreachable IPv6 can look similar.

Start troubleshooting with the shortest path. Confirm that the core starts successfully, then confirm that the domain resolves, verify that the result makes sense, and finally check which outbound handles the destination connection. If the v2rayN log shows a configuration-field error, fix the JSON first; if it shows a DNS timeout, inspect the upstream; if an IP is returned but the connection fails, turn to routing and the node.

The connection succeeds, but some domains still will not open. What should I do?

Record the failing and working domains separately, then check the log to see whether the target is a domain or an IP. If it shows only an IP, check whether the application resolved the domain before the proxy could handle it; if it shows a domain but uses the direct outbound, check the geosite classification and rule order.

What if every query times out after switching to DoH?

First restore a working traditional DNS fallback, then confirm that the DoH endpoint’s port 443 can be reached through the current outbound. For a hostname-based DoH endpoint, also keep an upstream available for bootstrap resolution.

Why are mainland websites being sent through the proxy?

Check whether a broader proxy rule matches before the intended rule in top-to-bottom order. Place the LAN, geosite:cn, and geoip:cn rules before the fallback proxy rule, then reload the configuration.

Is the first website load very slow after enabling IPv6?

Temporarily change queryStrategy to UseIPv4 for comparison. If the delay disappears, continue checking whether the local network, direct outbound, and proxy node all have usable IPv6 paths.

Did custom DNS disappear after a subscription update?

The subscription server configuration and the client-wide DNS settings may be managed in different places. Before updating, record the core options under “Settings” → “Parameter Settings” and confirm whether the custom configuration is being overwritten by the subscription-generated configuration.

You can also run a minimal comparison test: temporarily keep only one confirmed working node, one DNS upstream, and the simplest direct rule. If the minimal configuration works, restore ad filtering, complex domain sets, multiple upstreams, and custom hosts one at a time. Adding one item at a time makes conflicts easier to find than repeatedly clearing the entire configuration.

Final checks for a stable configuration

After completing split DNS, do not check only whether one website opens. Also verify that mainland CDNs use direct connections, overseas domains use the intended resolver, the DoH connection has no dependency loop, and the configuration loads correctly after a core restart. Repeat key-domain tests after subscription updates, client upgrades, or rule-database updates.

Desktop checks

Client
v2rayN
Menu path
Settings → Parameter Settings
System proxy
Confirm that it is enabled
Log target
DNS and routing

Reload the core after editing the custom JSON, then run a first-visit test.

Android checks

Client
v2rayNG / v2flyNG
Connection method
VpnService
Battery optimization
Allow background operation
Reload method
Disconnect and reconnect

Confirm that the system has not stopped the background connection before deciding that DNS is timing out continuously.

The final working setup is usually straightforward: send mainland domains to a low-latency local resolver, overseas domains to stable DoH, keep upstream selection aligned with outbound routing, and verify each step in the logs. When something fails, check in this order—core startup, DNS query, returned address, rule match, and outbound connection—rather than repeatedly switching nodes or resolvers.

Download client Windows, macOS, Android, and Linux versions