Skip to content

Instantly share code, notes, and snippets.

@ekho
Last active August 6, 2018 08:59
Show Gist options
  • Save ekho/8caf196d5d815c8f723345ff0676f6e2 to your computer and use it in GitHub Desktop.
Save ekho/8caf196d5d815c8f723345ff0676f6e2 to your computer and use it in GitHub Desktop.
Autoconnect to openvpn when connected to public WiFi SSIDs

How to

  • Open Tools > Script Editor
  • Paste code
  • Save as Application (not Script) with name ovpn-control
  • Create file ovpn-control-trusted-wifi-ssids.txt near ovpn-control with list of trusted SSIDs (one per line)
  • Add ovpn-control application to autolaunch
  • To hide icon from dock add into Info.plist:
<key>LSUIElement</key>
<string>1</string>
global ovpnConfigName
global notificationTitle
global ovpnPrevState
on idle
set ovpnConfigName to "your-openvpn-config-name"
set notificationTitle to "OpenVPN to " & ovpnConfigName
set trustedWiFiSSIDsFile to ((path to library folder from user domain) as text) & "Mobile Documents:com~apple~ScriptEditor2:Documents:ovpn-control-trusted-wifi-ssids.txt"
set trustedWiFiSSIDs to load_trusted_wifi_ssid_list(trustedWiFiSSIDsFile)
log "Trusted WiFi SSIDs: " & join_list(trustedWiFiSSIDs)
set currentWiFiSSID to do shell script "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}'"
log "Current WiFi SSID: " & currentWiFiSSID
log "curr ssid is trusted: " & ((currentWiFiSSID as string) is in trustedWiFiSSIDs) as string
set WiFiRequiresVPN to not (trustedWiFiSSIDs contains (currentWiFiSSID as string))
log "WiFiRequiresVPN: " & (WiFiRequiresVPN as string)
tell application "/Applications/Tunnelblick.app"
set ovpnConfigs to get name of configurations
log "available ovpn configurations: " & ovpnConfigs
if not (ovpnConfigs contains ovpnConfigName) then
display alert "Can not find ovpn configuration with name " & ovpnConfigName
return 300
end if
set ovpnConfigState to get state of first configuration where name = ovpnConfigName
log ovpnConfigName & " configuration state is " & ovpnConfigState
try
ovpnPrevState
on error errmsg number num
if num is -2753 then
set ovpnPrevState to ""
display notification "Started" with title notificationTitle
end if
end try
end tell
if ovpnConfigState is equal to "CONNECTED" then
if WiFiRequiresVPN then
vpn_show_state(ovpnConfigState, ovpnPrevState)
else
display notification "WiFi SID is " & currentWiFiSSID
vpn_disconnect()
end if
else if ovpnConfigState is equal to "EXITING" then
if WiFiRequiresVPN then
display notification "WiFi SID is " & currentWiFiSSID
vpn_connect()
else
vpn_show_state(ovpnConfigState, ovpnPrevState)
end if
else if ovpnConfigState is equal to "RECONNECTING" then
else
display notification "Unhandled Tunnelblick state " & ovpnConfigState
end if
set ovpnPrevState to ovpnConfigState
return 10
end idle
on vpn_connect()
display notification "Trying to connect" with title notificationTitle
tell application "/Applications/Tunnelblick.app"
if (connect ovpnConfigName) then
display notification "Connect started" with title notificationTitle
else
display notification "Can not connect" with title notificationTitle
end if
end tell
end vpn_connect
on vpn_disconnect()
display notification "Trying to disconnect" with title notificationTitle
tell application "/Applications/Tunnelblick.app"
if (disconnect ovpnConfigName) then
display notification "Disconnect started" with title notificationTitle
else
display notification "Can not disconnect" with title notificationTitle
end if
end tell
end vpn_disconnect
on vpn_show_state(ovpnConfigState, ovpnPrevState)
set stateTitle to "Unhandled state"
if ovpnConfigState is equal to "EXITING" then
set stateTitle to "Disconnected"
else if ovpnConfigState is equal to "CONNECTED" then
set stateTitle to "Connected"
end if
if (ovpnConfigState is not equal to ovpnPrevState) and ("" is not equal to ovpnPrevState) then
display notification stateTitle with title notificationTitle
else
log "Already disconnected"
end if
end vpn_show_state
on load_trusted_wifi_ssid_list(trustedWiFiSSIDsFile)
set listOfSSIDs to {}
set fileHandle to open for access trustedWiFiSSIDsFile
set theLines to paragraphs of (read fileHandle)
close access fileHandle
repeat with theLine in theLines
if length of theLine is greater than 0 then
set variable to theLine as string
copy variable to the end of listOfSSIDs
log "variable: " & variable
end if
end repeat
log "load_trusted_wifi_ssid_list => " & join_list(listOfSSIDs)
return listOfSSIDs
end load_trusted_wifi_ssid_list
on join_list(listVar)
set textVar to ""
repeat with nextItem in listVar
if class of nextItem is equal to "list" then
set nextItem to "{" & join_list(nextItem) & "}"
end if
if length of textVar is greater than 0 then
set textVar to textVar & ", "
end if
set textVar to textVar & nextItem
end repeat
log "join_list => " & textVar
return textVar
end join_list
on quit
display notification "Exiting..." with title notificationTitle
continue quit
end quit
@ekho
Copy link
Author

ekho commented Jul 19, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment