V2Ray DNS Setup: Split DNS and Prevent DNS Spoofing

Learn how V2Ray's built-in DNS works, route domains to separate resolvers, use DoH, and prevent DNS spoofing with routing rules.

At a glance

For users who can already connect to a node with v2rayN or v2rayNG and want to configure split DNS. First distinguish system, core, and proxy-side DNS resolution, then set up two upstreams with explicit outbound rules and verify the results. Examples use Xray JSON; merge the snippets into your existing configuration. They are not complete, ready-to-run node configs.

1. Where built-in DNS fits into a connection

“I configured DNS, so why is my browser still querying the system resolver?” The server address usually isn’t the problem—the request may never reach the core’s DNS module. Built-in DNS in V2Ray and Xray is a resolver the core can call. Adding a dns field does not automatically intercept every UDP port 53 request on your device.

Domain reaches the core A lookup is needed An upstream is selected The query uses an outbound The result is used to connect

When an app passes a domain to a SOCKS proxy, the core may send the domain to the remote server for resolution. If the app first resolves the domain through the system DNS and then passes the IP to the proxy, the core never sees the original domain. Neither path means that the client’s built-in DNS is necessarily in use.

2. Choose upstreams, ports, and the core’s role

This setup sends mainland China domains to 223.5.5.5 and all other domains to https://1.1.1.1/dns-query, routing the latter through your existing proxy outbound. Using an IP address for the DoH endpoint avoids needing to resolve the resolver’s hostname just to connect to it. Keep normal TLS certificate verification enabled.

Mainland China domain upstream

Server
223.5.5.5
Transport
Plain DNS over UDP port 53
Matches
geosite:cn
Query outbound
direct

Useful when you want DNS results from a local network perspective; this plain DNS connection is not encrypted.

Other domains upstream

Server
https://1.1.1.1/dns-query
Transport
DoH,TCP 443
Matches
Domains not matched by a dedicated upstream
Query outbound
proxy

Requires a working proxy node. If the proxy is unavailable, queries should not silently fall back to plain local DNS.

53
Example port for the mainland China DNS server
443
Example port for the DoH endpoint
2 upstreams
Domain-based resolver selection

v2rayN is a desktop client, not a guarantee that a particular core is in use. v2rayNG uses Xray, while v2flyNG uses V2Fly. Check the supported fields and default behavior for the core you actually run. In particular, don’t apply Xray settings for DNS fallback, special address prefixes, or outbound resolution strategies unchanged to every core.

  1. Back up a configuration that currently connects, and note the client version and core version shown in the startup log.
  2. Make sure the running config has a proxy outbound, and note its actual tag. This example uses proxy; it does not ask you to change the protocol name.
  3. Make sure geosite.dat is readable and includes the cn category. A missing data file causes rule loading to fail; it is not an upstream timeout.
  4. Change one layer at a time: DNS first, routing next, then check whether the system and browser still resolve independently.

3. Route domains to upstreams and restrict fallback

This is a snippet for the top-level dns field. The mainland China server has a domain match list and handles only those domains. The DoH server has no domain list and serves as the general upstream for everything else. IPv4 is used here to remove IPv6 reachability as a variable during initial troubleshooting—not to suggest disabling IPv6 permanently.

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

This config deliberately does not add localhost or the system DNS as a fallback. Otherwise, if proxy-based DoH is unreachable, queries may fall back to the very resolver path you wanted to avoid. If the startup log reports an unknown field, check the core’s documentation and version first. Don’t simply remove the fallback restrictions and assume the issue is fixed.

4. Route DoH through the proxy and make direct connections use built-in DNS

A DoH URL alone doesn’t tell you whether queries go through the node. Standard https:// DoH requests can be handled by the core router; the rules below send them to proxy by destination IP and port. Don’t casually switch to https+local://: it has different local lookup semantics, so the routing guidance here no longer applies.

Merge these rules into your existing routing config. Put DNS upstream rules before broad direct, IP-category, and final fallback rules. Replace proxy with your actual proxy outbound tag, and make sure direct matches an existing direct outbound. This example does not split traffic by destination IP, so it uses AsIs and avoids resolving every unfamiliar domain just for routing.

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

This is a minimal routing example, not a replacement for necessary rules such as LAN bypasses or direct connections to node addresses. In particular, if a node uses a domain name, its bootstrap lookup must not depend on the proxy that is not connected yet, or startup can get stuck in a loop. You can keep the client’s existing node resolution method and check which upstream it uses separately.

Check the direct outbound too. The snippet below shows the freedom outbound object to merge or replace; it does not mean you should create a second outbound with the same name. Once configured, domains routed directly through this outbound use built-in DNS to obtain an IPv4 address.

{
  "tag": "direct",
  "protocol": "freedom",
  "settings": {
    "domainStrategy": "UseIPv4"
  }
}

Approach: verify the query path before adding IP-based routing

First make sure the domain rules, two upstreams, and two outbounds line up. Add IPIfNonMatch and the relevant IP rules only if you genuinely need routing by destination IP. Don’t change resolution strategy, IPv6, and fallback rules all at once just to make the config feel more complete.

5. Apply the config in v2rayN and v2rayNG

A DNS page in the graphical interface may not accept a complete Xray JSON config. Some fields accept only a server address; other pages separate basic and advanced settings. Check whether the field expects an address, a DNS object, or a complete config before pasting. Direct edits to a client’s temporary generated config are usually overwritten when you switch nodes or restart.

  1. Desktop: find the right settings first: In v2rayN, open “Settings” → “DNS Settings” and check the DNS options for your current core. Then go to “Settings” → “Routing Settings” and review rule order. If your version uses different tabs, follow the descriptions shown for the actual fields.
  2. Use a custom config for complex rules: To control dns, routing, and outbounds together, import the complete merged config via “Servers” → “Add custom config server” in v2rayN. Keep the existing node’s authentication, transport, and TLS settings.
  3. Android: verify how the config runs: In v2rayNG, check VPN mode and DNS-related options under “Settings.” If you import a complete custom config, make sure it is the one actually running, not just saved in the list.
  4. Don’t mix config formats: v2rayNG raw custom configs must follow the Xray structure; v2flyNG must use fields supported by V2Fly. A subscription link, a single-node share link, and a complete JSON config are three different input types.
  5. Restart the connection after saving: Check the startup log for JSON parsing errors, unknown tags, or data file read errors. If startup fails, restore your backup first instead of toggling several options in a row and obscuring the cause.

6. Verify split DNS and DNS spoofing protection

A proper check answers three questions: who received the query, which outbound it used, and which address the app ultimately connected to. Seeing a working IP with nslookup does not prove that the core’s DNS is working; by default, it tests the system resolver path and can serve as a comparison.

CheckWhat to doWhat to look for
System DNS baselineRun nslookup www.example.comRecord the system resolver; don’t treat the output as proof of the core’s upstream.
Mainland China domain pathVisit a domain confirmed to be in geosite:cn.In logs or a packet capture, check for queries to 223.5.5.5:53 and a direct outbound.
Other domain pathVisit a domain outside the mainland China set and confirm that this action actually triggers core DNS resolution.Check whether the connection to 1.1.1.1:443 uses the proxy. If the domain is sent directly to the remote server, no local query may be expected.
Fallback behaviorTemporarily make the proxy unavailable, then trigger a fresh query that needs proxy-based DoH.The query should fail explicitly, not be handed off to the mainland China plain-DNS upstream.
App-level DNSCheck browser Secure DNS, system encrypted DNS, and excluded apps separately.Distinguish the app’s own HTTPS queries from the core’s DoH, and record which traffic each one covers.

Clear relevant caches before testing. On Windows, run the command below to clear the system DNS cache, then restart the core to clear its in-process cache. Browsers may keep their own caches too. Don’t repeatedly refresh the same cached domain and conclude the config is broken because no new query appears.

ipconfig /flushdns
nslookup www.example.com

For troubleshooting, briefly set the top-level log.loglevel to debug and inspect the connection logs. DNS details vary across core versions, so don’t rely on finding one specific log line. After testing, restore warning or the previous level, and avoid sharing full logs that expose visited domains, server addresses, or credentials.

7. Common questions

Why can’t I access a site even with DoH enabled?

DoH addresses only part of the problem: protecting DNS queries in transit. Also check the returned IP, destination port, node connectivity, routing match, and TLS handshake. If the proxy server resolves the domain, check DNS on the server side too; this client config may not have been involved in that lookup.

Do VMess, VLESS, or REALITY change these split DNS rules?

They affect the proxy connection’s protocol or security settings; they don’t choose a DNS upstream for you. The basic split DNS approach stays the same as long as the actual proxy outbound tag is correct. Bootstrap resolution for a node address that uses a domain still needs separate handling.

Should I enable FakeDNS right away?

Not necessarily. FakeDNS returns synthetic addresses for the core to map, so DNS capture and subsequent connections must follow the same processing path. Turning on one option without a complete interception path can leave apps with addresses they can’t connect to directly. First verify real IP resolution and outbound rules, then consider adding FakeDNS.

Do I have to choose between local and remote DNS resolution?

No. The client can resolve mainland China traffic through a specified upstream for direct connections, while other traffic can send the domain to the proxy server for resolution. Be clear about each path’s responsibilities; client-side built-in DNS settings do not automatically apply to the remote server.

Download clientv2rayN / v2rayNG