your vpn says connected. is anything actually going through it?
updated · by Anton Shakirov
open Terminal and run route -n get default. if the interface line says utun-something, the whole of your traffic is leaving through the tunnel; if it says en0 or en1, it is leaving through Wi-Fi or Ethernet and the vpn is decoration. that is the answer for most people. the two checks after it take another minute: whether the tunnel is carrying anything, and what address the outside world sees. that is where the surprises live.
check if the vpn is working: three commands, one minute
a vpn can be «connected» and carry nothing, carry half your traffic, or carry all of it while dns still goes to your isp. the word in the client covers every case. macOS knows which one you are in and says so in three places.
- route -n get default. the interface line names the door your traffic leaves through. utun7 (any utun number) means the tunnel; en0 means Wi-Fi or Ethernet, and nothing is being tunnelled by default. netstat -rn -f inet shows the same: two default rows, utun and en0, and the first one wins.
- scutil --nc list gives you the tunnel's name and its state; then scutil --nc statistics "name", wait five seconds, run it again. BytesIn should climb; here it went 154,447,263 → 154,763,044 in those five seconds. counters that sit still mean the tunnel is up and empty.
- curl https://api.ipify.org prints the address the rest of the internet sees. it should belong to the vpn provider, not to your home isp. any «what is my ip» page in a browser does the same job; the Terminal version just cannot be confused by a cached session.
if nothing loads at all, that is a different fault with its own page — this one assumes pages open and asks through what: fix a vpn with no internet
every flag of scutil --nc, from the manual page: scutil(8)
what «connected» in the client actually means
scutil --nc status "name" prints Connected for a tunnel that moved thirty megabytes this minute and for one that died an hour ago. there is no field for «carrying traffic»; the status describes the moment the tunnel was negotiated, and the client shows the same word because it asks the same system.
ifconfig sets a trap: a Mac keeps several utun interfaces regardless of any vpn (here eight, utun0 to utun7) and only one has an inet address. that one is the tunnel; seven without an address are not seven vpns.
vpn connected but ip not changed: where the traffic went instead
if the default route is on en0 while the client says connected, the tunnel came up and never took the route. it is not broken; nobody told it to carry everything. which switch does depends on the kind of vpn.
- for a built-in L2TP configuration the switch is in System Settings → VPN → ⓘ next to the service → Options → «send all traffic over VPN connection». Apple documents that this option exists only for L2TP over IPSec: for every other type the routes are dictated by the server when the connection is negotiated, and there is nothing to tick on your side.
- for a client with its own app, which is most of them, look for «split tunnelling», «exclude apps» or «bypass» in the client's settings. a split tunnel is a connected vpn whose default route is deliberately on en0, and your ip does not change by design.
- for one specific site that keeps seeing your real address, ask about that site: route -n get example.com names the interface for that destination alone, which is the answer when the default route is fine and one host is still leaking.
a tunnel that takes the route on connect and loses it after the lid closes is a different fault with its own page: reconnect a vpn that drops after sleep
on the option and which vpn types have it, from Apple: change options for l2tp over ipsec vpn connections on Mac
the routes a work vpn leaves out on purpose
scutil --nc status "name" has an ExcludedRoutes block. on this Mac it lists 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 against en0 — the private ranges. route -n get 192.168.50.1 confirms the router is reached over Wi-Fi, never through the tunnel. that is why the printer still prints with the vpn up, and it is not a leak: an address in those ranges leaving over en0 is the configuration doing what it says.
is dns going through the vpn too?
the outside address can be right while every name you look up is still answered by your isp. scutil --dns settles it: resolver #1 should be the tunnel's nameserver with if_index pointing at the utun interface — here nameserver[0] : 198.18.0.2, if_index : 25 (utun7). if resolver #1 is your router on en0 while the tunnel is up, names leave outside it, and the fix belongs to the client: a dns setting it should have pushed and did not.
ipv6 is the other quiet exit. many tunnels carry ipv4 only; if your network hands out a routable ipv6 address, sites that prefer it reach you over en0. route -n get -inet6 default says whether an ipv6 default exists at all — here Wi-Fi has only a link-local address, the answer is «not in table», and there is no exit to worry about.
when the one-off check is enough, and when it stops being
before one session that matters, a bank or a work share, the three commands above are the whole answer. run them, read utun and a foreign address, get on with it.
it stops being enough the moment it has to be repeated: the tunnel that carried traffic at nine is not required to carry it at eleven, and the client says connected either way. the free route costs attention rather than money: you have to remember to run them, again, every time you wonder.
how hop shows whether the vpn is carrying traffic
hop lists every vpn your Mac knows about and gives each one a switch. the list is read from System Settings, so whatever client you use is already in it. while a tunnel is up, a small dot sits on the menu bar icon.
- green — the tunnel is up and traffic is going through it.
- orange — the tunnel is on and nothing is coming back through it. that is the second command above, running all day with the panel closed.
- the panel marks the row it means, so with several configurations you know which one went quiet.
the switch itself, and what else it does with the list of tunnels: vpn switcher
| what you are doing | the built-in route | with hop |
|---|---|---|
| checking once before something that matters | route -n get default and curl to an ip service; a minute, done | not needed; run the two commands |
| finding out whether the ip the outside sees is the vpn's | curl https://api.ipify.org or any «what is my ip» page | hop does not check this: the dot is about the tunnel, not the address |
| checking where dns goes, or whether a split tunnel is leaving a host out | scutil --dns, route -n get host | hop does not check this either |
| a tunnel that goes quiet mid-afternoon while the client still says connected | scutil --nc statistics twice, if you thought to run it | the dot turns orange on its own |
| three configurations, and which one is up right now | scutil --nc list | one switch per row, state shown in the panel |
the tunnel is held by macOS, not by hop, so quitting the app changes nothing about your connection. clicking a name opens that vpn's own window for the times you need it. the dot can be turned off in settings; the switches keep working without it.
why a dot on a menu bar icon is the whole interface here: what macOS 26 changed for menu bar apps
when the vpn still is not carrying your traffic
- the ip page shows your own city while route says utun. check what the page is measuring: a site remembering you from before the tunnel came up, or Safari with iCloud Private Relay on: the relay hands sites a temporary address of its own, so its answer is not about your vpn. curl from Terminal has neither problem.
- the default route is utun and BytesIn still does not move. the tunnel is up and empty: disconnect and reconnect it once, and if that is a daily event, the tunnel is dying with sleep rather than at random.
- two clients installed at once fight over the routing table, and the loser's «connected» is a lie. remove the one you no longer use, properly, with what it left behind.
- the route flips back to en0 a few seconds after every connect. something else is rewriting the routing table: a second vpn, a firewall app, a proxy tool. quit them one at a time and run route -n get default after each.
what Private Relay does to the address a site sees, from Apple: about iCloud Private Relay
how people describe the symptom in their own words, on Apple Community: vpn connected but traffic goes directly
what a vpn client leaves behind, and how to take all of it out: uninstall an app with its leftovers
the tool that does it: app uninstaller
frequently asked questions
- how do i check if my vpn is working on Mac?
- route -n get default in Terminal: utun-something means traffic leaves through the tunnel, en0 means it does not. then curl https://api.ipify.org; the address should be the provider's, not your isp's. under a minute for both.
- how do i know if traffic is actually going through the vpn?
- the route says where packets are sent, the counters say whether any are moving. scutil --nc statistics "name" twice with a few seconds between them: BytesIn climbing means the tunnel is carrying traffic. still counters with a utun default route mean the tunnel is up and empty.
- why does my vpn say connected but my ip address has not changed?
- the tunnel is up and the default route is not on it. for a built-in L2TP configuration that is the «send all traffic over VPN connection» option; for other types the routes come from the server, and for a client app it is usually a split-tunnel setting. route -n get default tells you which case you are in first.
- does the vpn icon in the menu bar mean traffic is going through it?
- the client's own icon means the tunnel was established. it does not check whether anything is moving now. hop's dot is the exception it was built for: green while traffic goes through the tunnel, orange when the tunnel is on and nothing is coming back.
- how do i check for a dns leak on Mac?
- scutil --dns and look at resolver #1. with the tunnel up it should be the vpn's nameserver bound to the utun interface through if_index. if the first resolver is your router on en0, names are answered outside the tunnel even though pages travel inside it.
- why does my local printer or nas still work with the vpn on — is that a leak?
- usually no. scutil --nc status prints an ExcludedRoutes block, and the private ranges (10/8, 172.16/12, 192.168/16) are commonly listed against en0 on purpose. traffic to your own network staying on Wi-Fi is the configuration, not a fault.
- does hop check my ip address or dns?
- no. hop shows two things about the tunnel the system holds: that it is up, and whether anything is coming back through it. it also switches it. the outside address and the resolver are the two commands above, and they stay yours to run.
the tool behind this
vpn switcherevery vpn your Mac knows about, one switch each.done with vpn
other things people do
- your vpn says connected. nothing loads.vpn switcher
- the Mac woke up. the tunnel did not.vpn switcher
- no built-in way to see how hot your Mac issystem monitor
about the author

Anton Shakirovmakes hop
makes hop and every page on this site. eighteen tools under a single menu bar icon, MIT licensed and open source. reads and answers issues and email himself.