Recently hopped on the VPN train and needed a better way to manage my settings via the command-line. Cobbled together a bash script to make controlling OpenVPN a little more convenient. The script gets a list of all your configs, then lets you enable or disable individual or multiple instances of OpenVPN using the selected config file(s).
I've only used it on Ubuntu 16.04, so it relies on systemd for starting and stopping the OpenVPN service. Take a look through the file to see how it works and what settings you need to tweak. I tried to comment everything to make modifying easier.
View File:
#!/bin/bash
## OpenVPN Config Manager
## Script to help manage multiple configuration files for OpenVPN
##
## Last Updated: April 23 2018
## – Found a different way to get external ip
##
## January 12 2018
## Notes/Issues/Things to fix:
## – Only tested on Ubuntu 16.04
## – Uses systemd to control services
## – Also uses proxychains-ng to check proxy/vpn ip
## but can be edited to use curl, wget, etc.
## – Multiple VPN shows “ready” message even though
## second, third, etc interfaces are still starting up
## – Use the option to shutdown all VPNs to start from
## a clean slate if it feels like nothing is happening
##
##
################################################
## Settings ##
################################################
# Set directory that stores your config files
CONFIGDIR=/etc/openvpn/
# Change extension to .conf or .ovpn based on your setup
CONFIGS=($CONFIGDIR*.conf)
################################################
## Colors! ##
################################################
c1=’\e[0;32m’ c1b=’\e[1;32m’ #green bold
c2=’\e[0;31m’ c2b=’\e[1;31m’ #red bold
c3=’\e[0;34m’ c3b=’\e[1;34m’ #blue bold
c4=’\e[0;37m’ c4b=’\e[1;37m’ #white bold
endc=’\e[0m’ #end color
################################################
## Activate Single VPN ##
################################################
# Ask user to select a config, list files or exit
function confSelect {
while [[ ! $USRCONF =~ ^[0-9]+$ ]] || [[ “$USRCONF” -ge ${#CONFIGS[@]} ]];
do
printf “${c4}Input Config Number %s\n(L)ist configs (M)ain Menu (Q)uit):${endc} ”
read USRCONF
if [[ “$USRCONF” =~ ^[Ll]+$ ]]
then
confList
elif [[ “$USRCONF” =~ ^[Mm]+$ ]]
then
menuMain
elif [[ “$USRCONF” =~ ^[Qq]+$ ]]
then
exit
elif
! [[ “$USRCONF” =~ ^[0-9]+$ ]] && [[ ! “$USRCONF” =~ ^[Ll]+$ ]]
then
echo -e “${c2b}— Invalid input: numbers only —${endc}”
elif [[ “$USRCONF” -ge ${#CONFIGS[@]} ]];
then
echo -e “${c2b}— Invalid input: config not found —${endc}”
fi
done
echo -e “${c4b}You selected:${endc} ${c1b} ${CONFIGS[$USRCONF]##*/} ${endc}\n”
}
# Launch OpenVPN with the selected config
function confRun {
printf “${c3b}Running${endc} OpenVPN with selected config… %s\t%s\n\n”
# Stop active instances of OpenVPN
printf “${c2b}Stopping${endc} active process… %s\t%s\n\n”
sudo systemctl stop openvpn
sleep 2
printf “${c1}Starting${endc} service using ${c1b}${CONFIGS[$USRCONF]##*/}${endc}…
%s\t%s\n\n”
# Filter out file extension for use in openvpn@ command
CONFSEL=${CONFIGS[$USRCONF]##*/}
# Start OpenVPN service using the selected config file
sudo systemctl start openvpn@${CONFSEL%.*}
}
################################################
## Activate Multiple VPNs ##
################################################
# Ask user to select multiple configs, list files or exit
function confMultiSel {
while [[ ! “$usrinput” == “D” ]]
do
printf “${c4}Input Config Number (press enter after each input) %s\n(L)ist configs (D)one Adding Configs (R)eset selection (M)ain menu (Q)uit):${endc} ”
read usrinput
# Check if user wants to list configs, quit, or reset selection
# Then validate input for numbers or valid configs
if [[ “$usrinput” =~ ^[Ll]+$ ]]
then
confList
elif [[ “$usrinput” =~ ^[Qq]+$ ]]
then
exit
elif [[ “$usrinput” =~ ^[Mm]+$ ]]
then
menuMain
elif [[ “$usrinput” =~ ^[Rr]+$ ]]
then
unset ‘USRCONF[@]’
elif ! [[ “$usrinput” =~ ^[0-9]+$ ]] && [[ ! “$usrinput” =~ ^[Dd]+$ ]]
then
echo -e “${c2b}— Invalid input: numbers only —${endc}”
elif [[ “$usrinput” -ge “${#CONFIGS[@]}” ]]
then
echo -e “${c2b}— Invalid input: config not found —${endc}”
else
USRCONF+=($usrinput)
fi
done
# Remove end command (D) from array, leaving only selected conigs
unset ‘USRCONF[-1]’
# Output list of selected configs
printf “%s\n${c4b}You selected the following configs:${endc} ”
for x in “${USRCONF[@]}”
do
printf “${c1b}${CONFIGS[$x]##*/}${endc} ”
CONFSEL+=”${CONFIGS[$x]##*/} ”
done
printf “\n”
}
# Launch OpenVPN using the selected configs
function confMultiRun {
printf “${c3b}Running${endc} OpenVPN using selected configs… %s\t%s\n\n”
# Stop active instances of OpenVPN
printf “${c2b}Stopping${endc} active processes… %s\t%s\n\n”
sudo systemctl stop openvpn
sleep 2
printf “${c1}Starting${endc} service using ${c1b}${CONFSEL}${endc}…
%s\t%s\n\n”
# Filter out file extension for use in openvpn@ command
#CONFSEL=${CONFIGS[$USRCONF]##*/}
# Start OpenVPN services using the selected config files
# Edit filename to remove path, then remove extension
for z in “${USRCONF[@]}”
do
CONFSEL=”${CONFIGS[$z]##*/}”
SELMOD=${CONFSEL%.*}
sudo systemctl start openvpn@${SELMOD%.*}
done
}
################################################
## Loading Feedback ##
################################################
# Display feedack while waiting for network adapter(s) to activate
function adapterLoading {
spin=’-\|/’
sp=0
while ! (ip link | grep ‘tun\|tap’ > /dev/null)
do
sp=$(( (sp+1) %4 ))
printf “\r[${spin:$sp:1}] Waiting for network adapter(s)…”
sleep .1
done
printf “%s\n\n${c1b}VPN is ready!${endc}%s\n”
}
################################################
## Disable Individual VPN ##
################################################
# Display list of running vpn instances and configs
function vpnList {
# Get list of running openvpn processes and add to array
VPNIDS=( $(ps -fe | grep [o]penvpn | awk ‘{print $2}’) )
# Get info on configs used on running processes
for o in “${!VPNIDS[@]}”
do
VPNCFG+=( $(cat /proc/${VPNIDS[$o]}/cmdline | strings -1 | grep $CONFIGDIR\.*conf) )
done
# Print active vpn list for user to choose from
printf “${c4b}[#] %s\t[PID] %s\t[Config]${endc} %s\n”
for p in “${!VPNIDS[@]}”;
do
printf “%s\t%s\t%s\n” “[$p]” “${VPNIDS[$p]}” “${VPNCFG[$p]}”
done
}
# Get user input for which service to disable
function vpnOffSelect {
while [[ ! “$vpnInput” =~ ^[0-9]+$ ]]
do
printf “${c4}Input VPN Number to disable %s\n(L)ist active vpn (M)ain menu (Q)uit):${endc} ”
read vpnInput
# Check if user wants to list processes, go to main menu or quit
# Then validate input for numbers or valid running configs
if [[ “$vpnInput” =~ ^[Ll]+$ ]]
then
vpnList
elif [[ “$vpnInput” =~ ^[Qq]+$ ]]
then
exit
elif [[ “$vpnInput” =~ ^[Mm]+$ ]]
then
menuMain
elif ! [[ “$vpnInput” =~ ^[0-9]+$ ]] && [[ ! “$vpnInput” =~ ^[Ll]+$ ]]
then
echo -e “${c2b}— Invalid input: numbers only —${endc}”
elif [[ “$vpnInput” -ge “${#VPNIDS[@]}” ]]
then
echo -e “${c2b}— Invalid input: config not found —${endc}”
fi
done
}
# Disable the service selected by the user
function vpnOffRun {
printf “${c2b}Stopping${endc} service running ${c1b}${VPNCFG[$vpnInput]##*/}${endc}…
%s\t%s\n\n”
# Filter out file extension for use in openvpn@ command
STOPSEL=${VPNCFG[$vpnInput]##*/}
# Stop service using the selected config file
sudo systemctl stop openvpn@${STOPSEL%.*}
}
################################################
## Disable All VPN ##
################################################
function vpnAllOff {
# Stop active instances of OpenVPN
printf “${c2b}Stopping${endc} active processes… %s\t%s\n\n”
sudo systemctl stop openvpn
}
################################################
## Show Adapter Status ##
################################################
function adapterStatus {
printf “${c1b}Running OpenVPN processes${endc}%s\n”
vpnList
printf “${c1b}Default IP Address : ${endc}”
##curl v4.ifconfig.co
curl -s checkip.dyndns.org | sed -e ‘s/.*Current IP Address: //’ -e ‘s/<.*$//'
printf "${c1b}VPN/Proxy IP Address: ${endc}"
##proxychains4 -q curl v4.ifconfig.co proxychains4 -q curl -s checkip.dyndns.org | sed -e 's/.*Current IP Address: //' -e 's/<.*$//' } ################################################
## confList ##
################################################
# Output list of configuration files as an array
function confList {
echo "+--------------------------------------+"
echo "| Config List |"
echo "+--------------------------------------+"
printf "${c4b}[${#CONFIGS[@]} Available Configuration Files] ${endc}%s\n"
printf "${c4b}[#]%-2s[Filename]${endc} %s\n"
for i in "${!CONFIGS[@]}";
do
printf "%-4s %s\n" "[$i]" "${CONFIGS[$i]##*/}"
done | column
printf "%s\n" }
################################################
## Menus ##
################################################
# Main Menu
function menuMainDisplay {
# Obligatory ascii art
clear
echo "+-----------------------------+"
echo "| ██╗ ██╗██████╗ ███╗ ██╗ |"
echo "| ██║ ██║██╔══██╗████╗ ██║ |"
echo "| ██║ ██║██████╔╝██╔██╗ ██║ |"
echo "| ╚██╗ ██╔╝██╔═══╝ ██║╚██╗██║ |"
echo "| ╚████╔╝ ██║ ██║ ╚████║ |"
echo "| ╚═══╝ ╚═╝ ╚═╝ ╚═══╝ |"
echo "+-----------------------------+"
echo "| Config Manager |"
echo "+-----------------------------+"
echo "| [1] Activate Single VPN |"
echo "| [2] Activate Multiple VPNs |"
echo "| [3] Disable Individual VPN |"
echo "| [4] Disable All VPN |"
echo "| [5] Show Adapter Status |"
echo "| [Q] Exit |"
echo "+-----------------------------+" }
function menuMainSel {
local menuSel
read -p "Enter menu selection: " menuSel
case $menuSel in
1) menuActivateSingle;;
2) menuActivateMulti;;
3) menuDisableSingle;;
4) menuDisableAll;;
5) adapterStatus;;
Q) exit 0 ;;
q) exit 0 ;; *)
echo -e "${c2b}Input error...${endc}"
esac
}
# Menu Functions
function menuActivateSingle {
confList confSelect confRun adapterLoading
}
function menuActivateMulti {
onfList confMultiSel confMultiRun adapterLoading
}
function menuDisableAll {
vpnAllOff
}
function menuDisableSingle {
vpnOffSelect
vpnOffRun
}
function menuMain {
menuMainDisplay
menuMainSel
}
# Functions to run on start up
menuMainDisplay
menuMainSel