How to Verify Your VPN Really Works: Exit IP, DNS and Per-App Checks
Connected isn't the same as routed correctly: check the exit IP, check DNS, verify per-app routing — plus the common cases where it looks connected but isn't.
The client's status light is on, yet pages still look exactly as they did before — this is the most common form of the question about how to tell whether a VPN is really working. The answer isn't to stare at the connection status again; it's to check three layers in order: whether the exit address really changed, whether domain lookups follow the tunnel, and whether the app you're using is actually inside the proxy. Only when all three pass is traffic really going the right way. Stop after the first step and the layers you skipped are usually exactly the ones that are broken.
Why Connected Doesn't Mean It's Working
The status light tells you one thing only: the tunnel from your device to the node is up. It doesn't tell you whether traffic is being captured, which rule it follows once captured, or whether DNS lookups go with it. Those three are decided by the client's capture mode, its routing rules and its DNS settings — and if any one of them is off, the symptom is always the same: it says connected, but nothing is going through.
There are three common capture modes. System proxy only affects programs that read the system proxy settings — browsers usually do, many desktop clients don't. A TUN virtual adapter captures IP traffic at the network layer and covers the most ground. Per-app proxy sends only the apps on its list into the tunnel; everything else connects directly as before. How you test whether it's working depends on which mode you're in.
The protocol is a separate layer. Shadowsocks, VMess, VLESS and Trojan wrap traffic and deliver it to the node; Hysteria2 and TUIC run over QUIC and carry traffic as UDP, which holds up better on poor networks. The protocol decides how traffic is sent, not which traffic is sent — so switching protocols won't fix a routing mistake, it only improves link quality.
A subscription link is just a carrier for the node list. After you import it, the client builds its configuration from the nodes in that list; if the subscription expires or the link breaks, the list stops updating, but nodes already saved locally can still complete a handshake. In that case the status light comes on too, while nothing actually gets forwarded.
Step 1: Check the Exit IP and Location
Start with a baseline. Before connecting, open any IP lookup page in your browser, or run a command in the terminal, and write down the current exit address and its location.
# Before connecting: note the exit address and location
curl -s https://ipinfo.io/json
# After connecting: both ip and country should change
curl -s https://ipinfo.io/json
After connecting to a node, check again in a private window. The private window rules out cache and browser extensions — some proxy extensions take over requests on their own, which makes the result look like it has nothing to do with the client.
There are only two criteria: the address changed, and the location matches the region of the node you picked. Only when both hold is traffic really leaving through an overseas exit.
A few cases need to be treated differently. Public geolocation databases disagree with each other, and anycast or multinational broadcast addresses may show a nearby region — that isn't a fault. Streaming platforms use their own databases rather than public ones, so an address can be geolocated correctly while the platform still serves you local content. Conversely, an unchanged address isn't necessarily a failure: in rule-based mode, domestic sites are supposed to use the local exit, so what you need to test is the request to an overseas site.
In rule-based mode, a local address for domestic sites is by design. When you test the exit address, always use an overseas site that is certain to go through the proxy, or switch to global mode temporarily and test again for comparison.
Step 2: Confirm Domain Lookups Aren't Falling Back to Local DNS
A DNS leak means the traffic goes into the tunnel but the domain lookups don't follow — they're sent to your local ISP instead. That has two consequences: the list of sites you visit is exposed to the local resolver, and answers come back based on your local position, so you get an overseas exit address with local content.
Testing is straightforward: open a DNS leak test page, which lists the resolvers that actually answered and where they are. A normal result shows resolvers in the exit region, or resolvers handed out by the provider; an abnormal one shows your local ISP. Use a private window here too, so cached lookups in the browser don't skew the result.
There is one exception in rule-based mode: domestic domains resolving through local DNS is by design and doesn't count as a leak. What matters is the resolver that answers for overseas domains.
The browser's built-in secure DNS (DoH) ignores the system and client DNS settings and queries a third-party resolver directly — a very common reason for an IP that looks right while content stays local. Before testing, check the status of the browser's secure DNS setting, turn it off, and test again for comparison.
IPv6 is the same problem from another side. If the tunnel only captures IPv4, IPv6-capable sites leave through your local IPv6 address, and the test page reports a local address. There are two ways to handle it: disable IPv6 on the system, or let the client capture IPv6 traffic as well.
Step 3: Confirm Per-App and Routing Rules One by One
The third layer is the one people skip, because it isn't on the client's main screen. Per-app proxying means only the apps on the list are proxied: an app that isn't listed keeps connecting directly even with the tunnel up. To check, open the client's per-app list and confirm one by one that the apps you need are on it, then restart the target app after changing the list — most programs read the proxy configuration only once, at launch.
Differences Between Platforms
On desktop, system proxy and TUN are the two common modes: TUN covers every program, while system proxy covers only programs that read the system settings. Android clients generally offer per-app proxying. iOS is constrained by the system and usually works as a single tunnel, with no equivalent per-app switch. On Linux you mostly get command-line tools and system proxy, so you either set the http_proxy and https_proxy environment variables by hand or switch to TUN mode. When the same subscription behaves differently across platforms, this layer is usually why.
How Routing Rules Affect the Verdict
Rules typically match on domain suffix, GeoIP region or process name, and a domain that matches a direct rule never enters the tunnel. The test is simple: switch the client to global mode temporarily and visit the same site. If it works in global mode and fails again in rule-based mode, the problem is the rules, not the node. Line type (IEPL dedicated, relayed, direct) affects link stability and the path taken, not which traffic is proxied — don't mix the two when troubleshooting.
| Layer | How to check | Normal result | Warning sign |
|---|---|---|---|
| Exit address | Look up the address and location before and after connecting | Address changes and the location matches the node's region | Address unchanged, or location doesn't match the node |
| DNS resolution | DNS leak test page | Responding servers are in the exit region or belong to the provider | Responding server is your local ISP |
| Routing rules | Switch to global mode and compare the same site | Global and rule-based results agree | Only global mode works |
| Per-app proxy | Go through the client's per-app list one by one | The target app is on the proxy list | App isn't listed and connects directly |
| IPv6 | IPv6-capable test page | Matches the IPv4 exit, or returns nothing | Returns a local IPv6 address |
Seven Common Cases: Status Looks Fine but Traffic Never Enters the Tunnel
In every case below the status light is fine, yet traffic doesn't go where it should. Matching the symptom is faster than reconnecting again and again.
| Symptom | Likely cause | Fix |
|---|---|---|
| Status shows connected, but the browser still reports a local address | The client is in system-proxy mode and the app ignores system proxy settings; or the domain matches a direct rule | Switch to TUN mode, or add the domain to the proxy rules and retest |
| Exit address is correct, but some sites still show local content | Browser secure DNS goes around the client | Turn off browser secure DNS and retest |
| Only one app doesn't go through the tunnel | That app isn't on the per-app list | Select it, restart the app and try again |
| The test page returns a local IPv6 address | The tunnel only handles IPv4 | Disable IPv6 on the system, or let the client handle IPv6 |
| A new node still won't load, then works a moment later | DNS cache and connection reuse | Retest in a private window or after clearing the cache |
| No overseas site loads at all | Subscription expired, data used up, or the node is down | Check the subscription status, then retest with another node or line type |
| Connecting reports a certificate or time error | System clock is too far off, so the handshake fails | Sync the system time and reconnect |
A Complete Self-Check List
Here are the three layers as a checklist you can follow. Run through it after every node, device or network change — it usually takes two or three minutes.
- ✅ Note your local exit address and location before connecting, as a baseline.
- ✅ After connecting, recheck the exit address in a private window to rule out cache and extension interference.
- ✅ Use a DNS leak test to confirm the responding server isn't your local ISP.
- ✅ Know whether you're in global or rule-based mode, and which rule the target domain follows.
- ✅ Go through the per-app list for the apps you use, then restart them.
- ✅ Turn off or align the browser's built-in secure DNS so it can't go around the client.
- ✅ Check the subscription expiry and remaining data, and confirm the node list is current.
- ✅ Sync the system clock so the handshake doesn't fail.
- ❌ Assuming it works just because the client's status light is on.
- ❌ Judging the result by refreshing the same tab over and over.
- ❌ Using latency or bandwidth numbers to judge the exit — they measure different things.
Make the Three Steps a Habit
The order of the three steps can't be swapped: first confirm the exit address changed, then that lookups follow the tunnel, and finally that the app you're using is inside the proxy scope. Getting the order wrong costs you a misdiagnosis — check only the first step, assume all is well, and the other two layers stay broken in daily use, showing up as sometimes it loads and sometimes it doesn't.
Bottom line: exit address, DNS resolution, per-app and routing rules — all three layers must pass before the VPN is really working. If any layer looks wrong, run a global-mode comparison test first; that tells you whether the problem is a rule, DNS or the app itself, instead of switching nodes back and forth.
The service currently offers 90+ countries / 160+ lines, with clients for Windows, macOS, iOS, Android and Linux, no device limit, no logs, and a 7-day no-questions-asked refund; sign-up needs only a username and password, with no email address required. After changing nodes, run the three steps again — it saves more time than going by feel.
VPNFH
90+ countries / 160+ lines, no device limit
Sign up with no email address, no logs, 7-day no-questions-asked refund. After switching nodes, run the three steps again before you carry on.