A macOS menu bar app for fine-grained control over what goes through your VPN. Route specific domains and services around the VPN, force only some things through it, or — in Custom mode — send each domain, service, or subnet out a route of your choice: direct, a specific VPN, an HTTP/SOCKS5 proxy, or a Tailscale peer.
Corporate VPNs often route all traffic through the tunnel, which can cause issues:
- Performance: Streaming and messaging apps become slow or buffer constantly
- Broken features: Chromecast, AirPlay, and location-based features fail
- Unnecessary load: Non-business traffic clogs the VPN tunnel
- Privacy: Personal services don't need to go through corporate infrastructure
VPN Bypass intelligently routes selected services directly to the internet while keeping business traffic secure through VPN.
- 🎯 Menu bar app — quick access to status, mode, and controls
- 🧭 Three routing modes — Bypass (listed traffic skips the VPN), VPN Only (everything uses the VPN except what you list), and Custom (per-rule routing)
- 🌐 Custom domains & built-in services — add any domain, or toggle bundled service packs (Telegram, YouTube, WhatsApp, Spotify, Tailscale, and more)
- 🧩 Custom rules & routes — map each domain, suffix, IP/CIDR, service, or process to a specific route; first match wins
- 🔀 Multiple egresses — send traffic out the local gateway, a specific VPN interface (multi-VPN), an HTTP/SOCKS5 proxy, or a Tailscale peer used as an exit
- ⌨️
vpnbCLI — script the app over a user-only socket (status, routes, rules, mode) - 🔄 Auto-apply — routes are (re)applied automatically as the VPN connects, disconnects, or the network changes
- 🔁 Auto DNS refresh — periodically re-resolves domains and updates routes as IPs rotate
- 📋 Hosts file management — optional DNS bypass via
/etc/hosts - 🔍 VPN detection — GlobalProtect, Cisco, Fortinet, Zscaler, Cloudflare WARP, Tailscale exit nodes, and more
- 🔔 Notifications, ✅ route verification, 🪵 activity logs, 💾 import/export, 🚀 launch at login
- 🔐 Hardened privileged helper — a small root helper performs the routing; it's cdhash-pinned to this app and uses no Network Extension entitlements
VPN Bypass has three modes; switch anytime from the menu bar or Settings.
- Bypass (default) — everything uses the VPN as usual, and only the domains/services you list are routed around it to your regular connection. Best when your VPN carries all traffic but a few apps misbehave through it.
- VPN Only — the inverse: your regular connection is the default, and only the domains/services you list are forced through the VPN. Best for a mostly-direct machine with a few things tunneled.
- Custom — a per-rule engine: you define routes (egresses) and rules that map traffic to them. Rules are evaluated top-to-bottom, first match wins, with a pinned "everything else → default" rule. This is what unlocks multi-VPN, proxy, and Tailscale-peer routing.
Bypass and VPN Only work exactly as they did in earlier versions — if that's all you need, nothing changes. Custom mode is entirely opt-in.
A route is a place traffic can exit:
| Route type | Traffic exits via |
|---|---|
| Direct | your local gateway (around the VPN) |
| VPN | a specific VPN interface — pick which tunnel when several are up (multi-VPN) |
| HTTP / SOCKS5 proxy | a local 127.0.0.1 listener that forwards to your proxy |
| Tailscale peer | out through a chosen Tailscale device used as an exit |
A rule maps traffic to a route by domain, suffix, ip, cidr, service, or process. The first matching rule wins; anything unmatched takes the default route. Direct and detected VPN routes appear automatically; proxy and Tailscale-peer routes are ones you add.
# Add the tap (first time only)
brew tap geiserx/vpn-bypass
# Install VPN Bypass
brew install --cask vpn-bypassOr install directly from the repository:
brew install --cask --no-quarantine https://raw.githubusercontent.com/GeiserX/VPN-Bypass/main/Casks/vpn-bypass.rbDownload the latest .dmg from Releases, open it, and drag VPN Bypass to your Applications folder.
# Clone the repository
git clone https://github.com/GeiserX/VPN-Bypass.git
cd VPN-Bypass
# Build and create release DMG
make release
# Or just build and run
make runOpen Package.swift in Xcode and run the project.
CI note: The
testjob (swift test) requires full Xcode on the self-hosted macOS runner — XCTest ships only with Xcode, not with the Command Line Tools. The workflow selects Xcode viaDEVELOPER_DIRautomatically and fails with a clear message if it is missing.
Click the shield icon in the menu bar to:
- See VPN connection status and type
- View active bypass routes
- Quick-add domains to bypass
- Refresh or clear routes
- Verify routes are working
Click the gear icon to access settings. The visible tabs depend on the active mode:
Domains — add custom domains, enable/disable them individually, see resolved IPs.
Services — toggle built-in service packs (Telegram, YouTube, Spotify, …); each bundles known domains and IP ranges.
Rules (Custom mode) — the ordered rule list (first match wins) mapping domains/suffixes/IPs/CIDRs/services/processes to routes.
Routes (Custom mode) — your egresses: auto-detected Direct + VPN links, plus any proxy or Tailscale-peer routes you add.
General — launch at login, auto-apply on connect, /etc/hosts management, route verification, notification preferences, import/export, and network status (VPN type, interface, gateway, Wi-Fi SSID).
Logs — recent activity for debugging.
Info — version and helper status.
A bundled vpnb CLI drives the same routing the GUI does, over a user-only UNIX socket — handy for scripting or headless tweaks. It needs no extra privilege (the app already holds it).
vpnb status # current mode, routes, schema/version
vpnb mode mode=custom # switch modes: bypass | vpnOnly | custom
vpnb route.add name=work type=socks5 host=127.0.0.1 port=1080
vpnb rule.add match=suffix pattern=example.com routeId=<uuid>
vpnb route.list ; vpnb rule.listSecrets are never passed on the command line (argv is world-visible via ps). Pass the bare token pass:- and pipe the password on stdin:
read -rs PASS && printf '%s' "$PASS" | vpnb route.set id=<uuid> pass:-Set VPNB_SOCKET to override the socket path (default: ~/Library/Application Support/VPNBypass/control.sock).
| VPN Client | Detection |
|---|---|
| GlobalProtect | ✅ Full |
| Cisco AnyConnect | ✅ Full |
| OpenVPN | ✅ Full |
| WireGuard | ✅ Full |
| Fortinet FortiClient | ✅ Full |
| Zscaler | ✅ Full |
| Cloudflare WARP | ✅ Full |
| Pulse Secure | ✅ Full |
| Check Point | ✅ Full |
| Tailscale (exit node) | ✅ Full |
| Tailscale (mesh only) | ❌ Not VPN |
- VPN Detection: Monitors network interfaces and running processes to detect VPN type
- Gateway Detection: Identifies your local gateway (Wi-Fi/Ethernet router)
- Route Management: A small privileged helper adds/removes host routes to steer traffic per your mode — around the VPN (Bypass), through it (VPN Only), or to the route a rule selects (Custom). The helper is cdhash-pinned to this app and uses no Network Extension entitlements.
- Route Verification: Optionally pings routes to verify they're working
- DNS Bypass: Optionally adds entries to
/etc/hoststo bypass VPN DNS
The app intelligently detects corporate VPNs while avoiding false positives:
| Interface Type | IP Range | Detection |
|---|---|---|
| Corporate VPN (GlobalProtect, Cisco, etc.) | 10.x.x.x, 172.16-31.x.x |
✅ Detected as VPN |
| Cloudflare WARP | 100.96-111.x.x |
✅ Detected as VPN |
| Tailscale (mesh networking) | 100.64-127.x.x |
❌ Not detected* |
| Tailscale (exit node active) | 100.64-127.x.x |
✅ Detected as VPN |
*Tailscale in normal mode only routes traffic to other Tailscale devices. It's not a "full VPN" because your regular internet traffic still goes through your normal connection. The app only considers Tailscale as a VPN when you're using an exit node (routing all traffic through another Tailscale device).
The detection also requires:
- The interface must have the
UPflag (actually connected, not just configured) - The interface must have an IPv4 address in a VPN range
- macOS 13.0 (Ventura) or later
- Admin privileges (for route management and hosts file)
The app requires:
- Network access: To detect VPN connections and resolve domains
- Admin privileges: To add routes and modify
/etc/hosts(prompted when needed) - Notifications: Optional, for VPN status alerts (prompted on first launch)
The app is ad-hoc signed and not notarized with Apple, so macOS Gatekeeper may block it on first launch. You'll see errors like "VPN Bypass is damaged and can't be opened" or "Apple cannot check it for malicious software".
Fix: Remove the quarantine attribute:
xattr -cr /Applications/VPN\ Bypass.appPrevention: Install with the --no-quarantine flag:
brew install --cask --no-quarantine vpn-bypass- Check if VPN is actually connected (look for utun interface)
- Verify local gateway is detected in Settings → General
- Check Logs tab for errors
- Use "Verify Routes" button to test connectivity
The app will prompt for admin password when modifying /etc/hosts. If you deny, disable this feature in Settings → General.
Some VPNs force DNS through the tunnel. The hosts file entries help bypass this, but you may also need to:
- Disable "Route all DNS through VPN" in your VPN client
- Use a local DNS resolver
If routes are applied but verification fails:
- The destination host may be blocking ping (ICMP)
- Try accessing the service directly - it may still work
- Check if the service is actually accessible from your network
Contributions are welcome! Here's how you can help:
- Report bugs - Open an issue with details
- Suggest features - Use the feature request template
- Submit PRs - Fork, create a branch, and submit a pull request
Please read the issue templates before submitting.
This project is made possible by generous supporters: Lee
This project is licensed under the GPL-3.0 License.

