On macOS the usual blocker isn't the protocol, it's system permissions: the client is installed, the configuration is filled in, the menu bar icon is lit, and the browser still won't open international sites. This guide walks through a real setup in the order you'd actually do it — check the macOS version, install the client, approve the system network permission, import the subscription link, verify the exit address and DNS, and finally deal with the handful of prompts that keep coming back. Every step ends with something you can check, so you can tell exactly where you got stuck.
No terminal experience is assumed anywhere in this guide; wherever a command line is involved, the full command is given so you can copy and run it. First, a few baseline facts about VPNAJ, which you'll want later when deciding whether the rest is worth your time:
Before you start: macOS version and account permissions
Open the Apple menu and choose About This Mac to confirm your macOS version. From macOS 13 onward, System Preferences became System Settings, and plenty of older guides still use the pre-rename path, so following them click by click leads nowhere — both paths point to the same place, just under different names. On older versions the entry point for approving system extensions also sits somewhere else, so check before you start clicking.
Approving a VPN configuration requires an administrator account. A standard account gets rejected after entering the password in the prompt, or never sees the Allow button at all. If this Mac was issued by your employer, check first whether a configuration profile is managing network settings — otherwise every later step will stall.
There's no extra hurdle at the account level: an account needs only a username and password, no email address and no verification mail to wait for. The time saved here is far more than what you'd spend retrying things inside the client.
Before installing, quit any other VPN or proxy client. Running two programs that take over networking at the same time on macOS means the routing table and DNS overwrite each other, which shows up as 'connected but nothing loads' and is extremely hard to pin down. On corporate and campus networks, also check port and UDP restrictions — they directly determine which protocols you can use later.
Install: source, format and first launch
The macOS client ships as a disk image (.dmg). Open it, drag the app icon into the Applications folder, then eject the disk image — running it straight from the image means settings are easily lost after quitting, and updates break later on. Make sure you download the macOS build rather than an installer for another platform.
On first launch Gatekeeper often steps in with 'cannot be opened because Apple cannot check it for malicious software'. The file isn't damaged: open System Settings > Privacy & Security, find the blocked item near the bottom of the page, click Open Anyway and confirm once more. If you don't even see the block notice, check whether you're running the app straight from the Downloads folder — move it and try again.
The first time it starts, macOS asks whether the app may add a VPN configuration. This is the standard flow for network extensions: any app that wants to take over traffic at the system level has to get this approval, and the client has no way around it. Don't just click Don't Allow — once refused, the prompt won't come back on its own.
Approve: system prompts and privacy settings
Approval brings two or three prompts in a row. The order isn't fixed, but the handling is the same:
- Add VPN Configuration: click Allow and confirm with Touch ID or your account password. Once approved, the matching VPN entry appears under System Settings > Network — that's the tunnel itself.
- System extension blocked: go to System Settings > Privacy & Security > Security and click Allow. Some versions ask for a restart; the extension only loads after that, and connections keep failing until you do it.
- Notifications and local network: notification permission only affects status alerts, so you can decline it; from macOS 15 onward the system also asks about local network access — declining doesn't affect international routes, but it does affect device discovery and printing on the same LAN.
If you want it to connect automatically at startup, check System Settings > General > Login Items & Extensions and make sure the client is allowed to run in the background. This step is often skipped, and the result is a manual click after every restart — which then gets blamed on the client being unstable.
If the Allow button is greyed out, first check System Settings > General > VPN & Device Management for a corporate configuration profile. Profiles take precedence over personal approval, and until that management is removed the prompt will never appear.
Import a subscription: link, config file and manual entry
A subscription link is an address that returns a node list; the client fetches it on a schedule, so route changes don't require reconfiguring anything. The link usually carries a set of credential parameters at the end — holding the link is equivalent to holding account access, so don't paste it into group chats or public repositories. What comes back is typically a Base64-encoded node list or config file, decoded by the client; all you need to do is keep the link intact.
Importing takes three steps: copy the full link, paste it into the client's Subscriptions or Profiles section, and hit update. The node list only appears after a successful update, and you still need to pick a specific route before connecting. The three common import methods differ as follows:
| Method | Best for | How it updates | Watch out |
|---|---|---|---|
| Subscription link | Everyday use, routes change | One-click update in the client | The link contains credentials — keep it private |
| Config file import | Importing several nodes at once | Requires re-importing the file | Make sure the file comes from a trusted source |
| Manual entry | Single node, troubleshooting | Edit each parameter by hand | Protocol and transport must match the node |
With manual entry, one missing parameter is enough to break the connection: protocol (Shadowsocks, VMess, Trojan, VLESS, Hysteria2, TUIC), server address, port, UUID or password, plus transport (ws, grpc, tcp), TLS, SNI and path. Hysteria2 and TUIC run over QUIC and need UDP; on networks that restrict UDP, a TCP-based protocol is the steadier choice.
When a subscription update fails, check three things first: the link was truncated in a chat app or picked up spaces and line breaks; the system clock is far enough off to break the TLS handshake; the current network can't reach the subscription address at all — that chicken-and-egg case is solved by updating once from a network that works. If the list comes back empty after updating, check whether a middlebox replaced the response with an error page.
One step after importing is often skipped: routing rules. Global mode sends everything through the tunnel, so sites in mainland China take the long way round; rule mode decides by domain and IP, connecting directly for those sites and using the selected route for everything else, which feels better day to day. On macOS, per-app routing is less reliable than per-domain routing — don't spend too much time on it.
Verify: exit address, DNS and per-app tests
A 'Connected' label in the menu bar only means the tunnel is up, not that traffic actually uses the route. The most direct check is the exit address: run the same command before and after connecting.
# run once before connecting
curl -s https://ifconfig.me
# run again after connecting, then compare the two results
curl -s https://ifconfig.me
# show the DNS resolvers the system is currently using
scutil --dns | grep nameserver | head -n 5
If the two results differ and the new address sits in the country of the route you picked, traffic is really going out. The DNS line matters just as much: if the resolver is still your local ISP's address, domain lookups aren't following the tunnel, which is a leak — some sites fail to load or redirect to their local version. A browser's built-in encrypted DNS bypasses the system resolver, so turn it off while testing, or the results won't reflect system behaviour.
Also distinguish system proxy from TUN mode. A system proxy only applies to apps that read the system proxy settings — Safari and Chrome follow it, while curl, git and npm in the terminal don't by default and need environment variables set by hand, or a switch to TUN (enhanced) mode, which takes over the network layer. So 'the browser works but the command line doesn't' usually means the wrong mode, not a bad route.
Work through the checklist below and you can usually pin down the exact step:
- ✅ Menu bar shows connected, and the route name matches the one you selected
- ✅ Browser and terminal report exit addresses in the same country
- ✅ The resolvers in scutil --dns belong to the tunnel, not the local ISP
- ✅ Switching routes and re-querying changes the exit address accordingly
- ❌ Assuming it works because it says connected, without checking the exit address
- ❌ Two proxy clients running at once, with no way to tell which one is in effect
Testing only whether pages open proves little: caches, CDNs and per-site region detection all give misleading answers. The exit address and DNS comparison is what shows traffic actually goes through.
Common failures: connected but nothing loads, frequent drops
These are the issues that come up most often on macOS, and most of them have a straightforward fix:
- Clock skew breaks the handshake: if the system clock is a few minutes off, TLS throws errors. Run
sudo sntp -sS time.apple.comto resync, then reconnect. - MTU mismatch: pages load but video spins forever — usually large packets being dropped. Lower the MTU in the client and try again.
- No recovery after sleep: close the lid, open it again, the tunnel is still there but traffic is dead. Quit and reopen the client, or disconnect and reconnect under System Settings > Network.
- Network blocks UDP: Hysteria2 and TUIC run over QUIC and are sensitive to UDP; on such networks Trojan or VLESS over TCP is more reliable.
- IPv6 bypass: some networks hand out IPv6 as well, and when the tunnel only handles IPv4, traffic may go out directly over IPv6. When testing, check whether the exit address is in IPv6 form.
- Leftover configuration conflicts: after uninstalling, an old VPN entry can remain under System Settings > Network; delete it before reinstalling for a clean state.
Keep the troubleshooting order fixed: check that approval is complete, then whether DNS follows the tunnel, and only then suspect the route. Reverse the order and you'll keep switching between perfectly good routes, spending time in the wrong place.
Set it up once and what remains is maintenance: keep the client updated, refresh the subscription regularly, and re-check the exit address after switching networks. macOS's permission model is stricter than most people expect — ten extra minutes on approvals up front saves a lot of 'why won't it connect again' later.