Vibrant shield emblem with red, yellow lightning bolt, dynamic color background, and metallic border.

Linux Split Tunneling: 7 Smart Routing Methods Explained


Linux split tunneling lets you decide which traffic uses a VPN and which traffic keeps using your normal network connection. On Linux, that control can happen at several layers: inside a VPN app, with WireGuard routes, through policy routing, inside a network namespace, with OpenVPN route rules, on the local LAN, or at the router itself. The useful part is not making your routing table look impressive. It is knowing exactly where your packets go before you trust the setup.

I learned that distinction the practical way. My first Linux split tunneling goal was simple: keep selected VPN traffic protected while local resources stayed direct. Linux then introduced routing tables, marks, namespaces, DNS, and the possibility that one innocent-looking rule could send traffic somewhere I never intended.

If you enjoy these hands-on networking guides, you can join my HackersGhost newsletter. I use it for the practical experiments, fixes, and lab lessons I would want bookmarked myself, without turning your inbox into another device that needs incident response.

This guide explains seven practical ways to build Linux split tunneling, including WireGuard split tunneling, OpenVPN split tunneling, and ProtonVPN split tunneling. I also show where split tunneling vs full tunneling changes your risk model, how I separate VPN and local traffic in my own VMware-based lab, and what I test before calling a routing setup finished.

Routing methodBest forMain trade-off
VPN app or WireGuard routesEveryday Linux useEasy, but less granular
Policy routing or namespacesLabs and per-app controlMore setup and testing
Router-level split tunnelingMultiple devicesDepends on router firmware

Key Takeaways

  • Linux split tunneling is routing control, not a privacy switch. You still need to verify IP, DNS, local routes, and failure behavior.
  • WireGuard split tunneling is excellent for destination-based routing because AllowedIPs can define which networks belong in the tunnel.
  • OpenVPN split tunneling can be built by refusing a pushed default route and adding only the destinations you actually want tunneled.
  • For strict per-application separation, Linux network namespaces are cleaner than trying to identify every packet by application after it leaves the process.
  • ProtonVPN split tunneling now exists in supported Linux GUI packages, but Kali and other unsupported distributions can still require manual routing or may behave differently.
  • Split tunneling vs full tunneling is mainly a policy decision: convenience and local access on one side, simpler all-VPN enforcement on the other.
  • My rule is simple: if I cannot explain the route with ip route get, test the public IP, and check DNS, I do not call the setup finished.

What Linux Split Tunneling Actually Does

With a normal full-tunnel VPN, the client tries to make the VPN the preferred path for internet traffic. With Linux split tunneling, you deliberately create exceptions or inclusions. A browser might use the VPN while a printer stays local. A lab subnet might remain reachable directly while selected internet traffic uses WireGuard. You can also reverse the idea and tunnel only one application or one destination.

The important word is routing. Encryption comes from the VPN protocol, but Linux still decides which interface receives each packet. The main table, custom tables, marks, source addresses, destination prefixes, and namespaces can all influence that decision. The tunnel does not read your mind, unfortunately for anyone hoping to debug by staring at it.

HackersGhost Note: I treat split tunneling as a routing policy that happens to use a VPN, not as a VPN feature that magically understands my workflow. That mindset makes troubleshooting much easier because I ask “which route wins?” before I ask “why is the VPN broken?”

Linux split tunneling and VPN routing on a Linux laptop

Split Tunneling vs Full Tunneling on Linux

The split tunneling vs full tunneling choice depends on what you need. Full tunneling is easier to reason about: internet traffic uses the VPN, and a kill switch can block fallback. It is a clean default when you do not need local exceptions.

Linux split tunneling becomes useful when full tunneling creates friction. A VMware host-only network must stay reachable, local devices may need direct access, and lab targets should never leave the local environment. Split routing lets me keep those paths separate instead of forcing every packet into one tunnel.

The trade-off is complexity. A broad exception can send more traffic direct than intended, while DNS may follow a different path from the browser. That is why I verify every method instead of trusting the connection badge.

Method 1: ProtonVPN Split Tunneling in the Linux App

The easiest Linux split tunneling route is a VPN client with native app rules. ProtonVPN split tunneling is available in supported Ubuntu, Fedora, and Arch GUI packages, with an optional setup path on Debian. You can use exclude or include mode to choose which apps belong in the tunnel.

That makes ProtonVPN split tunneling easier than the manual setup I originally used. On a supported distribution, I would start there. Fewer hand-built rules also mean fewer places for me to create a remarkably sophisticated typo.

ProtonVPN Linux split tunneling needs more caution outside Proton’s support matrix. Proton says its Linux app can work on Kali, but support is limited. Parrot is Debian-based too, yet I still test advanced GUI features instead of assuming identical behavior.

There is one more practical limitation: split tunneling and kill-switch behavior are not identical across platforms. If I need fail-closed enforcement on Linux, I verify it separately instead of assuming an application exclusion automatically inherits the protection I want.

Method 2: WireGuard Split Tunneling With AllowedIPs

WireGuard split tunneling is beautifully simple when your policy is based on destination networks. In a WireGuard peer configuration, AllowedIPs does two jobs: it identifies the IP ranges that belong to that peer and helps determine which destinations should be sent to it. A full-tunnel configuration commonly uses 0.0.0.0/0 and ::/0. A split configuration can replace those broad ranges with only the networks you want inside the tunnel.

[Peer]
PublicKey = <VPN_SERVER_PUBLIC_KEY>
Endpoint = <VPN_SERVER_IP>:<PORT>
AllowedIPs = 203.0.113.0/24, 198.51.100.25/32

Those are documentation ranges, not real targets. Only those destinations are candidates for the WireGuard peer, while other traffic follows the normal route. This form of Linux split tunneling works well when I know the destination networks in advance.

It is less useful for “send Firefox through the VPN but not Chromium” because routing works on packets and addresses, not application names. For application-level control, I move to namespaces or a client with native app selection.

If you want to understand the protocol underneath this method, the WireGuard homepage is one of the rare networking references that manages to be technical without making the page feel like punishment.

Method 3: Linux Split Tunneling With Policy Routing

Policy routing makes Linux split tunneling more flexible. Linux can choose a table from a source address, firewall mark, or other rule. I use that logic when a Linux system acts as a gateway or when a clearly defined traffic class needs its own route.

The old version of this article used a source-subnet rule as if it automatically selected applications on the local machine. That is not what the rule means. A command such as the following is appropriate when packets actually have a source address from that subnet, for example traffic forwarded by a Linux gateway:

sudo sh -c 'echo "200 vpn" >> /etc/iproute2/rt_tables'
sudo ip route add default dev wg0 table vpn
sudo ip rule add from 192.0.2.0/24 table vpn

192.0.2.0/24 is only an example. The rule sends traffic sourced from that network to the vpn table; it does not mean “route my browser through WireGuard.” For per-app routing, I prefer Method 4.

Policy routing can also use nftables marks, but I treat that as an advanced extension. Marks must identify the intended traffic and the routing tables must agree. I trust the live routing state, not the confidence level of whoever wrote the snippet.

HackersGhost Note: ip rule tells Linux which routing table to consult. It does not enforce privacy by itself. I pair routing decisions with firewall rules only when I have defined exactly what should happen if the tunnel disappears.

VPN Kill Switch for Linux: 7 Ways to Prevent IP Leaks

Set up and test a VPN kill switch on Linux so traffic stops when the tunnel drops, helping prevent accidental IP and DNS leaks on Kali or Parrot OS.

Method 4: WireGuard Split Tunneling With Network Namespaces

For strict per-process isolation, namespaces are my favorite manual approach. A namespace has its own interfaces and routes, so I can launch a browser or command where the only internet path is WireGuard. This is WireGuard split tunneling by separation instead of packet-by-packet guesswork.

WireGuard has a useful namespace design: its encrypted UDP socket stays in the namespace where the interface was created even after the interface moves. That lets the physical network remain outside while the cleartext VPN side lives in vpnspace.

sudo ip netns add vpnspace
sudo ip link add wg-vpn type wireguard
sudo ip link set wg-vpn netns vpnspace
sudo ip -n vpnspace link set lo up

sudo ip netns exec vpnspace wg setconf wg-vpn /etc/wireguard/wg-vpn.conf
sudo ip -n vpnspace addr add <VPN_ADDRESS> dev wg-vpn
sudo ip -n vpnspace link set wg-vpn up
sudo ip -n vpnspace route add default dev wg-vpn

The file used with wg setconf contains WireGuard fields such as keys, endpoint, and AllowedIPs; address and DNS are handled separately. I configure namespace DNS explicitly rather than assuming the host resolver follows the tunnel.

sudo mkdir -p /etc/netns/vpnspace
echo "nameserver <VPN_DNS_IP>" | sudo tee /etc/netns/vpnspace/resolv.conf

sudo ip netns exec vpnspace curl https://ifconfig.io

I like this form of Linux split tunneling because the boundary is obvious: normal processes use the host network; processes launched with ip netns exec vpnspace use the namespace. I do not have to hope an exclusion list survived an update.

Method 5: OpenVPN Split Tunneling With Selective Routes

OpenVPN split tunneling uses OpenVPN’s route controls. A server can push redirect-gateway for a full tunnel; if I want only selected networks tunneled, I ignore that default-route instruction and add explicit routes instead.

pull-filter ignore "redirect-gateway"
route 203.0.113.0 255.255.255.0
route 198.51.100.25 255.255.255.255

I prefer this over blindly using route-nopull, which also blocks pushed DNS and route-related options. I ignore only what I intend to replace, then verify one tunneled and one direct destination.

If you still use OpenVPN or need compatibility with a legacy environment, the OpenVPN homepage is the second external reference I keep handy. OpenVPN split tunneling is not as minimal as WireGuard, but its route controls are mature and useful when the configuration is already based on OpenVPN.

Linux network namespace used for WireGuard split tunneling

Method 6: Keep Local and Lab Networks Outside the VPN

Sometimes Linux split tunneling simply keeps a trusted local network reachable while internet traffic stays tunneled. My vulnerable VMware machines live on an isolated host-only network, so Parrot must reach them directly. Lab packets do not need a scenic trip through a commercial VPN server.

The first command I use is not an add or delete command. It is a question:

ip route get <LAB_TARGET_IP>

If the output shows my host-only interface, the route is already specific enough. If the VPN client or firewall blocks local access, I fix that policy instead of adding random routes until something responds. A more-specific LAN route often wins over a default route, but a kill switch can still block the packet. Routing and firewall policy must agree.

This is also where split tunneling vs full tunneling becomes a practical decision rather than a definition. Full tunneling is simpler, but a security lab is full of networks that should stay local. Split routing lets me keep the vulnerable side intentionally boring and contained.

Method 7: Router-Level Linux Split Tunneling and Policy Routing

The seventh method moves the decision to the router. With VPN client and policy-routing support, selected devices or destinations can use the VPN while other traffic stays on the normal WAN. That can be cleaner than rebuilding Linux split tunneling on every VM.

I use a Cudy WR3000 as my VPN-facing router with ProtonVPN over WireGuard. I also keep a separate TP-Link Archer C6 for deliberately vulnerable lab experiments, isolated from my normal modem path. The exact menus depend on firmware, so I do not hard-code screenshots or menu names here. The concept is what matters: policy routing belongs at the layer where you want the decision to apply.

Router policy is easy to audit when a whole device needs the VPN. For one tunneled app and one direct app on the same machine, I use Linux split tunneling with a namespace or native ProtonVPN split tunneling.

I use the WR3000 because moving VPN policy to the router is useful when I want consistent routing for an entire device rather than one Linux process.

Practical Linux split tunneling workflow in a home cybersecurity lab

How I Use Linux Split Tunneling in My Own Lab

My lab runs on a second-hand HP EliteBook upgraded to 32GB of RAM. I use VMware rather than VirtualBox and keep Kali and Parrot available, although Parrot is my main environment. Vulnerable VMs stay on isolated networks so I can test routing and packet behavior without making the rest of my home network an unwilling participant.

That setup is why I prefer Linux split tunneling as a deliberate design. Lab traffic stays local, protected internet traffic can use the VPN, and local devices should not vanish because I changed a default route. Each path has a reason.

On the Cudy router I use ProtonVPN WireGuard and sometimes Secure Core when I want a multi-hop privacy route. It is another layer in my Linux split tunneling design, not a force field around my laptop.

ProtonVPN Linux Split Tunneling: Where It Fits Best

I use ProtonVPN often enough that it belongs here naturally. ProtonVPN Linux split tunneling is most convenient on a supported setup when you want app-level include or exclude rules without building a namespace.

For Kali, Parrot, unusual desktops, or a lab where I want full routing control, manual WireGuard still makes sense. Proton can remain the VPN endpoint while Linux itself makes the routing decision.

Affiliate disclosure: the Proton links below are affiliate links. I may earn a commission at no extra cost to you. I already use Proton in my own network, which is why it is the primary affiliate in this guide.

If you already use several Proton services rather than only the VPN, the bundled plan can make more sense than maintaining separate subscriptions.

Proton Unlimited combines Proton VPN, Proton Mail, Proton Drive, and Proton Pass in one subscription. If you already use several Proton services in your privacy or lab workflow, the bundle is usually the more coherent option.

How I Test Linux Split Tunneling Before I Trust It

A Linux split tunneling setup is not finished when the VPN connects. It is finished when expected traffic uses the expected route and failure behavior is predictable. I run the same short checks after every routing change.

Check the Route First

ip route get 1.1.1.1
ip route get <LOCAL_OR_LAB_IP>
ip rule show
ip route show table all

I want the output to match the design before I even open a browser. For WireGuard split tunneling, I also use wg show to confirm the interface and peer state.

Check Public IP From Both Paths

If one process should use the VPN and another should go direct, I test both. With a namespace that can be as simple as comparing a normal request with one executed inside vpnspace. If both show the same path when they should differ, I stop there and debug.

Check DNS, Not Just the Browser IP

DNS is where otherwise convincing Linux split tunneling setups can become misleading. A process may use the VPN for web traffic while the host resolver still sends DNS elsewhere. That may be acceptable in some split policies and unacceptable in others. The important part is that it is intentional.

Test Failure Behavior

Finally, I disconnect the tunnel. If protected traffic falls back to the normal route, I have routing but not fail-closed enforcement. When bypass must be impossible, I add firewall rules for that policy instead of assuming the client will infer it.

HackersGhost Note: The best Linux split tunneling test is boring: one tunneled destination, one direct destination, one local target, DNS, then a forced disconnect. If all five behave exactly as planned, I trust the configuration far more than a green “Connected” badge.

How to Test DNS & WebRTC Leaks: 7 Sneaky Checks

Run 7 practical DNS and WebRTC leak checks to see whether your VPN is exposing your real IP address, DNS requests, or browser network information.

Common Linux Split Tunneling Mistakes I Would Avoid

  • Assuming a source-based ip rule selects an application. It only matches traffic with that source address.
  • Testing only one public IP. Split tunneling has at least two intended paths, so I test both.
  • Ignoring IPv6. An IPv4-only routing policy can look perfect while IPv6 follows a different route.
  • Forgetting DNS. Your tunnel and resolver policy should agree with the privacy outcome you actually want.
  • Mixing a kill switch with split routing without checking compatibility. A firewall can block the very direct traffic you intentionally excluded.
  • Using 0.0.0.0/0 in WireGuard and calling it split tunneling. That is a full IPv4 default route unless policy routing changes the decision elsewhere.
  • Copying nftables rules without understanding the hook and mark. A firewall mark only helps when an ip rule or route actually uses it.

Real Use Cases for Linux Split Tunneling

Linux split tunneling does not need exotic use cases. The practical ones are enough.

  • Public Wi-Fi: keep sensitive browsing or work tools inside the VPN while allowing a captive-portal browser to reach the local login page directly.
  • Home lab: route internet traffic through the VPN while keeping vulnerable VMware networks local and isolated.
  • Remote work: keep a client-specific network in one tunnel while local printers or ordinary personal traffic stay outside it, where policy allows.
  • Performance-sensitive traffic: leave a video call direct while a browser or terminal session uses the VPN.
  • Testing: compare direct and VPN behavior from the same Linux machine without repeatedly rebuilding the whole connection.

I have used Linux split tunneling away from home and in my lab. The biggest benefit is clarity: I know which traffic belongs to which path, so failures are easier to isolate.

My Take on Linux Split Tunneling

Linux split tunneling is worth learning because each method fits a different policy. Native ProtonVPN split tunneling is easiest on supported distros. WireGuard split tunneling with AllowedIPs fits known destinations. Policy routing handles source- or mark-based decisions. Namespaces give me strong per-process separation, OpenVPN split tunneling suits existing OpenVPN setups, and router policy is ideal when a rule should cover a whole device.

I would not use all seven at once. That would turn a useful routing policy into a hobby project with trust issues. I pick the simplest method that expresses the rule clearly, test both sides of the split, check DNS and IPv6, and then force a disconnect to see what happens.

That is the real difference in split tunneling vs full tunneling. Full tunneling gives you one dominant path. Split tunneling gives you choices. On Linux, choices are powerful, but only when you can still explain them the next morning.

Frequently asked questions about Linux split tunneling

Frequently Asked Questions

What is Linux split tunneling

How does WireGuard split tunneling work on Linux

Does ProtonVPN support Linux split tunneling

Does ProtonVPN Linux split tunneling work on Kali

What is the difference between split tunneling and full tunneling

How does OpenVPN split tunneling work

Is Linux split tunneling safe

Can split tunneling cause DNS leaks

Can I keep my local network outside the VPN

Which Linux split tunneling method is best for applications

VPN & Network Infrastructure Cluster

Some links in this article are affiliate links. If you use them, I may earn a small commission — at no extra cost to you. I only recommend tools I’ve actually tested inside my own cybersecurity lab. Read the full disclaimer.

In many cases, these links unlock better deals than you’ll find on your own.
No paid reviews. No sponsored opinions. Just real testing and real setups.

If you decide to use them, you’re not just getting a discount — you’re helping keep this lab running.

2 Comments

  1. I just tried this on my Kali box and it worked perfectly. Honestly, I always thought split tunneling was only a Windows thing. Your nftables example saved me hours of frustration — thanks a lot!

    1. Glad to hear it worked for you! 🙌 A lot of people assume split tunneling on Linux is black magic, but with a little policy routing and nftables it becomes pretty straightforward. Keep experimenting — every setup has its quirks. And if you want to go a step further, check out my VPN killswitch guide. That way you’ll have a true fail-closed setup with zero leaks. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *