DevTools Hub

Search tools

Search for a developer tool

VPN Split-Tunneling Explained

Part of the VPN Toolkit

A VPN doesn't have to be all-or-nothing. Full tunneling sends every packet a device generates through the VPN; split tunneling sends only specific traffic through it, letting everything else use the normal network path directly. Both are legitimate, widely used configurations — the right choice depends entirely on what the VPN is actually for. This post covers how the split actually works at the protocol level, the DNS gotcha that catches nearly everyone at least once, and the specific "route everything except one subnet" case that needs real computation rather than a single config line.

Why you'd want either one

Full tunneling is the right default for a corporate VPN protecting an employee's traffic on an untrusted network, or for anyone who wants one consistent policy applied to everything a device does — no exceptions to reason about. Split tunneling earns its keep in narrower, common scenarios: reaching a company's internal servers while browsing the public internet normally, accessing a home NAS or printer while a laptop is elsewhere connected to a work VPN, or simply keeping already-fast, already-encrypted traffic (a video call, most modern web browsing over HTTPS) off a VPN server that would otherwise become an unnecessary bottleneck for it.

How the split actually happens

Each VPN protocol expresses the same idea with different syntax. WireGuard uses each [Peer]'s AllowedIPs — a list of CIDR ranges that determines both what gets routed to that peer and what WireGuard accepts as legitimately coming from it. 0.0.0.0/0 means everything (full tunnel); anything narrower is a split. OpenVPN achieves the same result differently: a server config either pushes redirect-gateway def1 (full tunnel) or a set of specific push "route ..." directives (split tunnel) to connecting clients. IPsec expresses it through traffic selectors — the specific address ranges each Child SA (ESP) proposal actually covers, negotiated per connection rather than configured as a single blanket rule.

The DNS leak nobody expects

This is the single most common split-tunnel surprise: routing decisions based on AllowedIPs or route directives only apply to IP traffic to specific address ranges — they say nothing about DNS resolution, which most operating systems handle as a completely separate system-level setting. A client with perfectly correct split-tunnel routes for its actual traffic can still send every DNS query to its regular, non-VPN resolver by default, which means every domain it looks up is visible to that network — including, ironically, the domains of internal services the split tunnel was specifically set up to reach privately. Fixing this means explicitly configuring DNS to route through the VPN too (WireGuard's DNS field, OpenVPN's dhcp-option DNS push), not just the IP traffic itself.

The specific hard case: "everything except this one subnet"

A very common real request is close to full-tunnel but not quite: route all traffic through the VPN except a specific local network — usually so a laptop can still reach a home printer or a NAS while otherwise routing everything through a VPN gateway. The problem is that CIDR notation can only express power-of-two-aligned ranges, so "everything except 192.168.1.0/24" isn't itself a valid single CIDR block — it has to be reconstructed from a set of smaller blocks that fit around the excluded hole. Excluding a /24 from a full 0.0.0.0/0 base takes exactly 24 separate blocks; excluding it from an already-narrower base range takes fewer. This is exactly the computation VPN Split-Tunnel CIDR Calculator performs, rather than something you can work out reliably by hand for anything beyond the simplest case.

Split tunneling changes the threat model, not just the routing

The security tradeoff is worth stating plainly: a VPN only protects the traffic that actually goes through it. Full tunneling gives one uniform answer to "is this traffic protected?" — yes, always. Split tunneling makes that answer depend on the destination, which is exactly right when the goal is narrow (reach these specific internal resources securely) and exactly wrong if the actual goal was protecting or hiding all of a device's traffic, since anything not explicitly routed through the tunnel gets none of the VPN's protection at all — including, again, DNS queries unless separately configured.

Per-application splitting is a different, higher-level feature

None of WireGuard, OpenVPN, or IPsec can natively route based on which application generated a packet — they all work at the IP layer, with no visibility into the process that created a given packet. Splitting traffic by application (common in some commercial VPN client apps, marketed as "app-based split tunneling") is implemented by the operating system or a purpose-built client wrapping the underlying VPN, using OS-specific mechanisms like per-process routing rules or a local proxy — a meaningfully different, more complex layer than the AllowedIPs/route-based splitting this post describes.

Why some organizations disable split tunneling entirely

A corporate VPN client offering a split-tunnel option to end users is itself a policy decision, not just a technical one — many organizations deliberately disable it, forcing full tunneling regardless of what an individual employee's config might otherwise allow. The reasoning is usually about consistent enforcement rather than any specific technical flaw in split tunneling itself: a full tunnel guarantees every policy the network already enforces (content filtering, intrusion detection, logging) applies uniformly to a remote employee's traffic, the same way it would if they were sitting in the office. This is frequently managed centrally through mobile device management (MDM) profiles that override whatever a user's own VPN client is configured to allow, precisely so the policy doesn't depend on each individual device being configured correctly.

Confirming what's actually routed, rather than assuming

Configuration describes intent; the operating system's own routing table shows what's actually in effect once the tunnel is up — worth checking directly rather than assuming the config took effect exactly as written:

# Linux/macOS
ip route show
netstat -rn

# Windows
route print

A route that should have been added by AllowedIPs or a push "route ..." directive but doesn't appear here means the split didn't take effect the way the config intended — a genuinely common way to discover a split-tunnel setup is quietly behaving as a full tunnel (or vice versa) despite the configuration file looking correct on its own.

Common mistakes

  • Assuming split-tunnel routes also cover DNS. They don't, by default, on any of the three protocols — DNS needs its own explicit configuration.
  • Hand-writing "exclude one subnet" as a guess. The correct block list for excluding even one /24 from a full tunnel is 24 separate CIDR ranges — not something to approximate.
  • Choosing split tunneling for a policy that actually needs full tunneling. If the requirement is "protect everything this device does," any split leaves a real gap, regardless of how narrow it looks.
  • Forgetting that split tunneling doesn't reduce what the VPN operator can see for whatever traffic is routed through it — it only changes what bypasses the tunnel entirely.

FAQ

Is split tunneling less secure than full tunneling?

It depends on what you're protecting against. Full tunneling gives one consistent policy for all traffic, which is what most corporate security policies want. Split tunneling reduces the VPN's protection to only the traffic explicitly routed through it — reasonable when the goal is reaching specific internal resources, but a gap if the goal was hiding or protecting all of a device's traffic.

Why does DNS leak even when I've set up split tunneling correctly for IP traffic?

AllowedIPs (or an equivalent route directive) only controls where IP packets to specific address ranges go — it says nothing about DNS resolution, which is a separate system-level setting. A client can have perfectly correct split-tunnel routes and still send every DNS query to its regular, non-VPN resolver, revealing every domain it looks up to that network regardless of which IP ranges are tunneled.

Can I split-tunnel by application instead of by IP range?

Not with WireGuard, OpenVPN, or IPsec themselves — all three route based on IP address ranges, with no visibility into which application generated a given packet. Per-application VPN routing exists, but it's implemented by the operating system or a dedicated client wrapping the VPN, not by the VPN protocol's own configuration.

What's the fix for "route everything except my home network"?

This is the specific case that needs actual computation rather than a single line of config: CIDR notation can't directly express "everything except one subnet," so the equivalent set of covering blocks has to be built and pasted in as a list.

Does split tunneling improve performance?

For traffic that doesn't need to go through the VPN at all — a local printer, a smart-home device on the same LAN, a video call that would rather use the best available direct path — yes, meaningfully: that traffic avoids the extra hop, encryption overhead, and often-longer route through wherever the VPN server actually sits. For traffic that does need the tunnel, split tunneling makes no difference either way.

Try it yourself

VPN Split-Tunnel CIDR Calculator computes the exact block list for routing everything through a VPN except specific subnets, entirely in your browser.

Related tools