Skip to content
tanderboldPublic

About

Several OpenVPN connections at once on macOS: a free, open-source menu-bar client with split DNS per connection, kill switch and leak protection.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

MugVPN icon: a steaming mug with VPN written on it

MugVPN

A free macOS menu-bar client for OpenVPN profiles that keeps several VPN connections up at the same time.

Release Downloads Build License: MIT macOS 13+ Apple silicon and Intel Homebrew openvpn 2.7 22 languages Swift

The office VPN, a client's VPN and your home lab — at the same time, each with its own tunnel, routes and DNS. MugVPN sits in the menu bar; every .ovpn profile gets its own submenu, and a Connections window creates, edits, imports and removes them. Under the hood each connection runs its own openvpn 2.7, which runs without root: a small helper checks every profile and every route and DNS change it asks for.

MugVPN's menu with three connections up at once: Office, Home Lab and Datacenter The status window of a connection: state, address, traffic and the openvpn log in colour

What you get

Several connections at once

  • Every connection has its own utun, routes and DNS; connect, disconnect and reconnect each on its own.
  • Split DNS per connection: names in the domains a server pushes go to that tunnel's DNS, everything else as before — so two VPNs can each answer for their own domains. For servers that push only dhcp-option DOMAIN, one switch makes those domains split too. A server that pushes no domains at all can still be used for the domains you list in the connection's options (the server's DNS, no addresses to type).
  • Your own DNS for a connection: its servers for the domains you list (or for all names), or leave the Mac's DNS alone.
  • Warnings when connections collide: two that both take all traffic, overlapping routes (IPv4 and IPv6), DNS already taken.

Connections window

  • Create a connection from scratch — servers, ports, protocols, CA, certificate, key, tls-auth/tls-crypt, password sign-in — or edit any profile in a form or as text. Only the lines you change are rewritten.
  • Import .ovpn files (with the keys they name), Tunnelblick .tblk folders, profiles from a URL or an OpenVPN Access Server; duplicate, rename, delete.
  • Per connection: connect at launch, its own proxy, connect silently, what to do when the Mac sleeps.

The Connections window: list of connections and the General tab with servers The Options tab: DNS mode, split DNS, kill switch and leak protection

Protection

  • Kill switch (per connection, off by default): if a connection that carries all traffic drops unexpectedly, your TCP and UDP traffic outside the VPN stays blocked (PF) until you reconnect or unblock it from the menu — even across a restart of the helper. Name lookups through the Mac's resolver still go out, so the VPN can find its server again.
  • Leak protection while a connection carries all traffic: no IPv6 and no DNS outside the VPN; the local network can be allowed.
  • Leak check after connecting and on every network change: warns if the default route, a public network (as a rogue DHCP server would push — TunnelVision) or the DNS goes around the tunnel.

MugVPN's menu after a kill switch fired: Internet blocked, Unblock Internet and Sign in to This Network

Signing in

  • Username and password, private-key passwords, static and dynamic challenges (OTP), web/SSO sign-in, PKCS#12 certificates, HTTP proxies. Passwords are kept in your login Keychain, per connection.
  • A warning when a connection's client certificate expires within 30 days, or has expired — before it connects.

Everyday

  • Coloured live log with a light/dark switch; View Log opens the log file (in Console by default); notifications.
  • Reconnects at once after sleep and on network changes (another Wi-Fi, a new router or lease); optional disconnect on sleep.
  • Networks that ask for a sign-in first (hotels, airports): the menu offers it, lifting a kill switch's block for two minutes so the page can load (a persistent connection's block: administrators only).
  • Opens at login if you like; Export Diagnostics… makes a zip for a bug report — versions, routes, DNS, logs, and the profiles reduced to settings known to hold no secrets (keys, passwords, setenv values and the like are left out).
  • Persistent connections that an administrator puts in config-auto start at boot, before anyone logs in.
  • Your own scripts beside a profile (<name>_pre.sh, _up.sh, _down.sh) — run as you, never as root; variables a server pushes (echo setenv NAME value) reach them as PUSHED_NAME.
  • Command line: MugVPN --command connect|disconnect|reconnect|status|list with exit codes and JSON — for scripts.
  • 22 languages, VoiceOver labels, light and dark appearance, an uninstaller.

The Authentication tab: certificates embedded in the profile The status window in the dark appearance

Compared with other OpenVPN clients for Mac

MugVPN is made for more than one VPN at a time: each connection keeps its own routes and DNS, and the kill switch, leak protection and leak check work with all of them together.

MugVPN Tunnelblick 9 Viscosity 1.13 OpenVPN Connect 3.8
Several OpenVPN connections at once Yes Yes ("for experts only") Yes No: one at a time
Split DNS for several VPNs at once Yes Not documented Yes One connection only
Kill switch with several tunnels Yes: per connection, blocks only traffic outside the tunnels Turns off all network services; not advised with several VPNs No built-in Seamless Tunnel (one connection)
IPv6 and DNS kept inside the VPN (firewall) Yes (macOS packet filter) IPv6 off IPv6 blocked IPv6 blocked
Leak check after connecting, incl. TunnelVision Yes Public IP check DNS problems in the log No
Warnings when connections collide Yes: both take all traffic, overlapping routes, DNS Generic warning No —
openvpn runs without root Yes No (root) Not documented Not documented
Editor for servers, certificates, keys Yes No (text files) Yes Name, server, proxy only
Hotel/airport Wi-Fi sign-in Yes, even while the kill switch blocks Not documented Not documented Yes
Command line connect/disconnect/status/list, exit codes, JSON AppleScript AppleScript No connect/disconnect on macOS
Connections at boot, before login Yes Yes No No (Windows only)
Managed settings (MDM) Yes Partial Yes Yes
Price, license Free, MIT Free, GPL v2 US$16, proprietary Free, proprietary
macOS 13+ 13+ 14+ 11+

As documented by each product on 2026-10-10: Tunnelblick (kill switch, background programs), Viscosity (multiple connections, leaks), OpenVPN Connect (one connection, command line). Corrections welcome in an issue.

Security

  • openvpn runs without root. Each tunnel's openvpn runs unprivileged; a small helper does what needs root, after checking each request.
  • Profiles are checked before they run: options that would run programs or load code are refused, with the line that caused it.
  • Passwords stay in your login Keychain, per connection.
  • Built test-first, with integration tests in virtual machines against real OpenVPN servers.

Found a security problem? Please report it privately through GitHub's security advisories rather than an issue.

Requirements

macOS 13 Ventura or later, Apple silicon or Intel.

Install

brew install --cask tanderbold/tap/mugvpn

or download MugVPN-<version>.dmg from the latest release (signed with a Developer ID and notarized by Apple; its SHA-256 is beside it), open it and drag MugVPN to Applications, then open it from there. The first time you connect, macOS asks you to allow MugVPN's helper in System Settings > General > Login Items; MugVPN opens that page for you. Install it as an administrator. A newer version replaces the app in the same way (brew upgrade); its helper is updated once no connection needs it. A helper too old to update itself is offered from the menu (Update MugVPN's Helper…, which stops every user's MugVPN connections).

Or build it yourself (Building): copy build/MugVPN.app to /Applications. The first build makes a code-signing certificate of your own, kept in ~/Library/Application Support/MugVPN Build; MugVPN's helper then works only with an app signed with it, so it trusts what runs as your account (the uninstaller leaves that folder; delete it when you no longer build MugVPN).

Macs with standard users. Routes and DNS are the whole Mac's, so by default a standard (non-administrator) user's connections reach only private networks (10/8, 172.16/12, 192.168/16, 100.64/10, fc00::/7), carry only that user's own TCP and UDP traffic (no ping), and set no DNS unless an administrator allows its names. The routing table is still the Mac's: such a route can make that private network unreachable for the Mac's other users while the connection is up. An administrator can allow more, or list the networks standard users may reach, in /Library/Application Support/MugVPN/policy.json (owned by root):

{
  "allowedNetworks": ["203.0.113.0/24", "2001:db8::/32"],
  "allowedDomains": ["corp.example.com"],
  "usersMayRouteAllTraffic": false,
  "usersMayChangeDNS": false,
  "trustedUsers": ["alice"]
}

usersMayRouteAllTraffic lets standard users send all traffic through a VPN; usersMayChangeDNS lets them set DNS for any names, all names included; trustedUsers are treated as administrators.

Managed settings. A configuration profile (MDM) for com.mugvpn.app can set and lock any of MugVPN's settings; MugVPN then shows them as set by the administrator. Among them: require_kill_switch, require_leak_protection (IPv6 and DNS only through the VPN), disable_save_passwords, allow_lan_when_blocked, persistent_connections (auto, manual, disable) and the proxy.

Profiles

Where What
~/Library/Application Support/MugVPN/config your profiles (Import puts them here, one folder each)
/Library/Application Support/MugVPN/config profiles an administrator installs for every user
/Library/Application Support/MugVPN/config-auto persistent profiles, started by the system at boot

A persistent profile is config-auto/<name>.ovpn; it and the files it names (inside config-auto) must be root's and readable only by root (chmod 600). Its settings go beside it, as <name>.json (root's, not writable by group or others; without it, all of these are off); MugVPN's window shows them but does not change them:

{ "kill_switch": true, "allow_lan": false, "block_ipv6": true, "dns_only_tunnel": true, "split_dns": false }

Its kill switch blocks the whole Mac's traffic outside the tunnel until the tunnel is back; a persistent tunnel that ends unexpectedly is started again, waiting longer each time (up to 5 minutes).

Standard .ovpn profiles work as they are. For safety, no profile — not even an administrator's — may run programs as root: up, down, plugin, script-security 2 and the like are refused, with the line that caused it. Use the _pre/_up/_down.sh scripts instead; they run as you.

Command line

MugVPN --connect <profile>
MugVPN --command connect|disconnect|reconnect <profile> [--wait] [--timeout <seconds>]
MugVPN --command list | status [<profile>]
MugVPN --command disconnect_all | rescan | exit
MugVPN --command silent_connection 0|1
MugVPN --command import <path>
MugVPN --uninstall [--keep-profiles] [--yes]

MugVPN here is /Applications/MugVPN.app/Contents/MacOS/MugVPN. --connect starts MugVPN and connects the profile (if MugVPN is running, it connects it there). A command returns once MugVPN has started it; with --wait (60 s) or --timeout <seconds>, once the connection is up or down. Exit codes: 0 done, 1 failed (an unknown profile, a connection that did not come up), 2 a usage error, 3 MugVPN is not running or does not answer (connect and import start it; exit just succeeds), 4 timed out. list prints every profile and status the connected ones (or the one named), as JSON: name, path, source (user, system, persistent), status (disconnected, connecting, waiting_for_web_auth, connected, reconnecting, disconnecting), ip, ipv6. A profile is named as MugVPN shows it, by its file path, or by its name when only one profile has it.

Uninstall

Drag MugVPN to the Trash: a minute later its helper removes what MugVPN put on the Mac — the helper itself, its files and logs, and every user's MugVPN logs and settings. Profiles stay (yours and those administrators installed, and policy.json), for a reinstall to find. Should the Trash be emptied and the Mac restarted within that minute, the system part goes at the next start; users' logs and settings and the Login Items entry then stay. Anything left is named in the system log (in Console, search for MugVPN).

About MugVPN > Uninstall MugVPN…, or MugVPN --uninstall --yes in Terminal (--uninstall alone lists what would go), removes everything; an administrator's. It disconnects every tunnel and removes the helper, its files and logs, the profiles administrators installed (config, config-auto) and policy.json, your own profiles, settings and saved passwords, and moves the app to the Trash; other users' own profiles and passwords stay. Keep my profiles (--keep-profiles) keeps every profile and policy.json. If the helper does not answer, MugVPN asks for an administrator's password to remove its system part itself (the command line prints the command instead).

With Homebrew: brew uninstall --cask mugvpn; --zap removes your profiles and settings too.

How it works

  • MugVPN.app (your rights): the menu, the windows, your profiles and saved passwords. It talks to each openvpn over its management interface.
  • The helper (a LaunchDaemon): starts and stops openvpn for the app, sets up the tunnels it asks for and cleans up after a tunnel that ended.
  • openvpn 2.7, built from source with OpenSSL 3.5, LZ4 and LZO, inside the app.

Building

Only the Xcode Command Line Tools are needed.

tools/build-openvpn.sh            # openvpn and its libraries (build.sh also runs it when needed)
MUGVPN_ARCH=native tools/build.sh # build/MugVPN.app (omit MUGVPN_ARCH for a universal build)

Translations: tools/l10n/l10n.py build writes Resources/<language>.lproj from tools/l10n/translations. Third-party notices: tools/notices.sh writes THIRD-PARTY-NOTICES.txt from the pinned source archives.

Tests

Three layers, written before the code they test (Tests/):

  • Logic — parsers, profiles, the helper's and the app's decisions, with the system faked: swift build --product MugVPNTests && .build/debug/MugVPNTests
  • Integration — real tunnels, routes, DNS and the helper as root, only inside two virtual machines (tools/stand/stand.sh: a macOS client and Ubuntu OpenVPN servers): .venv/bin/pytest Tests/Integration
  • Interface — the menu and windows, driven inside the macOS VM's login session against the app's test mode with a fake backend: tools/stand/stand.sh ui

Both run against a testing build (MUGVPN_TESTING=1 tools/build.sh).

Nothing in the integration or interface tests touches the Mac you run them from.

License

MugVPN is under the MIT License.

The app bundle also contains openvpn (GPLv2, with MugVPN's patch in tools/), OpenSSL (Apache 2.0), LZ4 (BSD 2-Clause) and LZO (GPLv2), each under its own license, built from the official releases listed with their full license texts in THIRD-PARTY-NOTICES.txt. MugVPN runs openvpn as a separate program.

"OpenVPN" is a trademark of OpenVPN Inc. MugVPN is not affiliated with or endorsed by OpenVPN Inc.; the name is used only to say which profiles MugVPN works with.

About

Several OpenVPN connections at once on macOS: a free, open-source menu-bar client with split DNS per connection, kill switch and leak protection.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages