VPN split tunneling on Mac default client (Cisco IPsec)

The first thing one needs to do is identify your router gateway ip address. To do that simply check the routing table:

$ netstat -rn
Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            10.0.1.1           UGScI          83        0     en3
130.14.65.1        10.0.1.1           UGHS            3      262     en3

The top of the routing table will show the default gateway (make sure you are off the vpn to run that).

Next step is to go ahead and connect to the vpn (when doing so go to the network pannel and note your new ip address.

Once connected we can look at the interface number using ifconfig.

$ ifconfig
# The output will be similar to this one
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
XHC0: flags=0<> mtu 0
XHC20: flags=0<> mtu 0
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	options=6b<RXCSUM,TXCSUM,VLAN_HWTAGGING,TSO4,TSO6>
	ether 1c:1b:0d:65:57:67
	nd6 options=201<PERFORMNUD,DAD>
	media: autoselect (<unknown type>)
	status: inactive
utun4: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1280
	inet 168.0.0.1 --> 168.0.0.4 netmask 0xfffffc00

If we look at the following output we can match the inet number with the vpn ip address we got earlier. (In this example 168.0.0.1).

Now let’s go back to the routing table and take note of every route that goes to the utun4 interface.

Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            link#14            UCS            88        0   utun4
default            10.0.1.1           UGScI          27        0     en3
50.10.8.199        link#14            UHW3I           0       24   utun4     82
40.100.2.110       link#14            UHWIi           1       15   utun4

If we look at the following example we can see 2 ip address that connects to the utun4 interface (the ip starts with 50 and 40).

Now let’s do a little script we can run as sudo.

#!/bin/bash

if [[ $EUID -ne 0 ]]; then
    echo "Run this as root"
    exit 1
fi

# If your utun interface tend to change like mine you can do the following given the right interface is the last one in the list
INTERFACE=$(ifconfig | grep utun | cut -d : -f 1 | grep utun | tail -n 1)

# use this syntax if your interface tends to change
route -nv add -net 40 -interface $INTERFACE

# last line in the file is the gateway ip
route change default 10.0.1.1

Now let’s make this script executable and run it.

$ chmod +x vpn.sh
$ sudo ./vpn.sh

Tada !

Bonus

If you want to make this run automatically one can use a launch deamon.

$ sudo touch /Library/LaunchDaemons/network.watcher.plist
$ sudo chown root:staff /Library/LaunchDaemons/network.watcher.plist

# Write the following to the previous file (replace the /patch/to/script with your absolute path
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>network.watcher</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>/path/to/script.sh</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/Library/Preferences/SystemConfiguration</string>
    </array>
</dict>
</plist>

# Now load the deamon
$ sudo launchctl load -w /Library/LaunchDaemons/network.watcher.plist