Back to blog
·9 min read·productdevbook

How to Monitor VPN Bandwidth on macOS

How to see exactly what your VPN tunnel is carrying on macOS: per-app traffic, encryption overhead, and leak detection.

  • VPN
  • macOS
  • Bandwidth
  • Privacy

You connect to your VPN, run a web check that reports the right country, and assume everything is now tunneled. Two days later you notice that one of your apps — say, an old chat client or a sync agent — has been talking directly to the public internet the entire time, ignoring the tunnel completely. The VPN was on. The leak was in a process that bound to the physical interface before the tunnel came up and never let go.

Monitoring VPN bandwidth on macOS is partly about confirming the VPN is doing its job and partly about catching the apps that quietly bypass it. This post covers what utun interfaces actually are, how to read VPN traffic with built-in tools, how to detect leaks, and how to measure the overhead the tunnel adds. If you've been searching for monitor vpn bandwidth mac because the VPN's own dashboard isn't telling you enough, the toolkit below answers the harder questions.

What utun interfaces are

When a VPN client connects on macOS, it creates a virtual interface — usually named utun0, utun1, utun2, etc. ("utun" stands for "user tunnel.") The VPN process reads packets that the OS routes to that interface, encrypts and encapsulates them, and writes the resulting wrapped packets out through your physical interface (en0 for Wi-Fi, typically).

Run this in Terminal to see what's currently up:

ifconfig | grep -E "^(en|utun)" -A 3

You'll see something like:

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        inet 192.168.1.42 netmask 0xffffff00 broadcast 192.168.1.255
utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
        inet 10.8.0.6 --> 10.8.0.1 netmask 0xffffff00

en0 is your real network. utun0 is the VPN. Some VPN clients create multiple utun interfaces (one for the data plane, one for control); some create utun9 or higher to avoid collisions with iOS-style personal hotspot tunnels.

How to monitor vpn bandwidth mac traffic with nettop

nettop is built into macOS and is the most direct way to see which interface a process is using. The relevant invocation:

sudo nettop -P -m route

This shows each process's connections grouped by route. A process talking through your VPN will show its traffic via the utun interface; a process bypassing the tunnel will show via en0 (or en1 if ethernet).

Watch nettop for a minute, then ask: which apps are using utun0 and which are using en0? If you intend everything to go through the tunnel and you see Slack on en0, that's a leak.

The flag -P aggregates per process; -m route shows the route column. Add -x for byte counts. Add -c and a delay for periodic refresh, e.g. nettop -P -c 2.

What ova shows for VPN traffic

A per-app monitor like ova sees the same kernel statistics nettop does and rolls them up over time. The bandwidth attributed to "Slack" in ova includes whatever Slack sent — over en0 or utun0 doesn't change the per-process total. So ova answers "how much did Slack use?" cleanly. It does not currently break the per-app number down by interface — if you need that level of detail, nettop is the tool.

For most VPN users that's fine. The questions you usually want answered are:

  • "Is my VPN client itself using the bandwidth I expect?"
  • "Did anything spike in the last hour?"
  • "Which app is currently the heaviest?"

ova gives you all three at a glance, with helper-process folding so a Slack helper PID doesn't show up as a separate row. The VPN client itself (Tailscale, Mullvad, ProtonVPN, NordVPN, etc.) appears as its own line, and its number is the wrapped/encrypted total going out your physical link.

Per-app history
ova retains scrubable history so you can compare bandwidth before and after enabling the VPN — the difference is the encryption overhead.

Detecting leaks

A VPN leak is when an app's traffic bypasses the tunnel and goes directly to the internet. Causes include:

  • The app cached a route before the VPN came up and is still using it.
  • The VPN doesn't route certain destinations (LAN, multicast, DNS to a specific server).
  • macOS's "exclude local network" toggle is doing what it says.
  • The VPN is split-tunneled and a particular app is in the bypass list.
  • IPv6 is enabled and the VPN only routes IPv4 (a common cause).

The diagnostic loop:

  1. With the VPN connected, run nettop -P -m route and watch for any process showing en0 traffic that you expected to be tunneled.
  2. Cross-check with ova for the per-process bandwidth. If a process shows traffic in ova but no utun rows in nettop, it's leaking.
  3. Confirm at the network level: visit ipleak.net or dnsleaktest.com from a browser. The reported IP should be the VPN exit, not your home/office.
  4. For DNS specifically: run scutil --dns | grep nameserver — the listed nameservers should be your VPN's, not your ISP's.

For IPv6 specifically, the safest setup is either a VPN that explicitly routes IPv6 or disabling IPv6 system-wide while connected. Disabling per-network: System Settings > Network > your network > Details > TCP/IP > Configure IPv6 > Link-local only.

Measuring VPN overhead

VPNs add overhead in two ways: throughput (you get less of your actual line speed) and latency (each round trip goes through an extra hop).

Throughput overhead

The encryption tax depends on the protocol:

  • WireGuard: typically 5 to 10 percent overhead on a fast link. Hardware-accelerated on Apple Silicon.
  • OpenVPN: 15 to 30 percent overhead. CPU-bound, slower than WireGuard at high speeds.
  • IKEv2/IPsec: 10 to 20 percent overhead. macOS native support.
  • Proprietary protocols (Lightway, NordLynx based on WireGuard, etc.): roughly WireGuard-level efficiency.

To measure: run a speed test with the VPN off, note the result. Run the same test with the VPN on, to a server in the same metro area as the off-test endpoint. The ratio is the overhead. Use ova during both tests — the per-app traffic shown for the speed test client should be the application-layer throughput; the system-wide rate during VPN tests is higher because of encryption framing.

Latency overhead

Run ping 8.8.8.8 with VPN off, note the steady-state RTT. Connect VPN, run ping 8.8.8.8 again. The difference is the round-trip cost of encrypting, traveling to the VPN exit, and back. Typical figures:

  • VPN exit in same city: +5 to +15 ms.
  • VPN exit in another country: +50 to +200 ms depending on geography.
  • VPN exit on a different continent: +150 to +400 ms.

This is unavoidable physics for the most part — you can't tunnel to Tokyo and have it not cost you the round trip.

Identifying the VPN's own bandwidth use

The VPN client process itself shows up in ova as its own row — "Mullvad VPN," "Tailscale," "ProtonVPN," etc. The number you see there is the encrypted, wrapped total going out your physical link. That's the right number for "how much real internet bandwidth is the VPN consuming."

A useful sanity check: at any moment, the VPN's reported bandwidth should be approximately equal to the sum of all other apps using it, plus a small percentage for encryption overhead. If they're wildly different, something else is going on — split tunneling, leakage, or the VPN client doing maintenance work (key rotation, peer discovery).

See ova in action

A glance-able menu bar bandwidth monitor — local, signed, ~3 MB.

Download for macOS

Always-on VPN: pitfalls

Several VPN clients offer a "kill switch" or "always-on" mode that blocks all traffic if the tunnel drops. Useful, but with surprises:

  • The first few seconds after wake-from-sleep may have unblocked traffic before the tunnel re-establishes. Some clients explicitly hold this; others don't.
  • Wi-Fi network changes (moving from home to coffee shop) trigger a brief disconnect. The kill switch should hold but the implementation varies.
  • Some apps have aggressive reconnect logic — they retry every 100 ms when the tunnel is down. That's a bandwidth spike at reconnect time once the tunnel comes back.

Watch ova the moment after waking from sleep with VPN on. The pattern is usually: VPN client itself shows a small surge as it re-handshakes, then within 5 to 30 seconds individual apps start surging as they reconnect their own sockets. If you see a 200 MB spike on wake, that's typically Slack/Discord/iMessage all catching up at once.

Per-app routing and split tunnels

Some VPN clients support routing only specific apps through the tunnel. The use case is "send my torrent client through Mullvad, but let Slack go direct so video calls don't add VPN latency."

Verifying split tunnel rules with nettop:

sudo nettop -P -m route

The split-tunneled apps should show only en0 traffic; the tunneled ones should show only utun. If both appear for the same process, the rules aren't being enforced cleanly — usually because the app holds long-lived sockets that pre-date the rule change. Restart the app to clear them.

Monitoring multiple VPN connections

Power users sometimes run two VPNs at once — for instance, Tailscale for accessing internal company services plus a commercial VPN (Mullvad, Proton) for general internet privacy. macOS handles this via routing tables: more specific routes (Tailscale's 100.64.0.0/10) win over broader ones (the commercial VPN's default route).

You'll see multiple utun interfaces in ifconfig. Use netstat -rn | head -30 to read the routing table — the first matching route wins. ova shows total per-app bandwidth without distinguishing which tunnel; for that, nettop's -m route view is the reference.

What to do next

A 10-minute audit to monitor vpn bandwidth mac end-to-end:

  1. Connect the VPN.
  2. Open ova in the menu bar, note the apps currently active.
  3. Run sudo nettop -P -m route in Terminal.
  4. Cross-check: every app showing significant bandwidth in ova should have its connections appearing under utun0 (or whichever utun your VPN uses) in nettop. Any en0 traffic from those processes is a leak candidate.
  5. Visit ipleak.net to confirm IP and DNS exit through the VPN.
  6. Disconnect, run a speed test, reconnect, run another. Compute the overhead.

You'll come out of this knowing whether your VPN is actually doing what you think it is, what its overhead actually costs, and which apps to keep an eye on. That's a stronger answer than the "Connected" indicator in your VPN client's menu bar.