#!/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