DEV Community

Cover image for πŸ”€ macOS Split-Tunneling VPN Guide: Route Only Specific Subnets
vavilov2212
vavilov2212

Posted on • Edited on

πŸ”€ macOS Split-Tunneling VPN Guide: Route Only Specific Subnets

Many remote developers need to access company-internal services behind a VPN. The standard VPN setup? Connect using L2TP over IPsec.

But that usually routes all your traffic through the VPN β€” from websites to updates and personal apps.

😬 Not ideal when you only need access to a specific internal subnet.

Let’s fix that with this split tunneling guide.


🧠 What Is Split Tunneling?

Split tunneling means routing only specific IP ranges (like your company subnet) through the VPN, while everything else uses your normal internet connection.

Example:

Internet traffic  ─────────► stays local
Internal subnet   ─────────► goes through VPN

Enter fullscreen mode Exit fullscreen mode

This results in:

  • ⚑ Better internet performance
  • πŸ”’ Better privacy
  • 🎯 More precise access to internal resources

❗ Default VPN Behavior on macOS

If you're using System Settings > Network to connect via L2TP over IPsec:

  • macOS routes all traffic through the VPN once connected
  • There’s no tun/ppp interface visible in ifconfig
  • No native UI option for split tunneling

πŸ”§ How To Manually Add a Route

Let’s say:

  • Your internal company subnet is <YOUR_SUBNET> (e.g., 192.168.50.0/24)
  • Your VPN gateway IP is <VPN_GATEWAY_IP> (e.g., 10.8.0.1)

After connecting to VPN:

sudo route -n add <YOUR_SUBNET> <VPN_GATEWAY_IP>
Enter fullscreen mode Exit fullscreen mode

πŸ” Example:

sudo route -n add 192.168.50.0/24 10.8.0.1
# βœ… Expected output:
# add net 192.168.50.0: gateway 10.8.0.1
Enter fullscreen mode Exit fullscreen mode

βš™οΈ Automating with /etc/ppp/ip-up

Let’s automate route setup when PPP-based VPN connects.

Create a new script:

sudo nano /etc/ppp/ip-up
Enter fullscreen mode Exit fullscreen mode

Paste this:

#!/bin/sh
# /etc/ppp/ip-up is triggered after a successful VPN connection
# $5 is the VPN gateway IP passed by macOS

VPN_GATEWAY="<VPN_GATEWAY_IP>"  # e.g., 10.8.0.1
TARGET_SUBNET="<YOUR_SUBNET>"   # e.g., 192.168.50.0/24

if [ "${5:-}" = "${VPN_GATEWAY}" ]; then
    /sbin/route -n add -net $TARGET_SUBNET $5 > /tmp/ppp.log 2>&1
fi
Enter fullscreen mode Exit fullscreen mode

Make it executable:

sudo chmod +x /etc/ppp/ip-up
Enter fullscreen mode Exit fullscreen mode

πŸ“„ The script logs output to:

sudo cat /tmp/ppp.log
Enter fullscreen mode Exit fullscreen mode

🧼 Optional: Cleaning Up with /etc/ppp/ip-down

To remove the route automatically when VPN disconnects:

sudo nano /etc/ppp/ip-down
Enter fullscreen mode Exit fullscreen mode
#!/bin/sh
VPN_GATEWAY="<VPN_GATEWAY_IP>"  # e.g., 10.8.0.1
TARGET_SUBNET="<YOUR_SUBNET>"   # e.g., 192.168.50.0/24

if [ "${5:-}" = "${VPN_GATEWAY}" ]; then
    /sbin/route -n delete -net $TARGET_SUBNET $5
fi
Enter fullscreen mode Exit fullscreen mode

Make it executable:

sudo chmod +x /etc/ppp/ip-down
Enter fullscreen mode Exit fullscreen mode

πŸ“‘ How to Test If the Route Works

1. Check the Routing Table

netstat -nr | grep <YOUR_SUBNET_PREFIX>
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Example:

netstat -nr | grep 192.168.50
# Expected output:
# 192.168.50.0/24   10.8.0.1        UGSc           25       0     en0
Enter fullscreen mode Exit fullscreen mode

2. Try a Ping

ping <INTERNAL_SERVER_IP>
# Example:
# ping 192.168.50.10
# Expected output:
# 64 bytes from 192.168.50.10: icmp_seq=0 ttl=64 time=30.1 ms
Enter fullscreen mode Exit fullscreen mode

3. Read the Log File

cat /tmp/ppp.log
# Example log:
# add net 192.168.50.0: gateway 10.8.0.1
Enter fullscreen mode Exit fullscreen mode

πŸ“ If there's an error (e.g., gateway not reachable), it will show up here.


🧱 Visual: Full Tunnel vs. Split Tunnel

πŸ”’ Full Tunnel (Default Behavior)

All traffic
    β”‚
    β–Ό
[ VPN Gateway ] ─────► [ Company Resources ]
      β–²
      β”‚
[ Your System ]──────► Internet (via VPN)

Enter fullscreen mode Exit fullscreen mode

⚑ Split Tunnel (Your Configuration)

[ Your System ]
   β”‚       β”‚
   β”‚       └───────► Internet (direct)
   β”‚
   └───────► VPN Gateway ───► <YOUR_SUBNET>
                         β–²
                         β”‚
                 [ Company Resources ]

Enter fullscreen mode Exit fullscreen mode

❗ What If VPN Pushes a Default Route?

Some VPN servers force your system to route all traffic through them.

To override:

1. Find Your Default Gateway

Before connecting:

netstat -nr | grep default
# Example output:
# default            192.168.1.1        UGSc           86       0     en0
Enter fullscreen mode Exit fullscreen mode

Save this value.

2. After Connecting to VPN

sudo route delete default
sudo route add default <YOUR_LOCAL_GATEWAY>
# Example
# sudo route delete default
# sudo route add default 192.168.1.1
Enter fullscreen mode Exit fullscreen mode

⚠️ Do this with caution β€” if you get it wrong, you may temporarily lose internet.


βœ… Summary

  • πŸ”Œ L2TP/IPsec VPN on macOS routes all traffic by default
  • πŸ”€ Split tunneling lets you access only what's needed
  • πŸ› οΈ Automate routes with /etc/ppp/ip-up
  • 🧹 Clean up with /etc/ppp/ip-down
  • 🧾 Logs are saved to /tmp/ppp.log
  • πŸ§ͺ Testing ensures everything’s working as expected
  • 🚧 Optionally override VPN-pushed routes

πŸ”— Further Reading

Top comments (0)