How to Configure VPN Split Tunnel on Mac

In this current world of remote work, we continue to see a growth in the use of VPNs in enterprises to support secure remote experiences for their users within their corporate network.

The norm in most institutions is that there will be an entire IT-support team dedicated to the provisioning of the required tools configured for use within the organization. Such are configured for accessing internal servers while accessing resources on internet and jumping into video calls. But then again this does not apply for every use case…

In certain cases you’ll need a device not configured for use within the corporate network or some institutions may not offer the support in setting up your devices for the same as well.

A VPN routes all the network connections through the VPN tunnel, this dramatically slows down connection to internet resources, at times refusing connection to others.

Split tunneling works by tunneling some of your traffic through a VPN and routing the rest via the open network. This way, you have both the benefits of a secure connection to your on-premise servers as well as a speedy connection to the open internet.

In this article we will set up split tunelling with Openconnect alongside vpn-slice(a vpnc-script replacement) to set your own split tunnel on client side. vpn-slice routes only traffic for specific hosts and/or subnets through the VPN by looking up named hosts, using the VPN's DNS servers, and adding these entries to the /etc/hosts (which it cleans up after VPN disconnection).

  1. Install Openconnect via Homebrew.
brew update
brew install openconnect

2. Add password-less sudo ability for the openconnect command.

sudo sh -c \
'echo "%admin ALL=(ALL) NOPASSWD: /usr/local/bin/openconnect" > /etc/sudoers.d/foo'

3. Test the vpn connection with:

sudo openconnect --user=<VPN username> <VPN host>

You will be prompted for your vpn password if any exists.

To exit use control + c(for mac).

Note: Newer versions of OpenConnect will use the utun device on OS X which does not require the TUN/TAP driver or other additional kernel modules to be installed.

4. Now we install vpn-slice via Homebrew.

brew install vpn-slice

5. While it would be easy to initiate the connection with a single command as below;

sudo openconnect --user=<VPN username> <VPN host> \
--script 'vpn-slice <internal host> <internal CIDR range>'

At times this becomes cumbersome in a practical daily use basis. Just to put this into context, if my vpn is set up for VPN host vpn.example.com with my internal host example.com and internal CIDR range 192.168.1.0/24for user johndoe

sudo openconnect --user=johndoe vpn.example.com \
--script 'vpn-slice example.com 192.168.1.0/24'

Any new internal host or CIDR range would require to be added to the list and the list may end up becoming too long. The easiset way out would be transforming this into shell functions and designing simpler commands that will be used for each new connection.

Scripting our shell functions

  1. Create a vpn-slice-addresses script in ~/vpn-slice-addresseswith the following:
#!/bin/sh

# Script that starts vpn-slice with the hostnames/subnets
# that need to be accessed via the VPN.

vpn-slice \
<host 1> \
<host 2> \
<CIDR range A> \
<CIDR range B>

Note: This file can live in any location as long as it is correctly referenced in the following steps.

2. Set the right permissions for the script:

chmod a+x ~/vpn-slice-addresses

3. Create the following functions in your .zshrc (or in a file that you source from your .zshrc). By default .zshrc located at ~/.zshrc:

export COMPANY_VPN_HOST=<VPN host>export VPN_USER=<VPN USER>function vpn-up() {
if [[ -z $COMPANY_VPN_HOST ]]
then
echo "Please set COMPANY_VPN_HOST env var"
return
fi
if [[ "$1" == "split" ]]
then
echo "Starting the vpn with split tunneling ..."
sudo openconnect --background --script='~/vpn-slice-addresses' --user=$VPN_USER $COMPANY_VPN_HOST
else
echo "Starting the vpn ..."
sudo openconnect --background --user=$VPN_USER $COMPANY_VPN_HOST
fi
}

function vpn-split() {
vpn-up split
}

function vpn-down() {
sudo kill -2 `pgrep openconnect`
}

For any help on the various tags used in the openconnect command, you can click here.

4. Reconfigure your .zshrc

source ~/.zshrc

5. Connect!

If you wand to send all the traffic through the VPN do:

vpn-up

If instead you want to do Split Tunneling, use:

vpn-split

6. Disconnect

Given OpenConnect is started using the --background flag, we can't use Ctrl-Cto close it, instead we need to run:

vpn-down

- DevSecOps Engineer at Safaricom PLC | AiOps & Founder Ticko Africa

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

My decade in review : 2010s

CS371 Spring 2022: Hrithik Ramganesh

Getting Started with Git

How to Publish to an Amazon SNS topic while keeping the messages secure in a private network using…

Kubernetes: Up & Integrated — Secrets & Configuration

COTI Pay VIPER is here!

Kubernetes Startup Probes — Examples & Common Pitfalls

Agile development process for my Upgrad Assignment

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Keith Njagi

Keith Njagi

- DevSecOps Engineer at Safaricom PLC | AiOps & Founder Ticko Africa

More from Medium

Build Your Personal Brand with a Profile Page using GitHub Pages and Hugo

I am having fun with NFC Tag with my iPhone

GitHub workflow

Storing Amazon SES Tracking Events directly in Mysql (RDS) Reduced our Load by 40%