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.
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.
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.
- Frequently used LAN names can be added to
hosts, such as mapping a router administration domain to192.168.1.1. - On IPv4-only networks, prefer
UseIPv4to avoid receiving AAAA records and waiting for unreachable IPv6 connections to time out. - Enable dual-stack queries only when IPv6 connectivity is stable, then verify that both direct and proxy outbounds can reach IPv6 destinations.
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.
- Back up the currently working configuration before making changes; do not repeatedly overwrite your only usable configuration.
- Add just one mainland DNS upstream and test whether commonly used mainland websites resolve and open normally.
- Then add the DoH upstream, test overseas domains that previously failed, and watch the core log for query errors.
- Finally add
expectIPs, the IPv4 strategy, and hosts rules, changing only one item at a time. - 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.
- Query timeout: First verify that the DoH endpoint’s port 443 can be reached through the intended outbound, then check for a hostname bootstrap-resolution problem.
- Dependency loop: Do not make the DNS query needed to resolve the DoH service hostname depend on the same DoH connection that has not been established yet.
- Cache not refreshed: Restart the core after changing the upstream and reopen the test application; browsers and operating systems may retain their own DNS caches.
- False IPv6 availability: Receiving an IPv6 address does not mean the outbound path is reachable. Temporarily use
UseIPv4for comparison testing. - Outdated rule database: Update the geosite and geoip data bundled with the client, reload the core, and then check whether the domain classification is wrong.
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.
- Core startup logs show no unknown fields, format errors, or port-conflict warnings.
- Mainland domains are resolved by the specified local upstream, with addresses matching the expected region.
- DoH queries for overseas domains can reach port 443 through the intended outbound.
- LAN and reserved addresses take the direct path first and do not fall into the proxy fallback rule.
- When the current network has no IPv6, AAAA connections do not repeatedly wait for a timeout.
- Custom DNS and routing settings remain after subscription and rule-database updates.
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.