Skip to content

Instantly share code, notes, and snippets.

@kaleksandrov
Last active April 19, 2024 03:46
Show Gist options
  • Save kaleksandrov/3cfee92845a403da995e7e44ba771183 to your computer and use it in GitHub Desktop.
Save kaleksandrov/3cfee92845a403da995e7e44ba771183 to your computer and use it in GitHub Desktop.
Simple script that starts and stops GlobalProtect.app on Mac OSX.
#!/bin/bash
case $# in
0)
echo "Usage: $0 {start|stop}"
exit 1
;;
1)
case $1 in
start)
echo "Starting GlobalProtect..."
launchctl load /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
launchctl load /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
echo "Done!"
;;
stop)
echo "Stopping GlobalProtect..."
launchctl remove com.paloaltonetworks.gp.pangps
launchctl remove com.paloaltonetworks.gp.pangpa
echo "Done!"
;;
*)
echo "'$1' is not a valid verb."
echo "Usage: $0 {start|stop}"
exit 2
;;
esac
;;
*)
echo "Too many args provided ($#)."
echo "Usage: $0 {start|stop}"
exit 3
;;
esac
@danielcn
Copy link

danielcn commented Mar 9, 2020

Very useful. Thanks!

@andrewrod33
Copy link

Solved my issue, thanks!

@riker1
Copy link

riker1 commented Dec 8, 2020

Excellent find! My GP just took a shit on me and then nothing would get it back working (did not want to restart!). thank you.

@albertomino
Copy link

Thanks kaleksandrov! It was very helpful.

@sming
Copy link

sming commented Oct 2, 2021

Hi, I'm new to Gists and I don't know if it's OK/cool/not-cool to link to a gist as a comment... If it's not, I'll delete the comment.

But I basically made this gist more foolproof (cos i is a f00l who needs all the protection he can get...) - you just call the script and it enables/disables globalprotect accordingly. Tested on MacOS 11.6 Big Sur :

GIST: globalprotect-vpn-toggler.sh. Cheers!

@kaleksandrov
Copy link
Author

Hi, I'm new to Gists and I don't know if it's OK/cool/not-cool to link to a gist as a comment... If it's not, I'll delete the comment.

But I basically made this gist more foolproof (cos i is a f00l who needs all the protection he can get...) - you just call the script and it enables/disables globalprotect accordingly. Tested on MacOS 11.6 Big Sur :

GIST: globalprotect-vpn-toggler.sh. Cheers!

Thanks Peter,

It is perfectly cool :)

Best regards,
Kiril

@bullth
Copy link

bullth commented Dec 2, 2021

@sming thx m8. perfectness in its simplicity :-D

@vurtomatic
Copy link

I'm getting this error:

Starting GlobalProtect...
Load failed: 5: Input/output error
Load failed: 5: Input/output error
Done!

@chungwy
Copy link

chungwy commented Apr 16, 2022

Starting GlobalProtect...
Load failed: 5: Input/output error
Try running launchctl bootstrap as root for richer errors.
Load failed: 5: Input/output error
Try running launchctl bootstrap as root for richer errors.
Done!

@ndutyme
Copy link

ndutyme commented Apr 19, 2022

I don't think these commands work for some GlobalProtect clients or OS versions. Running either this script, or either commands individually as root on my macOS 12.2.1 system does not stop or start the GlobalProtect client and it also does not break my GlobalProtect clients VPN connection to our Firewall. Maybe something changed either with the GP client, it's configuration (could ours be configured to not allow this?), or something new in the macOS 12.

@jldeen
Copy link

jldeen commented May 5, 2022

@ndutyme What version of GP are you using? I am running macOS 12.4 Beta (21F5071b) and Global Protect 6.0.0-262 and these commands work for me, though I made a script more suitable to my needs. I created the following 2 functions and can call them with ease from the command line:

function unloadGlobalProtect {
  launchctl unload -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist

  launchctl unload -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
}

function loadGlobalProtect {
  launchctl load -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist

  launchctl load -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
}

Note the difference between launchctl unload and launchctl remove is the first stops, unloads the job, waits for the job to stop, and allows the job to restart on the next login/reboot. As it waits, it supports error handling. The second, simply removes the job from launchd but does so asynchronously, as such, since there is no wait, there is no error handling.

@dlvhdr
Copy link

dlvhdr commented May 18, 2022

@jldeen your scripts result in the same errors for me:

Unload failed: 5: Input/output error
Try running `launchctl bootout` as root for richer errors.

I'm using GP version 5.2.10-6 with macOS 12.3.1

@dlvhdr
Copy link

dlvhdr commented Jun 20, 2022

This works for me:

launchctl enable gui/501/com.paloaltonetworks.gp.pangpa
launchctl enable gui/501/com.paloaltonetworks.gp.pangps

launchctl bootout gui/501 /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
launchctl bootstrap gui/501 /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist

launchctl bootout gui/501 /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
launchctl bootstrap gui/501 /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist

@Alechan
Copy link

Alechan commented Aug 1, 2022

Is there a way to also auto-connect?

After loading GlobalProtect in the terminal I have to still manually connect

@dlvhdr
Copy link

dlvhdr commented Aug 1, 2022

Is there a way to also auto-connect?

After loading GlobalProtect in the terminal I have to still manually connect

I have an apple script for that:

#!/bin/sh

osascript <<EOF
tell application "System Events" to tell process "GlobalProtect"
  click menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubar
  click button 2 of window 1 -- Clicks either Connect or Disconnect
  click menu bar item 1 of menu bar 2 -- This will close the GlobalProtect "window" after clicking Connect/Disconnect. This is optional.
end tell
EOF

@Alechan
Copy link

Alechan commented Aug 1, 2022

Works great, thanks!

@Alechan
Copy link

Alechan commented Aug 1, 2022

How to of GlobalProtect + zsh + skhd

  1. Add the following to ~/.zshenv (create it if doesn't exist already)
# Kill VPN
function unloadGlobalProtect {
  launchctl unload -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist

  launchctl unload -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
}

# Start VPN process
function loadGlobalProtect {
  launchctl load -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist

  launchctl load -w /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist

}

# Toggle VPN connection
function toggleGlobalProtectConnection {
	osascript <<EOF
	tell application "System Events" to tell process "GlobalProtect"
		click menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubar
		click button 2 of window 1 -- Clicks either Connect or Disconnect
		click menu bar item 1 of menu bar 2 -- This will close the GlobalProtect "window" after clicking Connect/Disconnect. This is optional.
	end tell
EOF
}
  1. Add bindings to skhd. For example these are mine (you may need to remove default MacOS bindings)
rcmd + ralt - space : zsh -c "toggleGlobalProtectConnection" # (dis)connect to VPN
# 0x2B = ,
# 0x2F = .
rcmd + ralt - 0x2B : zsh -c "unloadGlobalProtect " # killall global protect
rcmd + ralt - 0x2F : zsh -c "loadGlobalProtect " # start global protect
  1. Stop skhd service and start it manually to confirm everything is working fine
brew services stop skhd
skhd
  1. Play with the keybindings and see the functions outputs in the terminal from 3.

  2. Stop manual instance of skhd and restart service

# CTRL + C
brew services start skhd

@technocrat22
Copy link

technocrat22 commented Aug 29, 2022

How can I add drop-down option with diff VPN portals available to choose and connect in GP app via script/code for Mac?
OR
Deploy Mac GP App with list of available VPN portals to be chosen by user and connect ?

@jesusvico
Copy link

Thanks!

@stefanpricopie
Copy link

Thanks!

@OleksandrKucherenko
Copy link

OleksandrKucherenko commented Nov 30, 2022

Auto connects on recovering from sleep:

brew install sleepwatcher

~/.wakeup:

#!/usr/bin/env bash

# power on
/usr/local/bin/blueutil --power 1

# try to connect headphones
/usr/local/bin/blueutil --connect 00-1b-66-b0-eb-24

# autoconnect VPN
source ./vpn-connect.sh

./vpn-connect.sh

#!/usr/bin/env bash
# https://gist.github.com/kaleksandrov/3cfee92845a403da995e7e44ba771183
  
osascript <<EOF
tell application "System Events" to tell process "GlobalProtect"
	click menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubar
	set frontmost to true -- keep window 1 active
	tell window 1
	  -- Find the status 
	  tell (first UI element whose title is "Connect") to if exists then set message to "VPN is connecting now..."
	  tell (first UI element whose title is "Disconnect") to if exists then set message to "VPN is connected."
	  -- Click connect button
	  tell (first UI element whose title is "Connect") to if exists then click
	end tell
	click menu bar item 1 of menu bar 2 -- This will close the GlobalProtect "window" after clicking Connect/Disconnect. This is optional.
	say message
	return message
end tell
EOF

@devstuff
Copy link

Detect whether the VPN is currently connected:

#!/usr/bin/env bash
#
# check-vpn-connected
#
# Determines if the Global Protect VPN is connected. The detection method uses
# a comparison of the client's configured IP addresses and the active network
# interface addresses.
#
# - If VPN is connected, the script exits with code 0.
#
# - If VPN is NOT connected, the script exits with code 1.
#
# Arguments:
#
#   -v | --verbose  Prints out a message to STDERR if not connected.
#   -d | --debug    Prints debugging info. Implies --verbose.
#
# shellcheck disable=SC2155
#   (see https://github.com/koalaman/shellcheck/wiki)
#

main() {
  local verbose=0;
  local debug=0;
  local ipv4AddressRegex="(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --verbose|-v)
        # Verbose output.
        verbose=1;
        ;;

      --debug|-d)
        # Debug output; implies verbose.
        debug=1;
        verbose=1;
    esac;
    shift;
  done;

  # Get the active interface addresses.
  # shellcheck disable=SC2207
  # IPv6 support would require filtering on 'inet6' and an IPv6 regex.
  local interfaceIPs=($(ifconfig -a -u inet | grep -F "inet" | grep -oE "${ipv4AddressRegex}"));
  if [[ "${debug}" -ne 0 ]]; then
    >&2 echo "Interface Addresses: ${interfaceIPs[*]}";
  fi;

  # Read Global Protect client configuration, return the listed IPv4 addresses.
  # IPv6 support would require filtering on 'PreferredIPv6_' and an IPv6 regex.
  IFS=$'\n' read -d '' -r -a vpnIPs < <( \
    defaults read /Library/Preferences/com.paloaltonetworks.GlobalProtect.settings.plist | \
    grep -F "PreferredIP_" | \
    grep -oE "${ipv4AddressRegex}" \
  );
  if [[ "${debug}" -ne 0 ]]; then
    >&2 echo "VPN IPs: ${vpnIPs[*]}";
  fi;

  # If one of the interface IPs matches one of the VPN IPs then the VPN is connected.
  # printf converts the bash array into a pipe-delimited list and XXXX is a never-match last element.
  if grep -qE "($(printf '%s|' "${interfaceIPs[@]}")XXXX)" <<< "${vpnIPs[@]}"; then
    exit 0;
  else
    if [[ "${verbose}" -ne 0 ]]; then
      >&2 echo "$(tput setaf 208)Active VPN connection required!$(tput op)";
    fi;

    exit 1;
  fi;
}

main "$@";

@Alechan
Copy link

Alechan commented Dec 29, 2022

Update on my version of toggleGlobalProtectConnection that broke with the update to GlobalProtect of the last few days

function toggleGlobalProtectConnection {
  osascript <<EOF
  tell application "System Events" to tell process "GlobalProtect"
    click menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubar
    set frontmost to true -- keep window 1 active
    tell window 1
      -- Click on the connect or disconnect button, depending on if they exist or not
      if exists (first UI element whose title is "Connect") then
        tell (first UI element whose title is "Connect") to if exists then click
      else
        tell (first UI element whose title is "Disconnect") to if exists then click
      end if
    end tell
    click menu bar item 1 of menu bar 2 -- This will close the GlobalProtect "window" after clicking Connect/Disconnect. This is optional.
  end tell
EOF
}

(it has duplicate code but it works 🤣)

It's inspired by the previous comments. Thanks to everyone!

@Aadil-Mir-Rubrik
Copy link

Aadil-Mir-Rubrik commented Jan 8, 2023

Here is what I modified it to , check for connection state after every 30 minutes(you can modify this ) and then connect again

`➜  ~ cat gp.sh
#!/usr/bin/env bash


osascript <<EOF
tell application "System Events" to tell process "GlobalProtect"
	click menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubar
	set frontmost to false -- keep window 1 active
	tell window 1
	  -- Find the status
	  tell (first UI element whose title is "Connect") to if exists then set message to "VPN is connecting now..."
	  --tell (first UI element whose title is "Disconnect") to if exists then set message to "VPN is connected."
	  -- Click connect button
	  tell (first UI element whose title is "Connect") to if exists then click
	end tell
	click menu bar item 1 of menu bar 2 -- This will close the GlobalProtect "window" after clicking Connect/Disconnect. This is optional.
end tell
EOF
➜  ~ cat com.example.globalprotect.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.example.globalprotect</string>
    <key>Program</key>
    <string>/Users/Aadil.Mir/gp.sh</string>
    <key>StartInterval</key>
    <integer>1800</integer>
  </dict>
</plist>



cp com.example.globalprotect.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/com.example.globalprotect.plist


launchctl unload ~/Library/LaunchAgents/com.example.globalprotect.plist
`

@EvilJordan
Copy link

Hi, Friends.

I found that none of the above worked for me on MacOS Ventura 13.2.1 running GlobalProtect 6.0.5, so I created a simple script that does.

Perhaps I am different in that I have also disabled the underlying system LaunchDaemon service (pangpsd) when this thing is not running because I like to know what's happening on my machine at all times, to the best extent possible. I have no Login Items enabled and modified the plists directly with a text editor to keep them from launching on startup.

This quick script is part of my ~/.bash_profile and invoked by calling vpn on the command line and will start the requisite services, and then launch GlobalProtect. If you have a different install location, you may need to change the open -a /Applications/GlobalProtect.app line to the appropriate directory.

To quit, vpn unload will stop and disable all services and kill the app as well. Errors are suppressed, with the routing > /dev/null 2>&1 because I don't care if the shutdown process isn't clean. Your milage may vary.

vpn() {
	if [ "$1" = "unload" ]; then
		launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist > /dev/null 2>&1
		launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist > /dev/null 2>&1
		launchctl bootout gui/$(id -u) /Library/LaunchDaemons/com.paloaltonetworks.gp.pangpsd.plist > /dev/null 2>&1
		PID="$(launchctl list | grep palo | cut -f 1)"
		kill $PID
		echo "VPN unloaded"
	else
		launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
		launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist 
		launchctl bootstrap gui/$(id -u) /Library/LaunchDaemons/com.paloaltonetworks.gp.pangpsd.plist
		open -a /Applications/GlobalProtect.app
	fi
}

@reynardmarx
Copy link

Is there a way to fill in your 2FA code when prompted for this when connecting to a specific VPN portal?

@kaleksandrov
Copy link
Author

Is there a way to fill in your 2FA code when prompted for this when connecting to a specific VPN portal?

This script doesn't supports this. All it does is to register/unregister the global protect application as an autostart service. It doesn't use any global protect API.

@reynardmarx
Copy link

@kaleksandrov thank you, I understand that. However, do you think it would be possible, seeing that some of the scripts above are using the click functionality?

@erseco
Copy link

erseco commented Mar 11, 2024

This is a easier version that works for me in macOS Sonoma

vpn() {
    if [ "$1" = "stop" ]; then
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist > /dev/null 2>&1
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist > /dev/null 2>&1
        echo "VPN unloaded"
    elif [ "$1" = "start" ]; then
        #statements
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
        echo "VPN loaded"
    fi
}

@damosse31
Copy link

damosse31 commented Apr 1, 2024

I adapted the script to kill globalprotect icon in tray on stop and open globalprotect app when start :

# Add the function below to your .zsh_env or .bash_profile
# Usage : globalprotect start or globalprotect stop

globalprotect() {
    if [ "$1" = "stop" ]; then
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist > /dev/null 2>&1
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist > /dev/null 2>&1
        PID="$(launchctl list | grep palo | cut -f 1)"

        # Kill the processes IDs only if found
        if [ ! -z "$PID" ]; then
                kill -9 $PID
        fi

        echo "VPN unloaded"
    elif [ "$1" = "start" ]; then
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
        open -a /Applications/GlobalProtect.app
        echo "VPN loaded"
    fi
}

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