Multiple WireGuard tunnels on macOS: options, routing and DNS
Can you run two WireGuard tunnels on a Mac? Compare your options, avoid route and DNS conflicts, and check that both remote networks really work.
You can use multiple WireGuard tunnels on a Mac with a client or command-line setup that supports them. For both remote networks to work, the client must keep both tunnels active, macOS must send each destination through the right interface, and DNS must resolve each name correctly.
This guide covers IPv4 networks.
Two “Connected” indicators are not enough. Verify access to a real service on each network while both tunnels are active.
Official app status, 6 October 2026: the published WireGuard macOS app identified in our upstream check is version 1.0.16, with a single-active-tunnel policy. Multi-tunnel patches have been proposed, but our check found no upstream merge or published release containing them. This is a limitation of that application version, rather than a one-tunnel rule in the WireGuard protocol. See the official app source and macOS App Store listing.
Choose how to reach both networks
| Approach | When it fits | What to account for |
|---|---|---|
| Switch between configurations in the official app | You only need one remote network at a time | Access through the first tunnel stops when you switch. |
Use wireguard-tools, wireguard-go and wg-quick | You can maintain a command-line setup with separate interfaces | Routing, DNS and cleanup need checking on your installed versions. Linux instructions do not necessarily apply to macOS. |
| Use a graphical client supporting simultaneous tunnels | You want independent connections without managing interface setup yourself | Check its macOS support, DNS behaviour and what happens when one tunnel stops. |
| Reach several networks through one tunnel | An administrator can provide a gateway with access to those networks | The gateway needs forwarding, firewall rules and return routes. Editing your Mac’s configuration alone cannot create that access. |
Several [Peer] sections inside one WireGuard configuration are different from two
independent tunnel interfaces. Combining configurations is not a shortcut: one interface has
one private key, and every remote peer must be configured to recognise it.
For the command-line approach, start with WireGuard’s installation instructions, the wg-quick manual and the Darwin implementation. The command-line option is described from its upstream documentation and source; the validated Paart setup does not establish the behaviour of a separate CLI installation.
Prepare two routes that can coexist
What AllowedIPs actually does
Two decisions happen when you send traffic:
- The operating system chooses a route and an interface for the destination address.
- On a WireGuard interface,
AllowedIPsdetermines which peer receives that destination. It also limits which source addresses are accepted from that peer on incoming traffic.
Clients commonly install operating-system routes from AllowedIPs; wg itself does not
perform that route setup. The distinction matters when comparing clients or using custom
routing. See WireGuard’s
cryptokey routing explanation.
For an ordinary split-tunnel setup, include the remote destinations you need rather than every address on the Internet. Keep the configuration consistent with the remote administrator’s policy.
A simple two-site example
These are fictional networks and names, not a complete configuration:
| Destination | Intended path | Example |
|---|---|---|
| Site A | Tunnel A | 10.20.0.0/24; service 10.20.0.20; DNS 10.20.0.53 |
| Site B | Tunnel B | 10.30.0.0/24; service 10.30.0.20; DNS 10.30.0.53 |
| Your local network | Local connection | 192.168.50.0/24 |
| Other Internet destinations | Normal Internet connection | No full-tunnel route in this example |
The relevant peer in A would have AllowedIPs = 10.20.0.0/24; in B,
AllowedIPs = 10.30.0.0/24. Both DNS servers are inside their respective routed ranges.
Also check the interfaces’ own addresses and masks. For example, separate assigned tunnel
addresses such as 10.200.1.2/32 and 10.200.2.2/32 avoid introducing the same connected
subnet through both interfaces. Use addresses assigned by each administrator, rather than
changing them arbitrarily.
Each public WireGuard endpoint must remain reachable over a working underlying connection. A route that sends the endpoint’s own encrypted transport back into an unsuitable tunnel can prevent handshakes.
Overlaps and default routes
If both sites contain a server at 192.168.1.10, an ordinary destination-based route lookup
cannot tell which site you mean. Different DNS names returning that same address do not
solve the ambiguity.
Check for conflicts with your local LAN too. A remote 192.168.50.0/24 conflicts with the
local network in our example. More-specific routes can steer particular destinations, but
they do not provide simultaneous ordinary access to two different machines with the
identical address. Renumbering, address translation at a gateway, or an isolated
environment per site are architectural options.
0.0.0.0/0 covers all IPv4 destinations. Two full tunnels compete for broad coverage. Do
not assume the last activated tunnel always wins: installed routes, scope and client
policies affect the outcome. A more-specific route generally takes precedence within the
applicable routing context; inspect the actual path.
Make DNS work independently of routing
Split tunnelling chooses the path for an IP address. Split DNS chooses the resolver for a name. You often need both.
In our example, names under a.example.com should use 10.20.0.53, names under
b.example.com should use 10.30.0.53, and unrelated names should keep the appropriate
local or public resolver. Both remote DNS servers must themselves be reachable.
A search domain and a resolver-selection domain are different. A search domain can expand a
short name such as server into server.a.example.com; it does not, by itself, prove that
queries for that domain go to A’s DNS server. Use fully qualified names when checking two
sites.
The official app’s current network-settings code sets a catch-all DNS match when DNS
servers are configured. The Darwin wg-quick script uses networksetup to change
network-service DNS settings and restores saved settings during cleanup. Neither mechanism
should be assumed to create independent per-domain DNS for two tunnels merely because each
configuration has a DNS line. Two instances modifying shared settings can also interfere
when one stops. Check the behaviour of your chosen client and installed version.
On macOS, scutil --dns shows configured resolvers, including scoped and supplemental
entries. Read their domains, servers and interface scope; the first resolver listed is not
necessarily the one used for every query. Applications using their own DNS mechanism may
behave differently from the system resolver.
Verify that both accesses really work
Use a service you know is available on each site. The commands below illustrate checks for the fictional example; replace the addresses, names and ports with your own. They inspect routing and attempt connections; they do not activate or reconfigure a VPN.
1. Establish a baseline with each tunnel alone
With A active alone, check its route and a known service:
route -n get 10.20.0.20
nc -vz -G 5 10.20.0.20 443
Repeat with B alone:
route -n get 10.30.0.20
nc -vz -G 5 10.30.0.20 443
Read the interface in each route result and identify which tunnel it belongs to. An
interface named utun could belong to another VPN; its name alone is not proof.
A successful TCP connection establishes that the port is reachable, not that the application is healthy. Open the actual service too. Ping is optional: a host can block ICMP while its service works.
2. Repeat with A and B active together
Run both route and service checks again without switching either tunnel off. Keep an actual session open to each site and confirm both remain usable.
Check a recent handshake and received traffic for each peer using the client’s
diagnostics. Generate traffic before interpreting an old handshake: an idle tunnel need not
constantly exchange packets. Where command-line WireGuard interfaces are exposed to wg,
these queries can help:
sudo wg show all latest-handshakes
sudo wg show all transfer
They are not a universal way to inspect app-managed Network Extension tunnels. A missing
interface in wg does not prove that such an app is disconnected.
3. Check names through macOS and the application
scutil --dns
dscacheutil -q host -a name server.a.example.com
dscacheutil -q host -a name server.b.example.com
Compare the returned addresses with the intended sites. Then open each service by its full hostname. This also checks the application’s actual resolution path and, for HTTPS, certificate validation. Correct DNS does not repair an invalid certificate.
dig @10.20.0.53 server.a.example.com can test A’s DNS server directly. It does not prove
that macOS or your browser selected that resolver. Cached answers can also conceal a
resolver problem; confirm the behaviour using known records and the actual applications you
rely on.
4. Check local access, Internet access and stopping a tunnel
| State | Checks |
|---|---|
| A only | A’s service by IP and name; local resource; public website |
| B only | B’s service by IP and name; local resource; public website |
| A + B | Both services by IP and name while both are active; local resource; public website |
| Stop A | B’s route, DNS and service; any interruption and recovery; local and Internet access |
| Stop B after reconnecting both | A’s route, DNS and service; any interruption and recovery; local and Internet access |
Record expected and observed results rather than only “connected”. Use the IPv4 addresses and names configured for this setup.
If the second connection breaks something
| Symptom | Next check |
|---|---|
| Activating B disconnects A | The client’s activation policy; this may happen before routing is involved. |
| Both appear active, but one site fails by IP | Destination route, overlapping prefixes, handshake, remote firewall and return path. |
| IP works, hostname fails or reaches the wrong site | Resolver selection, DNS-server route, returned IPv4 addresses and cached answers. |
| Internet or local resources stop working | Broad routes, full-tunnel policy, DNS override and any intentional blocking rules. |
| Stopping A breaks B’s names | Shared DNS changes and restoration order; inspect scutil --dns again. |
| Handshake works but a service does not | Remote forwarding, return routing, firewall, service listener; MTU if larger transfers specifically fail. |
For a tunnel that never establishes a handshake, see When the tunnel will not connect. For one that shows a handshake but carries no traffic, see WireGuard connected but no traffic. For the relationship between DNS and routes, see DNS, routing and split tunnelling.
Using Paart for this setup
Paart Client is one graphical option for keeping separate WireGuard connections active on a Mac when their routes can coexist. Simultaneous connections are available on Free and Pro. Advanced networking is available on one chosen Free connection, and on every connection with Pro.
For names belonging to each site, its split DNS guide explains how to select the internal names and their resolver. These are Paart-specific instructions.
There are operational limits. Simultaneity relies on observed macOS behaviour, not something Apple guarantees. Paart reports overlaps it observes; it does not decide which conflicting route should win. In the validated Paart Mac setup, stopping one connection interrupted the others, which then resumed automatically. Account for that interruption in your workflow.
On iPhone and iPad, Paart supports one active connection at a time. Do not extrapolate the Mac setup to those devices.
Technical sources
- WireGuard: interfaces and cryptokey routing — protocol and peer selection.
- wg reference
—
AllowedIPsand runtime queries. - wg-quick reference and Darwin source — route setup and macOS DNS handling. The Darwin source is the platform-specific reference.
- wireguard-apple network settings — routes and DNS settings in the official client.
- wireguard-apple history and multi-tunnel patch proposal — distinguish a proposal from an upstream merge and a released app.
Source review: 6 October 2026. Multiple active tunnels, coexistence of routes, DNS and stop/resume behaviour were validated in the preceding Paart Mac acceptance tests. The command-line option is documented from upstream sources, rather than presented as part of that acceptance test.