Skip to content

Instantly share code, notes, and snippets.

@the-eater
Created June 30, 2016 15:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save the-eater/8248c8056a21892d29f0c9fcfe6e6480 to your computer and use it in GitHub Desktop.
Save the-eater/8248c8056a21892d29f0c9fcfe6e6480 to your computer and use it in GitHub Desktop.
vpnm - Bash Openvpn manager
#!/usr/bin/env bash
set -e;
VPNM_CONF="${VPNM_CONF:-$HOME/.vpnm}";
VPNM_SUDO="${VPNM_SUDO:-sudo}";
VPNM_GPG="${VPNM_GPG:-gpp2}";
VPNM_CREDS="${VPNM_CREDS:-keyring}";
main() {
local action="$1";
shift;
case "$action" in
enable)
enable_vpn "$1";
return;
;;
disable)
disable_vpn "$1";
return;
;;
start)
start_vpn "$1";
return;
;;
stop)
stop_vpn "$1";
return;
;;
status)
status_vpn "$1";
return;
;;
add)
add_vpn $@;
return;
;;
edit)
edit_vpn $@;
return;
;;
list)
list_vpn;
return;
;;
list-enabled)
list_enabled_vpn;
return;
;;
set-private-pass)
set_private_pass "$1";
return;
;;
set-auth)
set_auth "$1";
return;
;;
boot)
boot;
return;
;;
help)
print_man;
return;
;;
*)
echo "Action ${action} doesn't exist"
echo;
print_man;
exit 1;
;;
esac
}
print_man () {
cat <<MAN
vpnm - A Bash vpn manager
Commands:
- enable {vpn name} enables and starts the vpn
- disable {vpn name} disable and doesnt stop the vpn
- start {vpn name} starts vpn without enabling it
- stop {vpn name} stop vpn without disabling it
- add {vpn name} {openvpn config} [additionial files] add a vpn to the manager
- edit {vpn name} [file] edit the openvpn config or given file of vpn
- list list all vpns in config manager
- list-enabled list all enabled vpns
- set-private-pass {vpn name} save the private key pass in a gpg encrypted file or your keyring
- set-auth {vpn name} save the auth user combo in a gpg encrypted file or your keyring
MAN
}
add_vpn () {
local name="$1"; shift;
local config="$1"; shift;
ensure_not_empty "name" "${name}";
ensure_not_empty "config" "${config}";
if check_vpn_exists "${name}"; then
echo "Vpn with the name '${name}' already exists";
exit 1;
fi
local vpndir="$(get_vpn_dir "${name}")";
mkdir -p "${vpndir}/config";
cp "${config}" "${vpndir}/config/server.conf";
cp -a $@ "${vpndir}/config/";
echo "Succesfully created vpn ${name}";
}
enable_vpn () {
local name="$1";
ensure_not_empty "name" "${name}";
ensure_vpn_exists "${name}";
if grep -q "^${name}$" "${VPNM_CONF}/enabled"; then
echo "${name} is already enabled";
exit 1;
fi
echo "${name}" >> "${VPNM_CONF}/enabled";
start_vpn "${name}";
}
disable_vpn () {
local name="$1";
ensure_not_empty "name" "${name}";
grep -v "^${name}$" "${VPNM_CONF}/enabled" > "${VPNM_CONF}/enabled.new" || true;
rm "${VPNM_CONF}/enabled";
mv "${VPNM_CONF}/enabled.new" "${VPNM_CONF}/enabled";
}
boot () {
echo "Booting vpns";
while read -r vpn;
do
start_vpn "${vpn}";
done < "${VPNM_CONF}/enabled";
}
list_enabled_vpn () {
cat "${VPNM_CONF}/enabled";
}
edit_vpn () {
local name="$1";
local config="$2";
ensure_not_empty "name" "${name}";
ensure_vpn_exists "${name}";
"$EDITOR" "$(get_vpn_dir "${name}")/config/${config:-server.conf}";
}
list_vpn () {
ls -1 "${VPNM_CONF}/vpn";
}
status_vpn () {
local name="$1";
ensure_not_empty "name" "${name}";
ensure_vpn_exists "${name}";
local vpndir="$(get_vpn_dir "${name}")";
if [ -f "${vpndir}/pid" ] && $VPNM_SUDO kill -0 "$(cat "${vpndir}/pid")" 2>/dev/null; then
echo "Vpn ${name} is running...";
exit 0;
fi;
echo "Vpn ${name} is not running...";
exit 1;
}
start_vpn () {
local name="$1";
ensure_not_empty "name" "${name}";
ensure_vpn_exists "${name}";
local vpndir="$(get_vpn_dir "${name}")";
if [ -f "${vpndir}/pid" ] && $VPNM_SUDO kill -0 "$(cat "${vpndir}/pid")" 2>/dev/null; then
echo "Vpn ${name} is already running..."
exit 0;
fi;
local args="";
if [ -f "${vpndir}/auth" ]; then
local user="$(cat "${vpndir}/auth")";
local pass="$(lookup_pass "${name}" "auth")";
[ -f "${vpndir}/.pw" ] && rm "${vpndir}/.pw";
echo "$user" > "${vpndir}/.pw";
echo "$pass" >> "${vpndir}/.pw";
args="$args --auth-user-pass ${vpndir}/.pw";
fi
if [ -f "${vpndir}/privkeypass" ]; then
args="$args --askpass ${vpndir}/.pk";
lookup_pass "${name}" "private" > "${vpndir}/.pk";
fi;
cd "${vpndir}/config";
local ret=0;
$VPNM_SUDO openvpn --writepid "${vpndir}/pid" --daemon --log-append "${vpndir}/log" --config "${vpndir}/config/server.conf" $args || ret=$?;
sleep .5;
[ -f "${vpndir}/.pk" ] && rm "${vpndir}/.pk";
[ -f "${vpndir}/.pw" ] && rm "${vpndir}/.pw";
if [ $ret != 0 ]; then
echo "Failed to start openvpn";
exit $ret;
fi;
$VPNM_SUDO chmod a+r "${vpndir}/log";
echo "Started vpn ${name}";
}
stop_vpn () {
local name="$1";
ensure_not_empty "name" "${name}";
ensure_vpn_exists "${name}";
local vpndir="$(get_vpn_dir "${name}")";
local pid="$(cat "${vpndir}/pid")";
if [ ! -f "${vpndir}/pid" ] || ! $VPNM_SUDO kill -0 "${pid}" 2>/dev/null; then
echo "Vpn ${name} is not running..."
exit 0;
fi;
$VPNM_SUDO kill "${pid}";
$VPNM_SUDO rm "${vpndir}/pid";
while $VPNM_SUDO kill -0 "${pid}" 2>/dev/null; do
sleep 0.2;
done;
echo "Stopped vpn ${name}";
}
set_private_pass () {
local name="$1";
ensure_not_empty "name" "${name}";
ensure_vpn_exists "${name}";
read -rsp "Please enter the private key password: " pass;
echo;
store_pass "$name" "private" "$pass";
touch "$(get_vpn_dir "$name")/privkeypass";
}
set_auth () {
local name="$1";
ensure_not_empty "name" "${name}";
ensure_vpn_exists "${name}";
read -rp "Please enter the user for ${name}: " user;
read -rsp "Please enter the password for ${name}: " pass;
echo;
store_pass "$name" "auth" "$pass";
echo "${user}" > "$(get_vpn_dir "$name")/auth";
}
get_vpn_dir () {
local name="$1";
echo "${VPNM_CONF}/vpn/${name}";
}
check_vpn_exists () {
local name="$1";
test -d "$(get_vpn_dir "${name}")";
return $?
}
ensure_not_empty () {
local name="$1";
local value="$2";
if [ -z "${value}" ]; then
echo "${name} is empty";
exit 1;
fi
}
ensure_vpn_exists () {
local name="$1";
if ! check_vpn_exists "${name}"; then
echo "Vpn ${name} doesn't exist";
exit 1;
fi
}
lookup_pass () {
local name="$1";
local what="$2";
case "${VPNM_CREDS}" in
keyring)
secret-tool lookup "vpnm/vpn/${name}" "${what}";
;;
gpg)
$VPNM_GPG --decrypt "$(get_vpn_dir "${name}")/pass/${what}.gpg";
;;
pass)
pass show "vpnm/vpn/${name}/${what}";
;;
*)
echo "Secret storage engine ${VPNM_CREDS}, not available";
exit 1;
esac
}
store_pass () {
local name="$1";
local what="$2";
local pass="$3";
case "${VPNM_CREDS}" in
keyring)
echo "${pass}" | secret-tool store --label "${what} password for ${name} vpn" "vpnm/vpn/${name}" "${what}";
;;
gpg)
if [ -z "${VPNM_GPGKEY}" ]; then
echo "No GPG key given to encrypt passwords with";
fi
local vpnpassdir="$(get_vpn_dir "${name}")/pass";
[ ! -d "${vpnpassdir}" ] && mkdir "${vpnpassdir}"
echo "${pass}" | $VPNM_GPG --encrypt --armor -r "$VPNM_GPGKEY" | "${vpnpassdir}/${what}.gpg";
;;
pass)
echo "${pass}" | pass insert -e "vpnm/vpn/${name}/${what}";
;;
*)
echo "Secret storage engine ${VPNM_CREDS}, not available";
exit 1;
esac
}
main $@;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment