A website opening through a proxy doesn’t mean its DNS queries are going through the proxy too. This guide explains the difference between system DNS, core DNS, and browser Secure DNS, then uses comparison tests to trace where queries exit. Check system proxy and TUN settings on desktop, and VPN coverage, per-app exclusions, and Private DNS on Android. Finally, verify the setup with FakeDNS, upstream routing, and disconnect tests. For users who have imported a subscription and want to confirm where DNS queries actually go.
1. DNS leaks are about query paths, not country labels
DNS translates domain names into IP addresses. An app may ask the system to resolve a name, then send the resulting IP through a proxy. Or it may pass the domain directly to a local proxy for resolution by the core or a remote server. Both paths can open a website, but the first may send the query to a resolver provided by your local network. Whether this counts as a leak depends on your routing rules: the issue here is a domain that should go through the proxy being resolved through a local exit instead.
Domains in mainland China can be sent to a local DNS resolver when that’s part of your plan; this isn’t automatically a leak. VLESS and VMess are proxy protocols, while REALITY is a connection security mechanism. None of them dictates how the operating system sends DNS queries. A subscription may include node settings without providing complete DNS interception or routing rules.
Choose your goal first: full-proxy testing or everyday split tunneling
Full-proxy test
- Route both the test app and its DNS queries through the proxy.
- The connection to the remote DNS upstream should also use the proxy outbound.
- Use this to rule out local DNS interference and establish a repeatable baseline.
Everyday split tunneling
- Send explicitly allowed local domains to a local resolver.
- Send domains that require the proxy to a remote upstream.
- Set explicit fallback rules for unmatched domains and DNS connections.
Establish a baseline with full-proxy routing, then restore split tunneling. Otherwise, it’s hard to tell rule-based direct connections from unexpected bypasses.
2. Online DNS leak tests: compare three setups before drawing conclusions
Online tests typically ask your browser to look up a batch of random subdomains, then show which recursive resolvers made those queries. The results reveal the resolvers’ exits—not necessarily the upstream address your device connected to or the city where your proxy node is located. Public DNS providers use anycast and forwarding clusters, so a map or country label alone can’t confirm a leak.
-
Record a direct-connection baseline
Disconnect the proxy, open
dnsleaktest.comin your browser, and run both the standard and extended tests. Record the network type, time, resolver IPs, and organizations as a baseline for your local network. -
Test through the proxy
Start the client and confirm that the same browser is covered, then run the tests again. Keep the same node and network, and don’t change DNS, routing, and browser settings at the same time.
-
Isolate browser DNS
Search your browser settings for “Secure DNS” and temporarily turn it off before testing again. Whether to turn it back on afterward depends on whether you plan to manage the browser’s encrypted DNS path separately.
-
Test after disconnecting
If a brief network interruption is acceptable, disconnect the proxy and start a new test. If your goal is to block access whenever the proxy fails, check for direct system DNS, VPN bypasses, and app-level fallbacks if new domains still resolve and load after disconnection.
| What you see | Check first | What you can’t conclude from this alone |
|---|---|---|
| A local ISP resolver still appears when the proxy is on | System DNS, app exclusions, direct UDP 53 traffic | Don’t dismiss the result just because web traffic exits where expected |
| Two public DNS providers appear | Browser Secure DNS, Android Private DNS, upstream fallback | This doesn’t necessarily mean there are two physical network exits |
| Resolver country differs from the proxy node’s country | Upstream provider, anycast location, and actual routing | This alone doesn’t prove a DNS leak |
| Full-proxy mode works, but results change with split tunneling | Domain matching, rule order, and default outbound | This alone doesn’t mean the node has failed |
3. v2rayN on desktop: troubleshoot system proxy and TUN separately
The steps below follow the settings layout commonly found in v2rayN 7.x. Group names may differ between minor releases, so first check which core is running and review its generated configuration. In particular, TUN mode may use different components and DNS settings from regular system proxy mode. Changes to Xray’s DNS fields may not affect the active TUN path.
Verify TUN coverage
RecommendedIf you need to cover multiple apps, first check that TUN was created successfully, DNS is intercepted, and IPv4 and IPv6 are handled as expected. TUN doesn’t automatically prevent access if the connection drops; test what happens when the client exits, too.
Best for: desktop setups that need unified app traffic and DNS management.
System proxy only
The system proxy affects only apps that honor the setting; it doesn’t intercept DNS at the operating system level. If an app resolves names through the system first, its queries may still go direct. For SOCKS apps, also check whether they send domain names to the proxy for resolution.
Best for: apps that explicitly support proxies and whose remote DNS behavior you can verify.
-
Confirm the active mode
Open “Settings” → “Parameter Settings” and check the core-related options. Then return to the main window and verify the actual status of “System Proxy” and “Enable TUN.” An enabled system proxy in the notification area doesn’t mean every program is using the tunnel.
-
Check the DNS upstream
Go to “Settings” → “DNS Settings” and check the configuration for the active core. You can use
https://1.1.1.1/dns-queryas a remote upstream for testing, then confirm that connections to it are routed through the proxy. Entering a DoH URL alone doesn’t guarantee that. -
Verify the local proxy port
Under “Settings” → “Parameter Settings,” check the local listening port and compare it with the proxy address configured in your browser or app. For example, if the listener is
127.0.0.1:10808, the app should use that port and the matching proxy type. Example ports may not match your setup. -
Clear stale DNS cache
On Windows, open a terminal and run
ipconfig /flushdns, then close and reopen your browser before testing a new domain. This command won’t clear existing connections or every cache maintained by the browser itself.
On Windows with multiple network adapters, also check your Wi-Fi, Ethernet, and virtual adapters. On systems that support Group Policy, go to “Computer Configuration” → “Administrative Templates” → “Network” → “DNS Client” and set “Turn off smart multi-homed name resolution” to “Enabled.” This can help reduce parallel queries, but it doesn’t replace TUN coverage or disable every kind of system DNS fallback. Verify the result with actual tests.
4. v2rayNG on Android: route traffic through the VPN, then check Private DNS
The steps below follow the settings commonly found in v2rayNG 1.9.x. v2rayNG uses the Xray core, but Android VPN coverage, Private DNS, and browser Secure DNS are separate layers. v2flyNG uses the V2Fly core, so not every option and configuration field here applies directly.
-
Check which apps are covered
Open “Settings” → “Per-app proxy” in the side menu and make sure the test browser isn’t excluded. For troubleshooting, you can temporarily turn off per-app proxying to make the test scope clearer. If you use an allowlist, the browser must be included.
-
Check local DNS settings
Open “Settings” in the side menu, find “Enable Local DNS,” and turn it on. Check the “Remote DNS” and “Domestic DNS” fields. Some versions put these options under a DNS Settings group. Verify the remote and mainland China upstreams separately; field names alone don’t reveal their final outbound routes.
-
Test Private DNS
On stock Android, the usual path is “Settings” → “Network & internet” → “Private DNS.” Note the current setting, then temporarily set it to “Off” to establish a baseline for the core’s DNS. Some manufacturers call it “Private DNS” in localized settings; search for that term if needed.
-
Reconnect the VPN
Save your settings, stop the connection, then start it again and confirm that Android shows a VPN connection. Test once over Wi-Fi and once over mobile data. If only one network has problems, check its IPv6 support, DNS reachability, and VPN reconnection behavior.
-
Test the kill switch
If you want access to stop when the proxy fails, go to Android “Settings” → “Network & internet” → “VPN” → “v2rayNG” and check “Always-on VPN” and “Block connections without VPN.” Availability depends on the device and app state. After enabling these options, verify that per-app rules still behave as expected.
5. FakeDNS: avoid early resolution, but don’t skip the remote upstream
FakeDNS returns synthetic addresses and maps them back to domain names when connections follow. This lets the core retain domain information for routing and proxy forwarding. FakeDNS isn’t an encrypted DNS service and doesn’t automatically route every real DNS lookup through the proxy. Direct connections that need real IP addresses still require a suitable DNS upstream.
In v2rayNG “Settings,” look for “Enable Fake DNS.” Before turning it on, make sure “Enable Local DNS” is working, then save and restart the VPN. On desktop, configure FakeIP/FakeDNS according to the active TUN component’s supported options. Don’t copy an Xray FakeDNS object directly into a different configuration format.
FakeDNS flow
- What it returns
- A synthetic address, not the target’s real address
- Example IPv4 pool
198.18.0.0/15- Key requirement
- DNS queries and subsequent connections must use the same mapping
- What to troubleshoot
- Address restoration, sniffing settings, and app compatibility
This address pool is for synthetic mappings, not a resolver to enter in your system DNS settings.
Real DNS flow
- What it returns
- The target’s real A or AAAA record
- Standard DNS
- Typically uses UDP/TCP port 53
- DoH
- Typically queries over HTTPS on port 443
- What to troubleshoot
- Upstream connection routing, fallback, and bootstrap resolution
Encryption doesn’t guarantee the query takes the intended route. Check how the upstream connection is routed.
- If websites misbehave after enabling it, restart the app and clear stale DNS caches before reverting the setting.
- If an app receives a synthetic address and bypasses the VPN, that address usually won’t work as expected. Adjust the VPN coverage.
- Some apps verify real addresses themselves or use their own resolver. FakeDNS may not suit that traffic, so test each app.
6. Disable fallback and set routing safeguards at both layers
“Disable system DNS fallback” isn’t a universal cross-platform switch. Check the core’s backup upstreams, Windows queries across multiple adapters, Android network switching, and browser Secure DNS separately. Xray’s disableFallback controls fallback queries in its built-in DNS only; it doesn’t stop the operating system from sending queries directly.
The examples below show parts of an Xray DNS and routing configuration, not a complete config. They demonstrate a remote upstream and a routing constraint. Your existing configuration must define a proxy outbound tagged proxy and route app queries through the core’s DNS. Update client-generated configs through the appropriate editor and check the final result; don’t overwrite your existing config and run this snippet as-is.
{
"dns": {
"servers": [
"https://1.1.1.1/dns-query"
],
"queryStrategy": "UseIPv4",
"disableFallback": true
},
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": [
"1.1.1.1/32"
],
"port": "443",
"network": "tcp",
"outboundTag": "proxy"
}
]
}
}
An IP-based DoH URL is used here to reduce bootstrap dependencies when resolving the upstream’s domain. UseIPv4 limits the address family for this built-in DNS query only; it doesn’t disable system IPv6. This example has no domain-based split routing or app DNS interception rules, so it doesn’t provide global leak protection by itself.
- Match remote upstreams first: Put routing rules for remote DNS connections before any direct-connection rules they might match. Xray checks routing rules in order and stops at the first match.
- Check the default outbound: If no Xray routing rule matches, the first outbound is used. If you want proxy fallback, make sure the first outbound isn’t direct by mistake.
- Don’t mix in local modes: When choosing an upstream, watch for address forms such as
https+local://, which imply local access. Don’t treat them as ordinary remote DoH settings subject to the same routing rules. - Intercept standard DNS: With the right inbound and routing setup, UDP/TCP port 53 can be handled by a DNS outbound. Blocking port 53 alone can break lookups in some apps and won’t cover queries carried over port 853 or HTTPS.
- Make sure the node’s domain can be resolved at startup: If the proxy server uses a domain name, it may need bootstrap DNS before the proxy can connect. Define how this exception is handled to avoid a loop where DNS depends on the proxy and the proxy depends on DNS.
7. Verify the setup with browser results, logs, and disconnect tests
After making changes, don’t rely on a screenshot of the test page alone. Record the client version, operating mode, network type, remote upstream, and test app. First verify a single upstream with full-proxy routing, then restore mainland China domain rules, browser Secure DNS, and per-app rules one at a time. Retest after each change to identify which layer altered the query path.
| Check | How to test | Expected evidence |
|---|---|---|
| Standard DNS traffic | On a physical network adapter, inspect udp.port == 53 || tcp.port == 53 | No plaintext queries violate your intended rules; assess loopback and virtual adapter traffic separately |
| Remote upstream routing | Temporarily increase the log level and inspect upstream connections and outbound tags | Remote DNS connections use the intended proxy outbound |
| Browser-specific DNS | Test with Secure DNS turned off and on | Any change in results can be explained by the selected upstream and routing |
| IPv6 coverage | Retest on a dual-stack network and check queries on the physical adapter | No IPv6 DNS traffic bypasses your policy |
| Proxy failure | Disconnect the proxy and request a new domain | Behavior matches your chosen policy: block access or allow direct connections |
Seeing no port 53 traffic on the physical adapter only means you didn’t observe this type of plaintext DNS. Browser DoH may still connect directly over port 443. To assess encrypted queries, check the upstream destination, connection route, and logs. Restore the usual log level after testing, and remove subscription URLs, user identifiers, and visited domains before sharing logs.
Why does the test page still show a nearby resolver when I use DoH?
Public DNS may use a nearby anycast node, so its location doesn’t tell you whether the query went direct. First identify the provider shown by the test, then check whether the DoH connection goes through the proxy. If only browser results differ, start by checking the browser’s own Secure DNS setting.
Do I still need a remote DNS server with FakeDNS enabled?
Usually, yes. FakeDNS handles synthetic addresses and domain mappings, not every real DNS lookup. Direct destinations, certain address queries, and other cases that need real IPs may still require an actual DNS upstream.
If a DNS leak test always passes, does that prove no apps can leak?
No. A test only verifies behavior within its scope at that moment. Background apps, app-specific DoH, per-app exclusions, network changes, and access after the VPN stops all need separate checks. A reliable setup has understandable traffic paths and predictable failure behavior; seeing a single country on the results page isn’t proof.