OS X Automatic VPN Connection

When I wander from place to place, I don’t want to have to remember to connect to the right VPN.

If I’m doing something for work, I need to be on the work VPN (IPSec), and if not, I should be on my personal VPN (OpenVPN , using Viscosity ). Unfortunately, there is no easy way to check the box and have it all done automagically, particularly when work and personal VPNs are different software.

Scripting

A small amount of scripting will solve this problem. Because Apple is involved, we have some calls for AppleScript . Everything else is plain shell.

 1#!/bin/bash
 2
 3set -e
 4
 5PATH="/bin:/usr/bin:/usr/local/bin"
 6
 7while getopts "i:t" COMMAND_LINE_ARGUMENT ; do
 8	case "${COMMAND_LINE_ARGUMENT}" in
 9		i) install="YES"
10			;;
11		t) test_mode="YES"
12			;;
13		\?) echo "-i and -t are optional"
14			exit 1
15			;;
16	esac
17done
18
19cmd_pfx=""
20if [ "${test_mode}" = "YES" ]; then
21	echo "Test Mode"
22	cmd_pfx="echo Would issue"
23fi
24
25# Get our current SSID
26current_ssid=`networksetup -getairportnetwork en0 | cut -c 24-`
27# Home VPN profile to execute
28viscosity_connection="home"
29# Work and home
30whitelist=("<work ssid>" "<home ssid>")
31# Work datacenter SSIDs
32sites_need_work_vpn="<site1 ssid> <site2 ssid>"
33# Start off untrusted
34untrusted=true
35 
36install () {
37	# Creating plist
38	cat > ${HOME}/Library/LaunchAgents/local.network-change.plist < EOF
39<?xml version="1.0" encoding="UTF-8"?>
40<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
41<plist version="1.0">
42<dict>
43	<key>Enabled</key>
44	<true/>
45	<key>EnvironmentVariables</key>
46	<dict>
47		<key>PATH</key>
48		<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin</string>
49	</dict>
50	<key>Label</key>
51	<string>local.network-change</string>
52	<key>LowPriorityIO</key>
53	<true/>
54	<key>ProgramArguments</key>
55	<array>
56		<string>${HOME}/.config/bin/connect_to_vpn.sh</string>
57	</array>
58	<key>RunAtLoad</key>
59	<true/>
60	<key>WatchPaths</key>
61	<array>
62		<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
63	</array>
64</dict>
65</plist>
66EOF
67
68	# Loading plist
69	${cmd_pfx} launchctl load ${HOME}/Library/LaunchAgents/local.network-change.plist
70
71}
72
73if [ "${install}" == "YES" ] ; then
74	install
75	exit 0
76fi
77
78for ssid in "${whitelist[@]}" ; do
79	# Check if SSID is trustworthy or not
80	if [ "${current_ssid}" == "${ssid}" ] ; then
81		untrusted=false
82	fi
83done
84 
85if [ ${untrusted} == true ] ; then
86	if [ "${current_ssid}" == "`echo ${sites_need_work_vpn} | grep ${current_ssid}`" ] ; then
87		# If we're at work, or a work-datacenter, use the work VPN
88		${cmd_pfx} scutil --nc start "Work IPSEC VPN"
89	else
90		# Otherwise, use the home VPN
91		${cmd_pfx} osascript -e "tell application \"Viscosity\" to connect \"$viscosity_connection\""
92	fi
93fi

You will need to put in the following bits:

  • whitelisted SSIDs
  • work vpn SSIDs
  • Viscosity connection name

Once you have all this defined, you can try running the script. If you’re on a whitelisted SSID or not on a work SSID, nothing should happen. If you’re not on a whitelisted SSID, your personal VPN connection should’ve started up. If you’re on a work-related SSID, your work VPN should’ve started up.

My Viscosity connection looks like this

My IPSec connection looks like this


Footnotes and References

Copyright

Comments