How to route certain applications through a VPN and others to use my 'standard' connection in OSX 10.6?

I am currently working abroad and use my company's VPN for FTP and some browsing. This is a relatively slow connection and while it is suitable for those VPN necessities; much of my other internet usage can be done without the VPN at a much higher speed.

Is there a way to tell Safari and my FTP software to use the VPN and for all other connections to go directly to the internet.

I am currently using OSX's Network Prefs for running my VPN connection.

Ta


I would consider the use of VirtualBox/VMWare Player to run a small machine for your VPN connection requirements so you can leave your main internet connection of your computer free of customizations.

In this way, both connections are completely separated and you don't have to configure or customize your routing tables or worry about complex network configurations.


It looks like you know what network IPs and domain you are connecting to.

A way of achieving this would be to only use the VPN based on which IP/domain you are requesting.

You can do this by using the macOS built-in VPN with "Send all traffic through VPN" unchecked, and define routes.

For instance, if your FTP server is at 1.2.3.4, this command will make sure that traffic to 1.2.3.4 will use the VPN to access the internet:

/sbin/route -n add -net 1.2.3.4/32 -interface ppp0

Note: you can list all existing route with netstat -rn.

And if you have dynamic IPs behind DNS, you can use dig to retrieve the IP and add it to routes. (10.11.12.13 is the IP address your got from the VPN).

dig -b 10.11.12.13 +noall +answer ftp.company.example

There is also a hooking mechanism that will look at /etc/ppp/ip-up and execute it, that helps automate the above process. This bash script can create routes and lookup IP addresses for you automatically.

That's a rough example to give an idea of what can be done:

#!/bin/bash

# change name to whatever your VPN is named in Pref system
vpn_name="Company vpn" 

read_args() {
  # Example: ppp0 0 10.239.163.212 192.0.2.1 192.168.2.1
  iface=$1; shift 3
  remote_ip=$1; shift
}

log() {
  echo "$@" >&2
  echo "$@" 2>/dev/null >> /tmp/vpn-split-tunnel.log
}

get_vpn_iface() {
  /usr/sbin/scutil --nc status "$vpn_name" | grep InterfaceName | awk '{ print $3 }'
}

lookup_ips() {
  if [ "$MAC_OS_MAJOR_VER" -ge 11 ]; then
    xargs dig -b $remote_ip +noall +answer | grep 'IN\s\s*A' | awk '{ print $NF "/32" }'
  else
    xargs dig +noall +answer | grep 'IN\s\s*A' | awk '{ print $NF "/32" }'
  fi
}

init() {
  echo "" 2>/dev/null > /tmp/vpn-split-tunnel.log
  read_args "$@"
  vpn_iface=$(get_vpn_iface)

  if [[ "$iface" != "$vpn_iface" && -z "$DEBUG" ]]; then
    log "Interface $iface is not for the \"$vpn_name\" connection on interface $vpn_iface"
    exit
  fi
}

init "$@"

cmd=(/sbin/route -n add -net "1.2.3.4/32" -interface "$iface")
log ">> ${cmd[@]}" 
log $(${cmd[@]} 2>&1)