Skip to content
VPNmine
PROTOCOLS

Split tunnelling explained

Split tunnelling routes part of your traffic through the tunnel and lets the rest take the normal path. It is implemented either by application or by destination address, and the two models fail in opposite directions, so knowing which one your client uses is the whole of using it safely.

4 min read

Illustration of a splitting arrow and a shield with a check mark, joined by a dashed tunnel line on a dark grid.

Split tunnelling is useful and it is the feature most likely to leave someone protected in theory and exposed in practice. The reason is that "some traffic through the tunnel" can be decided two different ways, and clients rarely explain which one they use.

Model one: by destination address

The tunnel captures certain address ranges and nothing else. In WireGuard this is simply AllowedIPs:

# Full tunnel
AllowedIPs = 0.0.0.0/0, ::/0

# Split: only the office network goes through
AllowedIPs = 10.20.0.0/16

The routing table does the work, and the operating system does not care which program sent the packet.

Fails toward exposure. Anything you did not list takes the normal path. A service that moves to a new address range silently stops being covered.

Model two: by application

The tunnel captures traffic from named programs. On Android this is VpnService.Builder with either addAllowedApplication or addDisallowedApplication.

Those two are opposites and the distinction is the important part:

  • Allow-list. Only the named apps use the tunnel. Everything else goes around it, including apps installed later.
  • Deny-list. Everything uses the tunnel except the named apps. New apps are covered automatically.

An allow-list configured while expecting a deny-list routes almost nothing. A deny-list configured while expecting an allow-list routes almost everything. Both look plausible in the interface.

Which model your client uses

Check before relying on it. The interface language is a reliable hint: "apps that use the VPN" is an allow-list, "apps that bypass the VPN" is a deny-list. If it is ambiguous, test it — open what is my IP from a browser you expect to be inside the tunnel and from one you expect to be outside, and confirm the two answers differ as you intended.

Good reasons to use it

A banking app that objects to a foreign address. Excluding it is more honest than connecting to a server in your own country solely to keep it happy, though either works.

A local network resource. Printers, network shares and casting live on your LAN, and a full tunnel that captures local ranges breaks them. Most clients exclude private ranges by default for this reason.

A game. Excluding it avoids the added latency and the NAT type change while keeping everything else covered.

A corporate tunnel that should only carry corporate traffic. The original purpose of the feature, and still the most common one.

Bad reasons

"To make the VPN faster." Excluding a heavy download from the tunnel makes that download faster and leaves it visible. If speed is the problem, a nearer server addresses it without giving anything up.

"To save battery." The saving is marginal and the exposure is not.

As a default. If you cannot articulate why a particular application is outside the tunnel, it should be inside it.

The DNS trap

Split tunnelling by application does not always split DNS. On several platforms name resolution is a system service, so an excluded app's lookups may still go through the tunnel's resolver — or, worse, the tunnel's resolver may be used for everything while excluded apps' traffic leaves outside, which is a confusing half-state.

The reverse also happens: an excluded app resolves through your ISP while included apps resolve through the tunnel, so your provider sees a partial list of what you opened.

Neither is a fault exactly. It is a consequence of DNS being a separate service from routing, and it means the coverage you get is rarely as clean as the interface implies.

Where it is available

Platform Split tunnelling
Android Yes, per app, in the client
Windows Client-dependent, per app or per address
macOS Client-dependent, usually per address
iOS Managed devices only
Linux By address, via AllowedIPs
Routers Policy-based routing, if the firmware supports it

The Android client is where per-app routing is most capable, because the platform provides the API rather than the client having to invent it.

The rule worth keeping

Default to a full tunnel. Add exclusions one at a time, for a stated reason, and re-verify after each one. Split tunnelling is a scalpel, and the failure mode is that you cannot see the cut.

Inverse split tunnelling on a router

On a router the same idea is expressed as policy-based routing: a rule that sends traffic from one LAN address, or to one destination range, out through the tunnel interface while everything else uses the normal gateway.

That is the most flexible version of the feature, because it can select on source address, destination, protocol and port at once. It is also the one most likely to be configured wrongly, since a rule that fails to match simply falls through to the default route with no warning. Test each rule from the device it is supposed to cover, not from the router itself.

Sources

  1. Android developers — VpnService.Builder
  2. WireGuard — quick start and AllowedIPs
  3. RFC 4301 — Security Architecture for IP

Try it on the network this was written from

VPNmine is a free no-logs VPN running its own WireGuard servers, with native apps for Windows, macOS, Android, iOS, Android TV and Apple TV. No ads, no card.

Get VPNmine