Automate 2FA for Pritunl VPN

Contents
I use Pritunl to connect to the office VPN. It needs entering a two-factor authentication token generated by okta
app on my phone. All below run on macOS
however, can be adopted on linux
as well.
By using Pritunl CLI you can avoid entering OTP everytime connecting VPN.
Prepare environment
Install the packages
brew install rsc_2fa
brew install --cask pritunl
Get pritunl
profile_url and Two-Step Authentication Key on user profile webpage
profile_key='AB4QDR123WDW4S3F'
profile_url='pritunl://company.com/ku/aaabbbccdd'
Create 2fa
named vpn
# enter profile_key
2fa -add vpn
2fa vpn
Import compony profiles to pritunl-client
/Applications/Pritunl.app/Contents/Resources/pritunl-client add "$profile_url"
/Applications/Pritunl.app/Contents/Resources/pritunl-client list
Connect to vpn
Connect to vpn_name
/Applications/Pritunl.app/Contents/Resources/pritunl-client start $(/Applications/Pritunl.app/Contents/Resources/pritunl-client list --json | jq -r '.[] | select(.name | test("\\(vpn_name\\)")) | .id') --password $(2fa vpn)
Disconnect
/Applications/Pritunl.app/Contents/Resources/pritunl-client stop $(/Applications/Pritunl.app/Contents/Resources/pritunl-client list --json | jq -r '.[] | select(.name | test("\\(vpn_name\\)")) | .id')
All-in-one script
Briefly it does:
- install brew packages
- create 2FA config
- create pritunl-client
- starts/stops VPN
Create /tmp/vpn.sh to test it.
cat <<"EOF" > /tmp/vpn.sh
#!/bin/bash
# Check if we have enough arguments
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <action> [...]"
echo "Example: $0 'init' 'pritunl://url_here'"
echo "Example: $0 'start' [<profile>]"
echo "Example: $0 'stop' [<profile>]"
exit 1
fi
# Hardcoded
profile_pritunl='Tunnel_Name'
profile_2fa='vpn_okta'
# Parameters
action=$1
param=$2
check() {
echo "Check dependencies"
echo -n " Install rsc_2fa "
if ! command -v 2fa &>/dev/null; then
brew install rsc_2fa
else
echo -e "\t\tlatest"
fi
echo -n " Install pritunl "
if ! command -v /Applications/Pritunl.app/Contents/Resources/pritunl-client &>/dev/null; then
brew install --cask pritunl
else
echo -e "\t\t$(/Applications/Pritunl.app/Contents/Resources/pritunl-client version)"
fi
}
init() {
if [ -z "$param" ]; then
echo "Pritunl URL not set"
exit 1
fi
# Add the 2fa key for VPN
echo -e "\nAdding VPN 2FA key for $profile_2fa. Login <company>.okta.com then search for Pritunl, copy Two-Step Authentication Key:"
2fa -add "$profile_2fa"
# Test if the 2fa key works
echo -n "Testing VPN 2FA for $profile_2fa..."
echo -e "\t\t$(2fa "$profile_2fa")"
# Add Pritunl profile
echo "Adding profile to Pritunl: $param"
if ! /Applications/Pritunl.app/Contents/Resources/pritunl-client add "$param" &>/dev/null; then
echo "Failed to add Pritunl profile. Refresh the page for new URL profile"
profile_id=$(/Applications/Pritunl.app/Contents/Resources/pritunl-client list --json | jq -r --arg profile "$profile_pritunl" '.[] | select(.name | test("\\(" + $profile + "\\)")) | .id')
echo $profile_id
fi
}
profile() {
profile_id=$(/Applications/Pritunl.app/Contents/Resources/pritunl-client list --json | jq -r --arg profile "$profile_pritunl" '.[] | select(.name | test("\\(" + $profile + "\\)")) | .id')
# Check if the profile ID exists
if [ -z "$profile_id" ]; then
echo "Profile for $vpn_name not found."
exit 1
fi
}
start() {
profile
echo -ne "Starting profile: \t\t\t$profile_id\n"
/Applications/Pritunl.app/Contents/Resources/pritunl-client start "$profile_id" --password $(2fa "$profile_2fa")
sleep 5
/Applications/Pritunl.app/Contents/Resources/pritunl-client list
}
stop() {
profile
echo -en "Stopping profile \t\t$profile_id\n"
/Applications/Pritunl.app/Contents/Resources/pritunl-client stop "$profile_id"
sleep 5
/Applications/Pritunl.app/Contents/Resources/pritunl-client list
}
# Action based on the parameter (start or stop)
if [ "$action" == "start" ]; then
check
start
elif [ "$action" == "stop" ]; then
check
stop
elif [ "$action" == "init" ]; then
check
init
else
echo "Invalid action: $action. Use 'init' or 'start' or 'stop'."
exit 1
fi
EOF
Make the script available system-wide
chmod +x /tmp/vpn.sh
mv /tmp/vpn.sh /usr/local/bin/vpn