How to split traffic on GlobalProtect VPN on Mac OS

Updated on 2021-01-16

Recently the company I work for started to use Palo Alto's GlobalProtect as a solution for VPN. The solution works quite well but has 2 flaws by default that I don't like.

First is that the GlobalProtect agent (client) runs automatically after the operating system turns on and this behavior can't be changed in the settings. You can find a solution for it on other blogs.

The second flaw is that it automatically sends ALL of my traffic through my company's VPN. I don't think this is beneficial for the company but most importantly it goes against my privacy. There is no need for the employer to know what goes on in my traffic.

This article describes:

  • How to split traffic based on IP addresses

  • How to do traffic splitting automatically after the GlobalProtect agent connects to VPN

I will only focus on Mac OS but similar steps can be taken also on other operating systems.

Traffic split with GlobalProtect

When you connect to VPN with GlobalProtect, it creates a new network interface and edits the routing table so all our traffic is sent through this new network interface.

To solve this we need to remove a route created by GlobalProtect and then create a few new routes for only those IP addresses which we want to be directed through our VPN.

We implemented it in Python (based on this blog post). Save the script as split_vpn.py to your home folder. Edit the lists VPN_NETS and VPN_HOSTS based on your needs. Then you can run it every time you want to split traffic.

#!/usr/bin/env python
import os
import re
import subprocess
import sys

WIRELESS_INTERFACE = 'en0'    # could be different on other systems
TUNNEL_INTERFACE = 'utun2'

VPN_NETS = [
    '172.222',                # subnets which should use VPN
]

VPN_HOSTS = [
    '90.131.25.244',
    '90.131.25.240',        # IP address which should use VPN
]


def get_tunnel_interface():
    # Get last utun interface.
    for line in reversed(subprocess.check_output(["ifconfig"]).splitlines()):
        match = re.match(r"(utun\d)", line)
        if match:
            return match.groups(1)[0]


def split_vpn_traffic():
    if os.getuid() != 0:
        sys.exit("Please, run this command with sudo.")

    gateway = None
    tunnel_interface = get_tunnel_interface()
    out = subprocess.check_output(("netstat", "-nrf", "inet"))
    routes = out.decode("utf-8").split("\n")[3:]

    for route in routes:
        route = route.split()
        interface = route[3]
        if interface == WIRELESS_INTERFACE:
            gateway = route[1]
            break

    if gateway is None:
        sys.exit("Unable to determine VPN default gateway.")

    print("Resetting routes with gateway " + gateway)
    subprocess.call(
        ("route", "-n", "delete", "default", "-ifscope", WIRELESS_INTERFACE)
    )
    subprocess.call(
        ("route", "-n", "delete", "-net", "default", "-iface", tunnel_interface)
    )
    subprocess.call(("route", "-n", "add", "-net", "default", gateway))

    print("\nAdding routes for addresses which should go through VPN.")
    for addr in VPN_NETS:
        subprocess.call(
            ("route", "-n", "add", "-net", addr, "-iface", tunnel_interface)
        )
    for addr in VPN_HOSTS:
        subprocess.call(
            ("route", "-n", "add", "-host", addr, "-iface", tunnel_interface)
        )


if __name__ == "__main__":
    split_vpn_traffic()

Automatic traffic split after connecting to VPN

Now that we have the script to split our traffic, we want it to run automatically after we connect to VPN with GlobalProtect. As it is stated in the documentation, GlobalProtect agent can run commands before connecting, after connecting and before disconnecting.

Follow these steps to run the script after GlobalProtect agent connects to VPN:

  1. Disable and close GlobalProtect

  2. Run killall cfprefsd

  3. Open in editor /Library/Preferences/com.paloaltonetworks.GlobalProtect.settings.plist

  4. Add to the section /Palo Alto Networks/GlobalProtect/Settings/ following (edit path based on your username):

<key>post-vpn-connect</key>
<dict>
        <key>command</key>
        <string>/Users/your_usename/post_vpn_connect.sh</string>
        <key>context</key>
        <string>admin</string>
</dict>
  1. Add this script to your home folder and save it as post_vpn_connect.sh
#!/bin/bash
osascript -e 'display notification "Start" with title "VPN traffic split"'

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

${DIR}/split_vpn.py

country=`curl ifconfig.co/country`

osascript -e "display notification \"End. You country is $country\" with title \"VPN traffic split\""

Now your traffic should be automatically split each time you connect to VPN with GlobalProtect. Nice!