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

ApproachWhen it fitsWhat to account for
Switch between configurations in the official appYou only need one remote network at a timeAccess through the first tunnel stops when you switch.
Use wireguard-tools, wireguard-go and wg-quickYou can maintain a command-line setup with separate interfacesRouting, DNS and cleanup need checking on your installed versions. Linux instructions do not necessarily apply to macOS.
Use a graphical client supporting simultaneous tunnelsYou want independent connections without managing interface setup yourselfCheck its macOS support, DNS behaviour and what happens when one tunnel stops.
Reach several networks through one tunnelAn administrator can provide a gateway with access to those networksThe 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:

  1. The operating system chooses a route and an interface for the destination address.
  2. On a WireGuard interface, AllowedIPs determines 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:

DestinationIntended pathExample
Site ATunnel A10.20.0.0/24; service 10.20.0.20; DNS 10.20.0.53
Site BTunnel B10.30.0.0/24; service 10.30.0.20; DNS 10.30.0.53
Your local networkLocal connection192.168.50.0/24
Other Internet destinationsNormal Internet connectionNo 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

StateChecks
A onlyA’s service by IP and name; local resource; public website
B onlyB’s service by IP and name; local resource; public website
A + BBoth services by IP and name while both are active; local resource; public website
Stop AB’s route, DNS and service; any interruption and recovery; local and Internet access
Stop B after reconnecting bothA’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

SymptomNext check
Activating B disconnects AThe client’s activation policy; this may happen before routing is involved.
Both appear active, but one site fails by IPDestination route, overlapping prefixes, handshake, remote firewall and return path.
IP works, hostname fails or reaches the wrong siteResolver selection, DNS-server route, returned IPv4 addresses and cached answers.
Internet or local resources stop workingBroad routes, full-tunnel policy, DNS override and any intentional blocking rules.
Stopping A breaks B’s namesShared DNS changes and restoration order; inspect scutil --dns again.
Handshake works but a service does notRemote 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

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.