The conclusion first: verifying that a VPN is working needs no specialist tools — just three checks in order. Has the exit IP that outside sites see actually changed? Who resolves your domain names? Which path does the target app's traffic really take? If any one of the three isn't going through the route, it doesn't count as working, even if the client keeps showing “Connected.”
A client showing “Connected” is only local state
The moment you hit Connect, the client flips to “Connected.” That state only means the local process has loaded its configuration and opened a session with the route endpoint — it doesn't mean your traffic is actually leaving through that route. Two more links sit in between: whether the system hands traffic to the tunnel, and whether DNS resolution follows it.
Break “working” into three layers and the picture gets much clearer:
- Local state: the process is running, the interface shows connected, and there are no errors.
- Tunnel takeover: a virtual adapter or system proxy setting sends the target traffic into the tunnel instead of letting it leave directly through the local NIC.
- Exit and resolution: the source address outside sites see is the route's exit, and DNS resolution is handled on the tunnel side too.
If any one of the three layers isn't connected, you get the classic “the client says connected but traffic isn't on the route” situation. The client's working mode decides how much it takes over: system proxy mode only affects programs that read the system proxy settings — most browsers qualify, but command-line tools and some apps with their own network stack may not. Virtual adapter mode takes over the whole machine's traffic, or the traffic you specify through routing rules; it covers more, and it's the precondition that makes the three-step verification below line up.
| Verification layer | What to check | Pass criteria | Common misreads |
|---|---|---|---|
| Local state | Client process and connection badge | Shows connected, no errors | Treating “Connected” as the whole chain working |
| Tunnel takeover | Routing table and virtual adapter | A default route points to the tunnel, or a rule matches the target traffic | In system proxy mode, only the browser uses the proxy |
| Exit IP | The address and location an outside echo service reports | Matches the region of the selected route | Only the browser was tested, not other programs |
| DNS resolution | Who sends the resolution request | Resolver location matches the exit region | The exit changed, but a local recursive resolver still handles queries |
| Per-app | The target program's actual exit | Apps that should use the route actually do | Routing rules match only domains, missing the process or UDP traffic |
Step 1: Check the exit IP to see where traffic leaves
The exit IP is the most direct check and the hardest one to fool yourself with: the source address an outside site sees is either your local network or the route's exit — there's no ambiguity. Before testing, disconnect and record a baseline, then connect and test again; compare the two results.
Opening an IP echo page in a browser gives you a quick answer, but the browser may have proxy extensions installed or may have cached the previous response. For a cleaner result, query from the command line, which isn't affected by browser settings:
# macOS / Linux
curl -4 https://api.ipify.org
curl -6 https://api64.ipify.org
# Windows PowerShell
Invoke-RestMethod -Uri "https://api.ipify.org?format=json"
The full sequence is:
- Disconnect and record your local exit IP, its location, and the ISP (ASN) as a baseline.
- Connect to a route, query again, and confirm both the address and the location have changed.
- Check IPv4 and IPv6 separately; both should point to the route's exit, rather than one going through the route and the other connecting directly.
- Test with a second echo site to rule out a single site's misreading.
The exit IP's location depends on which route you actually selected. One country can have several routes, with different cities and ISPs, so the ASN you see will differ too. If the location doesn't match what you expected, first confirm the selected node in the client, then decide whether the verification method itself is the problem.
Step 2: Check for DNS leaks and resolver location
Your exit IP may have changed while DNS resolution stays local: the query never enters the tunnel and is handled by the recursive resolver your local network provides. The result is that outside sites see an address abroad, but when they judge your location by domain name they get a local answer — showing up as the wrong content region, extra verification steps on some services, or sites that simply won't load.
How to see which resolver handled the query
Start with any DNS leak test page and note the resolver address and location it reports, then cross-check from the command line. Both commands below return the resolver that handled the query; compare it with your exit IP:
# macOS / Linux
dig +short TXT whoami.ds.akahelp.net
# Windows
nslookup -type=TXT whoami.ds.akahelp.net
Three common reasons resolution skips the tunnel
- Encrypted DNS is on in the system or browser: with DoH / DoT enabled, queries go straight to the chosen public resolver, bypassing the DNS settings the tunnel pushed.
- The tunnel only takes over TCP traffic: DNS queries use UDP port 53 by default, so if your rules only cover TCP 80 / 443, resolution leaves locally.
- A routing rule sends resolution direct: when rules match by domain or IP, the query hits the direct branch.
Secure DNS / encrypted DNS in the browser and third-party DNS tools installed on the system both make resolution results look different from what the tunnel actually does. Turn them off first; only then do your test results mean anything.
The fix differs slightly by platform: on desktop, turn on “DNS through tunnel” in the client or use the tunnel's built-in resolver, then retest. On Android, if the system's Private DNS is on, queries go to the encrypted resolver you specified and may differ from the one the tunnel pushes — set it to Automatic before verifying. On iOS, if you've installed a configuration profile with DNS settings, check whether it overrides the client's resolver settings.
Step 3: Per-app verification, so only the traffic that should use the route does
Even with the first two steps passing, you can still hit “the browser is fine but one app isn't using the route.” The cause is routing rules: they decide which traffic enters the tunnel based on domain, IP range, or process name, and writing them correctly doesn't guarantee the target app matches. Per-app verification exists to test that link on its own.
- Temporarily switch the client to global mode (all traffic through the route) and open the target app to see whether it works.
- Working in global mode but failing in rule mode means the problem is in the rules, not the route itself.
- Switch back to rule mode and fill in the gaps one by one: the target domain, any required IP ranges, and the process name.
- For voice, multiplayer, and live-streaming apps, make sure the rules cover UDP; otherwise you get “pages load but voice won't connect.”
- When you're done testing, switch back to your everyday mode — don't leave it on global long term.
The trap here is protocols and UDP. Whether Shadowsocks, VMess, Trojan, or VLESS can forward UDP depends on the specific server and client implementations; Hysteria2 and TUIC are built on QUIC and run over UDP themselves, so forwarding UDP traffic is more natural. If your rules only proxy TCP, the browser's QUIC requests (UDP 443) either fall back to TCP or go direct — which shows up as “the connection works, but one site behaves as if it isn't on the route.”
Looks connected but isn't: six common cases
Here are the most common failure symptoms from the three-step check in one table — when something looks off, work down the rows.
| Symptom | Likely cause | Fix |
|---|---|---|
| The client shows connected, but the exit IP is identical to when disconnected | System proxy mode only covers the browser, or no rule matches the current program | Switch to global mode and retest; once you know the coverage, go back to rule mode |
| Pages load, but voice, multiplayer, or live streaming won't connect | UDP traffic isn't entering the tunnel; QUIC and voice both use UDP | Make sure the protocol and rules cover UDP; if needed, disable QUIC in the browser before testing |
| The exit IP changed, but some sites still show local content | DNS resolution isn't going through the tunnel | Turn off encrypted DNS in the system and browser, switch to in-tunnel resolution, and retest |
| After restarting the client, the exit is local again | Another virtual adapter, firewall, or security suite rewrote the routes | Quit the conflicting software, reconnect, and check the routing table again |
| Only one particular app doesn't use the route | Routing rules match by domain or process and miss it | Add the matching domain or process to the rules, or verify temporarily in global mode |
| IPv6 sites show a local address | The tunnel only covers IPv4; IPv6 goes out directly from the local network | Disable IPv6, or switch to a route that supports dual stack |
Once you've ruled out all six, run through this checklist — only when everything passes is it really working:
- ✅ The exit IP differs between disconnected and connected, and its location matches the selected route
- ✅ IPv4 and IPv6 queries return an exit in the same direction
- ✅ The DNS resolver's location matches the exit region
- ✅ The target app works normally in global mode
- ✅ Back in rule mode, the target app still uses the route
- ❌ Drawing conclusions after testing only the browser
- ❌ The tunnel is on, but IPv6 sites still show a local address
How verification differs across platforms
The three-step order is the same on every platform; what differs is how much system information you can get. Desktop systems let you inspect routes and resolver state, while mobile relies mainly on outside echo pages and the client's built-in connection diagnostics.
Windows
The difference between system proxy mode and virtual adapter mode is most obvious on Windows: the former only affects programs that read the system proxy. route print shows whether the default route points at the tunnel adapter, and ipconfig /all confirms the adapter's state; if the browser has QUIC enabled, turn it off separately before testing UDP scenarios.
macOS
scutil --dns shows the resolver order currently in effect, and networksetup -getwebproxy Wi-Fi confirms whether the system proxy is being taken over; pair them with curl -4 and curl -6 to finish the exit check.
iOS and Android
Mobile has no command line, so verification relies on a browser echo page plus the connection status inside the client. On Android, if Private DNS is on, set it to Automatic before testing; on iOS, if you've installed a configuration profile with DNS settings, check whether it overrides the client's resolver settings.
Linux
ip route for the default route, resolvectl status for the resolver, and curl for the exit — three commands cover all three verification steps.
Client interfaces differ by platform, but routes are imported through a subscription link on all of them: log in, copy the subscription URL from the dashboard, import it into the client, then verify in the order exit IP → DNS → per-app. A subscription link is the same as account credentials — don't screenshot it or paste it in public.
What to do after verification passes
Verification itself takes only a few minutes, but keeping the results saves far more time the next time something goes wrong.
- Record a baseline: one line each for the exit IP while disconnected, the exit IP after connecting, and the resolver's location. When something looks wrong, compare against it and you'll know instantly which layer failed.
- Retest after changes: after switching networks, a major OS update, or installing new security software, run the three steps again.
- Wrong region? Switch nodes first: different routes have different exit locations, so switch nodes before deciding it's a client settings problem.
- Keep your subscription link safe: it's the same as account credentials, so reset it in the dashboard if it leaks.
This service offers 120+ countries and 180+ routes, no limit on the number of devices, and a 30-day money-back guarantee. Route status is on the servers page; if one of the three steps keeps failing, work through the troubleshooting guide item by item.