A basic openvpn bash wrapper with completion

Monday, April 12, 2021

I’m working with multiple openvpn environments in Linux and while I enjoy working with the command line, it can be cumbersome to manage different connections through the openvpn cli.

My ideal VPN cli would be super simple : connect, disconnect and bash completion for everything.

As cumbersome + linux often leads to automation, my solution involves a little bit of bash :-)

Install

The following code needs to be sourced. Personally, I’ve added it to my .bashrc.

### VPN helper
# vpn autocompletion
_vpn_complete()
{
  local cur prev
  COMPREPLY=()
  cur=${COMP_WORDS[COMP_CWORD]}
  prev=${COMP_WORDS[COMP_CWORD-1]}
  if [ $COMP_CWORD -eq 1 ]; then
    COMPREPLY=( $(compgen -W "connect disconnect killall" -- $cur) )
  elif [ $COMP_CWORD -eq 2 ]; then
    case "$prev" in
      "connect")
	COMPREPLY=( $(compgen -W "$(find ~/.vpn/ -name *.ovpn  -printf "%f\n")" -- $cur) )
	;;
      "disconnect")
	COMPREPLY=( $(compgen -W "$(ls /tmp/openvpn_pids 2> /dev/null)" -- $cur) )
	;;
      *)
	;;
    esac
  fi
  return 0
}

complete -F _vpn_complete vpn

# vpn helper script
vpn() {
    ovpn_pid_dir=/tmp/openvpn_pids
    ovpn_filename=$2
    ovpn_pid_file=$ovpn_pid_dir/$2
    mkdir -p $ovpn_pid_dir
    if [ "$1" == "connect" ] && [ -f ~/.vpn/$ovpn_filename ]; then
	    sudo openvpn --config ~/.vpn/$ovpn_filename --daemon --writepid $ovpn_pid_file
    elif [ "$1" == "disconnect" ] && [ -f $ovpn_pid_file ]; then
	    sudo kill $(cat $ovpn_pid_file) && sudo rm $ovpn_pid_file
    elif [ "$1" == "killall" ]; then
	    sudo killall openvpn 2> /dev/null && sudo rm $ovpn_pid_dir/*
    else
	    echo "Usage : $ vpn [connect|disconnect] ovpn_file"
	    return 1
    fi
}

Usage

To use this, we need to first create a .vpn directory in our HOME.

Then, we put our .ovpn files in $HOME/.vpn/.

Finally, we enjoy the bash completion after typing vpn [...]!

Example commands:

vpn connect config.ovpn
vpn disconnect config.ovpn # or vpn killall
bash  openvpn  cli