Mullvad VPN manipulates the system routing table to ensure all traffic flows through the VPN tunnel and to implement split tunneling. The implementation varies by platform.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mullvad/mullvadvpn-app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Routing management handles:- Default route replacement - Routes all traffic through tunnel
- Specific routes - Allows API access and relay connectivity
- Split tunneling - Excludes specific applications from tunnel
- Route monitoring - Detects and handles external changes
talpid-routing/src/lib.rs
Core Concepts
Route Structure
A route consists of:talpid-routing/src/lib.rs:75-83
Node Types
Gateway Node:talpid-routing/src/lib.rs:226-249
Route Destinations
Real Node:talpid-routing/src/lib.rs:199-210
Windows Routing
Implementation
Uses IP Helper API and routing change notifications: Source:talpid-routing/src/windows/mod.rs
Route Management
Add route:Default Route Handling
Windows monitors default route changes: Detection:- Listens for
NotifyRouteChange2callbacks - Detects new default gateway
- Updates symbolic default routes
talpid-routing/src/windows/default_route_monitor.rs
Best route selection:
- Interface with lowest metric
- Gateway IP address
- Used to route non-tunnel traffic
talpid-routing/src/windows/get_best_default_route.rs
Split Tunneling (Windows)
Windows implements split tunneling via driver: Architecture:- WFP callout driver intercepts packets
- Checks process path against exclusion list
- Redirects excluded traffic to alternative interface
- Preserves in-tunnel for other traffic
talpid-core/src/split_tunnel/windows/mod.rs
Driver communication:
- Opens device handle to driver
- Sends IOCTLs to configure exclusions
- Monitors driver status
- Watches for excluded executable changes
- Updates driver when paths modified
- Handles volume mount/unmount events
talpid-core/src/split_tunnel/windows/path_monitor.rs
Linux Routing
Implementation
Uses Netlink (rtnetlink) for routing operations: Source:talpid-routing/src/unix/linux.rs
Routing Tables
Linux uses multiple routing tables: Main table (254):
- Default application routes
- Tunnel default route
1984):
- Split tunnel routes
- Excluded process routes
- Selected via fwmark
talpid-core/src/firewall/linux.rs:98-100
Route Operations
Add route:RTA_DST- Destination prefixRTA_GATEWAY- Gateway IPRTA_OIF- Output interface indexRTA_PRIORITY- MetricRTA_TABLE- Routing table IDRTA_METRICS- MTU and other metrics
talpid-routing/src/unix/linux.rs
Default Route Replacement
Tunnel setup replaces default route:Policy Routing
Linux uses policy routing for split tunneling: IP rules:Split Tunneling (Linux)
cgroup2 Method (Modern)
Primary method using cgroups v2: Source:talpid-core/src/split_tunnel/linux/mod.rs:99-112
Setup:
-
Create cgroup2 at
/sys/fs/cgroup/mullvad-exclusions -
Add PIDs to cgroup:
-
nftables matches cgroup:
talpid-core/src/firewall/linux.rs:355-375
How it works:
- Processes added to cgroup2
- All packets from cgroup get fwmark
- Policy routing sends marked packets to custom table
- Custom table routes to non-tunnel interface
/sys/fs/cgroup
Customize: TALPID_CGROUP2_FS=/custom/path
Source: docs/README.md:207-210
net_cls Method (Legacy)
Fallback using cgroups v1 net_cls controller: Source:talpid-core/src/split_tunnel/linux/mod.rs:114-124
Setup:
-
Mount net_cls (if needed):
Customize:
TALPID_NET_CLS_MOUNT_DIR=/custom/path -
Create cgroup:
-
Add PIDs:
-
nftables matches classid:
talpid-core/src/firewall/linux.rs:376-383
How it works:
- Processes added to net_cls cgroup
- Packets inherit classid (0xf41)
- nftables matches classid
- Applies fwmark for routing
docs/README.md:212-214
Firewall Integration
Split tunnel rules in nftables: Mangle chain (mark packets):talpid-core/src/firewall/linux.rs:391-495
Connection Tracking
Connection tracking ensures consistency:- New connections marked based on cgroup
- Subsequent packets match conntrack mark
- Survives process exit or cgroup removal
talpid-core/src/firewall/linux.rs:426-441
macOS Routing
Implementation
Uses routing socket and BSD routing APIs: Source:talpid-routing/src/unix/macos/mod.rs
Routing Socket
MacOS communicates viaPF_ROUTE socket:
Operations:
RTM_ADD- Add routeRTM_DELETE- Delete routeRTM_GET- Query routeRTM_CHANGE- Modify route
talpid-routing/src/unix/macos/routing_socket.rs
Default Route Monitoring
Monitors default route changes: Detection:DefaultRouteAdded- New default gatewayDefaultRouteRemoved- Default gateway removedDefaultRouteChanged- Gateway IP changed
talpid-routing/src/unix/macos/watch.rs
Route parsing:
- Reads routing messages from socket
- Parses route attributes (dst, gateway, interface)
- Identifies default routes (
0.0.0.0/0,::/0) - Resolves MAC address via ARP
talpid-routing/src/unix/macos/default_routes.rs
Split Tunneling (macOS)
MacOS implements split tunneling via PF routing: Mechanism:- Process monitoring tracks excluded apps
- PF rules use BPF device filters
- Route-to directs traffic to physical interface
- Preserves tunnel traffic for other apps
talpid-core/src/split_tunnel/macos/mod.rs
PF route-to rule:
- Matches tunnel interface
- Routes to physical interface instead
- Bypasses tunnel for excluded processes
talpid-core/src/firewall/macos.rs:755-775
Process identification:
- Uses Endpoint Security framework
- Monitors process launch/exit
- Tracks process tree (parent-child)
- Updates exclusions dynamically
talpid-core/src/split_tunnel/macos/process.rs
BPF integration:
- Attaches BPF program to interface
- Filters packets by process
- Works with PF rules for routing
talpid-core/src/split_tunnel/macos/bpf.rs
Interface and Gateway Resolution
Gateway includes MAC address:talpid-routing/src/lib.rs:63-70
Android Routing
Implementation
Uses VPN Service API - no direct routing control: Source:talpid-routing/src/unix/android.rs
VPN Service Routing
Configuration:- System handles all routing automatically
- Cannot add specific routes
- Split tunneling via allowed/disallowed apps
Split Tunneling (Android)
Per-app exclusion:- Excluded apps bypass VPN entirely
- Use system default routes
- Get system DNS
docs/split-tunneling.md:63-73
Route Manager Interface
Initialization
Adding Routes
Simple route:talpid-routing/src/lib.rs:170-196
Removing Routes
Default Route Handling
Routes usingDefaultNode update automatically:
- Route manager detects change
- Updates all
DefaultNoderoutes - Uses new default gateway
talpid-routing/src/lib.rs:199-210
Common Routing Patterns
Tunnel All Traffic
Relay Endpoint Access
API Access
LAN Access
MTU Considerations
Routes can specify MTU:- WireGuard adds ~60 bytes overhead
- Prevents fragmentation
- Typical: 1420 for tunnel, 1380 for multihop
talpid-routing/src/lib.rs:192-196
Monitoring and Resilience
Route Change Detection
All platforms monitor routing changes: Windows:NotifyRouteChange2callbacks- Detects route additions/deletions
- Updates symbolic routes
talpid-routing/src/windows/default_route_monitor.rs
Linux:
- Netlink route notifications
- Monitors
RTM_NEWROUTE/RTM_DELROUTE - Validates expected routes
talpid-routing/src/unix/linux.rs
macOS:
- Routing socket messages
- Parses
RTM_*events - Updates gateway information
talpid-routing/src/unix/macos/watch.rs
Route Restoration
On disconnect:- Remove tunnel default routes
- Restore original default gateway
- Delete custom routes
- Reset routing tables (Linux)
Split Tunneling Summary
Windows
Method: WFP callout driver Granularity: Per executable path How: Driver intercepts and redirects packetsLinux
Method: cgroup2 + nftables (or net_cls fallback) Granularity: Per process (PID) How: Mark packets, policy routing to alternate tablemacOS
Method: PF route-to + process monitoring Granularity: Per process tree How: BPF + PF rules route to physical interfaceAndroid
Method: VPN Service disallowed apps Granularity: Per app package How: System bypasses VPN for excluded apps Source:docs/split-tunneling.md
Environment Variables
docs/README.md:207-214
Troubleshooting
Routes Not Applied
Check route manager status:Split Tunneling Not Working
Linux - Verify cgroup:Default Route Issues
Symptoms: No connectivity after tunnel up Diagnosis:- Verify tunnel interface exists
- Check default routes point to tunnel
- Verify relay route via physical interface
- Check firewall allows relay endpoint