Getting a VPN working on macOS is not about tapping Connect. Three things decide whether it works: whether the system extension was approved, whether the subscription actually imported, and whether traffic really goes through the route. This guide follows the install order and gives a check you can reproduce at every step, so nothing rests on guesswork.
These are the figures this article works from. The capacity, pricing and refund window mentioned in the steps below all follow them.
System VPN vs. client: sort out the routing mode first
macOS offers two completely different ways to connect. Work out which one you are using first, or the steps below will not line up.
The first is the VPN configuration built into macOS, added under System Settings → Network → VPN, which supports standard protocols such as IKEv2 and L2TP over IPSec. Once it is configured, the system brings up a utun interface and takes over all traffic, with no extra client needed. The trade-off is no split routing: everything goes down the same tunnel.
The second is the client that comes with a subscription service. It builds a tunnel through Network Extension and opens a local proxy port, then decides by domain or region which traffic uses the route and which goes direct. For cross-border access, this is the path almost everyone takes.
| Connection method | Traffic coverage | Permission required | Best for |
|---|---|---|---|
| Built-in VPN configuration | Global, all apps | Confirmed once when adding the profile | One fixed route, no split routing needed |
| Client TUN mode | Global, with rule-based split routing | Network Extension + System Extension | Browser, Terminal and desktop apps all use the route |
| Client system proxy mode | Only apps that read the system proxy settings | Usually just a Keychain approval | Occasional use, browser only |
None of the three is better than the others; it is about fit. If you need one fixed route and no split routing, the built-in configuration is enough. If the browser, Terminal and desktop apps all need to use the route, choose TUN mode. For a quick session, system proxy mode is the lightest.
Download and install: signature and notarization first
Download the installer only from the provider's official site. When you open an app, macOS checks two things: the developer signature and Apple's notarization. An installer with a mismatched signature or no notarization is blocked, with a message saying Apple cannot check it for malicious software.
The right order is this:
- Download the disk image or installer and double-click to mount it;
- Drag the app into the Applications folder instead of running it from the mounted image;
- If the first launch is blocked, go to System Settings → Privacy & Security, click Open Anyway at the bottom of the page, and confirm once more;
- Do not work around the prompt by turning Gatekeeper off, which amounts to letting every unsigned program through.
On Apple Silicon machines the native client is a universal binary. If the installer is Intel-only, macOS runs it through Rosetta. It works, but it adds a layer of overhead, so for long-term use switch back to the native build.
Permissions: three prompts and one switch
Network apps do not work without permissions, and the prompts often appear only once, so dismissing them means they are gone. After installing, check these three places.
Network Extension
The first time you click Connect, macOS asks whether an app may add a VPN configuration and requires Touch ID or your login password. What you agree to here is permission for it to build a tunnel.
System Extension
Since macOS 11, clients generally use a System Extension instead of the old kernel extension. After installation, System Settings shows a notice that an extension was blocked from loading; click Allow, and on some versions you need to restart once.
Login Items & Extensions
On macOS 13 and later, System Settings → General → Login Items & Extensions shows the network extension switch, so confirm it is on.
Incomplete permissions show up in three typical ways: the Connect button spins forever; the interface says connected but the exit IP has not changed; the client log mentions a provider failing to start. When that happens, go back to the three places above instead of reinstalling over and over.
Network extension permission hands all traffic on the machine to that program. Before you approve it, make sure the installer came from an official source, and do not click Allow for a client of unknown origin.
Import the subscription: from link to route list
A subscription link is usually an https address followed by a long token. It is both configuration and credential.
- Copy the subscription link from the provider dashboard, and do not pick up stray spaces or line breaks;
- Open the client's Subscriptions or Profiles section and choose import from URL;
- Paste the link, give the profile a name you will recognise, and save;
- Update it once manually and wait for the route list to appear;
- Turn on auto-update and set the interval to 24 hours.
If the import reports success but the list is empty, it is usually a format mismatch. The subscription may return a base64-encoded node list, Clash YAML or sing-box JSON, and the client has to be told the right type to parse it. Another common cause is a link truncated by a chat app, so copy it again.
A leaked subscription link means someone else is using your account. Do not post screenshots of it in group chats and do not run it through online converters; if you suspect a leak, reset the subscription address in the dashboard and the old link stops working immediately.
Verify: four commands to confirm the route works
Connected in the client only means the tunnel is up, not that traffic actually uses the route. Open Terminal and paste the four lines below one at a time.
curl -s https://ipinfo.io/ip
route -n get default
scutil --dns | grep nameserver
scutil --proxy
| Check | Command | Expected result |
|---|---|---|
| Exit IP | curl -s https://ipinfo.io/ip |
The returned address differs from your home connection and matches the region of the selected route |
| Default route | route -n get default |
In TUN mode, the interface line points to an interface starting with utun |
| DNS resolver | scutil --dns | grep nameserver |
The first resolver is not your router's or ISP's address |
| System proxy | scutil --proxy |
In system proxy mode, HTTPSProxy points to 127.0.0.1 and a local port |
To confirm DNS is not leaking, run dig +short whoami.akamai.net, which returns the address of the server that actually performed the lookup. If that address belongs to your local ISP, DNS queries are not going through the route, and you need to hand DNS to the tunnel in the client.
Verification comes down to one metric: the exit IP. Once the IP location matches, check DNS; only when both line up is the route really working.
When it will not connect: troubleshoot in order
Connection failures fall into roughly three groups. Working through them in order is faster than reinstalling.
Stuck at Connecting
Check the three permission points first. If those are fine, look at the protocol: Hysteria2 and TUIC run over QUIC and depend on UDP, and hotels, corporate networks and some public Wi-Fi drop UDP 443 outright, so the connection never completes. Switching to a TCP-based protocol such as VLESS, Trojan, VMess or Shadowsocks usually gets through.
Connected but pages will not load
Three common causes. First, DNS is not captured, so domains are still resolved locally, and the lookup either fails or returns an address that does not suit the current route. Second, the system clock is far enough off that the TLS handshake fails; open System Settings → General → Date & Time and turn on automatic setting. Third, a routing rule classifies the domain as direct, so switch that domain to the route temporarily and try again.
Only some apps fail
System proxy mode only applies to apps that read the system proxy settings. curl in Terminal, many developer tools and game clients do not. If you need full coverage, switch to TUN mode or set proxy environment variables for Terminal separately. This is a difference between modes, not a route failure.
- ✅ Exit IP matches the region of the selected route
- ✅ The first resolver in
scutil --dnsis not your local ISP - ✅ After disconnecting, pages go back to a direct connection with no leftover routes
- ✅ Auto-update for the subscription is on, interval 24 hours
- ❌ Do not solve a blocked launch by turning Gatekeeper off
- ❌ Do not post subscription links in public chats or support screenshots
Long-term use: protocol trade-offs and routing rules
Three things are worth setting up once.
Connect on demand
After you close and reopen the lid or switch Wi-Fi networks, the client has to rebuild the tunnel. Connect on demand lets the system reconnect automatically when the network changes, so you do not have to click Connect again.
Protocol trade-offs
TCP-based protocols (VLESS, Trojan, VMess, Shadowsocks) hold up better on lossy networks; QUIC-based Hysteria2 and TUIC give better throughput on high-latency links, provided UDP is not blocked. A single subscription usually includes both, so switching to match the current network is more practical than sticking to one.
Split routing and DNS
Write routing rules domain-first with region as the fallback, and send frequently used sites direct to cut detours. Let the client handle DNS so the system resolver and the client are not running two separate paths.
Reading route types
IEPL runs over a dedicated point-to-point line that avoids congested public internet nodes; relay means an entry node forwards to an exit; direct means the client connects straight to the exit server. The difference is stability and how much detour there is, and which one is faster can only be tested on the network you actually use, since someone else's speed numbers are of limited value.
VPNVL needs no extra configuration for any of this: 120+ countries, 180+ routes, unlimited devices online at the same time; creating an account needs only a username and password, with no email address; monthly plans start at ¥9.9 for 60GB, ¥18 for 250GB and ¥28 for 500GB, with data resetting each month on the day you subscribed; data packs last until used up and never expire; a no-questions refund can be requested within 60 days of the first payment; payment accepts Alipay, WeChat Pay and USDT. The service's privacy policy is no logging.
For most macOS users, three things cover everyday cross-border access: client TUN mode, automatic subscription updates, and an exit IP self-check.