diff --git a/src/ubuntu/install/vpn/install_vpn.sh b/src/ubuntu/install/vpn/install_vpn.sh index d954354..7b36ce1 100644 --- a/src/ubuntu/install/vpn/install_vpn.sh +++ b/src/ubuntu/install/vpn/install_vpn.sh @@ -9,37 +9,43 @@ if [[ "${DISTRO}" == @(ubuntu|kali|debian|parrotos5) ]]; then openvpn \ resolvconf \ wireguard-tools \ - zenity + zenity \ + jq elif [ "${DISTRO}" == "alpine" ]; then apk add --no-cache \ openresolv \ openvpn \ tailscale \ wireguard-tools \ - zenity + zenity \ + jq elif [[ "${DISTRO}" == @(oracle8|oracle9|rockylinux8|rockylinux9|almalinux8|almalinux9) ]] ; then dnf install -y epel-release dnf install -y \ openvpn \ - wireguard-tools + wireguard-tools \ + jq elif [[ "${DISTRO}" == @(centos|oracle7) ]]; then yum install -y epel-release yum install -y \ openvpn \ wireguard-tools \ - zenity + zenity \ + jq elif [[ "${DISTRO}" == @(fedora37|fedora38) ]] ; then dnf install -y \ openresolv \ openvpn \ wireguard-tools \ - zenity + zenity \ + jq elif [ "${DISTRO}" == "opensuse" ]; then zypper install -y \ openresolv \ openvpn \ wireguard-tools \ - zenity + zenity \ + jq fi # Install tailscale @@ -90,5 +96,5 @@ fi sed -i '/cmd sysctl -q/d' $(which wg-quick) # Copy startup script -cp ${INST_DIR}/ubuntu/install/vpn/start_vpn.sh / -chmod +x /start_vpn.sh +cp ${INST_DIR}/ubuntu/install/vpn/start_vpn.sh /dockerstartup/start_vpn.sh +chmod +x /dockerstartup/start_vpn.sh diff --git a/src/ubuntu/install/vpn/start_vpn.sh b/src/ubuntu/install/vpn/start_vpn.sh index 2b6eeae..d2504a2 100644 --- a/src/ubuntu/install/vpn/start_vpn.sh +++ b/src/ubuntu/install/vpn/start_vpn.sh @@ -1,11 +1,30 @@ #!/usr/bin/env bash +set -x -set -ex +ICON_SUCCESS="/usr/share/icons/ubuntu-mono-dark/status/22/nm-signal-100-secure.svg" +ICON_ERROR="/usr/share/icons/ubuntu-mono-dark/status/22/network-error.svg" +ICON_OFFLINE="/usr/share/icons/ubuntu-mono-dark/status/22/network-offline.svg" +OPENVPN_STATUS_LOG="/tmp/openvpn-status.log" +DEFAULT_OPENVPN_CONFIG="/dockerstartup/openvpn.conf" +DEFAULT_OPENVPN_CREDS="/dockerstartup/openvpn-auth" +DEFAULT_WIREGUARD_CONFIG="/dockerstartup/wireguard.conf" + +SHOW_VPN_STATUS_DEFAULT="1" +SHOW_VPN_STAT=${SHOW_VPN_STATUS:-$SHOW_VPN_STATUS_DEFAULT} + +SHOW_IP_STATUS_DEFAULT="1" +SHOW_IP_STAT=${SHOW_IP_STATUS:-$SHOW_IP_STATUS_DEFAULT} # Logging and trap -LOGFILE="/vpn_start.log" +LOGFILE="/dockerstartup/vpn_start.log" function notify_err() { - zenity --error --text="An error has occurred configuring the VPN please review the log at ${LOGFILE}" + local exit_code=$? + local failed_command="$BASH_COMMAND" + msg="An error occurred with exit code $exit_code while executing: $failed_command.\n\nPlease review the log at ${LOGFILE}" + echo msg + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "${msg}" + exit $exit_code + } function cleanup_log() { rm -f ${LOGFILE} @@ -27,64 +46,178 @@ function get_set_creds() { VPN_CONFIG=/home/kasm-user/vpn.ovpn } -# Start VPN based on content -if [ ! -z ${VPN_CONFIG+x} ]; then - if [ "${VPN_CONFIG: -4}" == "conf" ]; then - echo "wireguard config detected checking for support" - if ip link add dev test type wireguard; then - echo "wireguard kernel module is present on this host continuing" - ip link del dev test - else - zenity --error --text="wireguard kernel module is not present on this host and a wireguard config was passed will not continue" - echo "wireguard kernel module is not present on this host and a wireguard config was passed will not continue" - exit 1 - fi - wg-quick up ${VPN_CONFIG} +function tailscale_status() { + if [ "$SHOW_VPN_STAT" == "1" ]; then + tailscale_status=$(tailscale status) + notify-send -u critical -t 0 -i "${ICON_SUCCESS}" "Tailscale Status" "${tailscale_status}" fi - if [ "${VPN_CONFIG: -4}" == "ovpn" ]; then +} + +function ip_status(){ + if [ "$SHOW_IP_STAT" == "1" ]; then + ip_status=$(curl https://ipinfo.io/json) + notify-send -u critical -t 0 -i "${ICON_SUCCESS}" "Public IP Status" "${ip_status}" + fi +} + +function process_tailscale(){ + + local tailscale_key=$1 + + if [ ! -c /dev/net/tun ]; then + mkdir -p /dev/net + mknod /dev/net/tun c 10 200 + fi + tailscaled & + sleep 2 + set +e + tailscale up --authkey=${tailscale_key} + if [ $? -ne 0 ]; then + msg="Failed to establish tailscale connection. Please review the log at ${LOGFILE}" + echo msg + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "${msg}" + exit 1 + fi + set -e + + notify-send -u critical -t 0 -i "${ICON_SUCCESS}" "VPN Connected!" "Tailscale VPN Connected Successfully" + tailscale_status + ip_status + cleanup_log + exit 0 +} + + +function openvpn_status() { + if [ "$SHOW_VPN_STAT" == "1" ]; then + openvpn_status=$(cat ${OPENVPN_STATUS_LOG}) + notify-send -u critical -t 0 -i "${ICON_SUCCESS}" "OpenVPN Status" "${openvpn_status}" + fi +} + + +function process_openvpn() { + local openvpn_config=$1 + + # Create tun device + if [ ! -c /dev/net/tun ]; then + mkdir -p /dev/net + mknod /dev/net/tun c 10 200 + fi + if which resolvconf; then + openvpn --pull-filter ignore route-ipv6 --pull-filter ignore ifconfig-ipv6 --config "${openvpn_config}" --status ${OPENVPN_STATUS_LOG} & + sleep 10 + if ! pgrep openvpn; then + msg="An error has occurred starting the VPN please review the log at ${LOGFILE}" + echo msg + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "${msg}" + exit 1 + else + notify-send -u critical -t 0 -i "${ICON_SUCCESS}" "VPN Connected!" "OpenVPN Connected Successfully" + openvpn_status + ip_status + cleanup_log + exit 0 + fi + else + msg="Resolvconf is not found on this system this container is not compatible with OpenVPN" + echo msg + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "${msg}" + exit 1 + fi +} + +function wireguard_status() { + if [ "$SHOW_VPN_STAT" == "1" ]; then + wg_show=$(wg show) + notify-send -u critical -t 0 -i "${ICON_SUCCESS}" "WireGuard Status" "${wg_show}" + fi +} + + +function process_wireguard() { + + local wireguard_conf=$1 + echo "WireGuard config detected checking for support" + if ip link add dev test type wireguard; then + echo "WireGuard kernel module is present on this host continuing" + ip link del dev test + else + msg="WireGuard kernel module is not present on this host and a WireGuard config was passed will not continue" + echo msg + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "${msg}" + exit 1 + fi + + wg-quick up ${wireguard_conf} + if [ $? -ne 0 ]; then + msg="Failed to establish WireGuard connection. Please review the log at ${LOGFILE}" + echo msg + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "${msg}" + exit 1 + fi + notify-send -u critical -t 0 -i "${ICON_SUCCESS}" "VPN Connected!" "WireGuard VPN Connected Successfully" + wireguard_status + ip_status + cleanup_log + exit 0 + +} + +notify-send -u critical -t 0 -i "${ICON_OFFLINE}" "Connecting to VPN" "Please wait while the VPN connection is being established..." + +VPN_LAUNCH_CONFIG='/dockerstartup/launch_selections.json' +# Launch Config Based Workflow +if [ -e ${VPN_LAUNCH_CONFIG} ]; then + + VPN_SERVICE="$(jq -r '.vpn_service' ${VPN_LAUNCH_CONFIG})" + + if [ "${VPN_SERVICE}" == "tailscale" ]; then + ts_key="$(jq -r '.tailscale_key' ${VPN_LAUNCH_CONFIG})" + process_tailscale $ts_key + + elif [ "${VPN_SERVICE}" == "openvpn" ]; then + OPENVPN_USERNAME="$(jq -r '.openvpn_username' ${VPN_LAUNCH_CONFIG})" + OPENVPN_PASSWORD="$(jq -r '.openvpn_password' ${VPN_LAUNCH_CONFIG})" + echo ${OPENVPN_USERNAME} > ${DEFAULT_OPENVPN_CREDS} + echo ${OPENVPN_PASSWORD} >> ${DEFAULT_OPENVPN_CREDS} + jq -r '.openvpn_config' ${VPN_LAUNCH_CONFIG} > ${DEFAULT_OPENVPN_CONFIG} + sed -i "s#auth-user-pass#auth-user-pass ${DEFAULT_OPENVPN_CREDS}#g" ${DEFAULT_OPENVPN_CONFIG} + process_openvpn $DEFAULT_OPENVPN_CONFIG + + elif [ "${VPN_SERVICE}" == "wireguard" ]; then + jq -r '.wireguard_config' ${VPN_LAUNCH_CONFIG} > /dockerstartup/wireguard.conf + process_wireguard "/dockerstartup/wireguard.conf" + else + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "Unknown or missing vpn_service" + exit 1 + fi + +else + +# File-Mapping/Env Based Workflow + + ### Tailscale ### + if [ "${TAILSCALE_KEY:0:5}" == "tskey" ]; then + process_tailscale $TAILSCALE_KEY + + ### WireGuard ### + elif [ -e ${DEFAULT_WIREGUARD_CONFIG} ]; then + process_wireguard $DEFAULT_WIREGUARD_CONFIG + + ### OpenVPN ### + elif [ -e ${DEFAULT_OPENVPN_CONFIG} ]; then + VPN_CONFIG=$DEFAULT_OPENVPN_CONFIG # Check if we need user credentials if grep -x auth-user-pass ${VPN_CONFIG}; then get_set_creds fi - # Create tun device - if [ ! -c /dev/net/tun ]; then - mkdir -p /dev/net - mknod /dev/net/tun c 10 200 - fi - if which resolvconf; then - openvpn --pull-filter ignore route-ipv6 --pull-filter ignore ifconfig-ipv6 --config "${VPN_CONFIG}" & - sleep 10 - if ! pgrep openvpn; then - zenity --error --text="An error has occurred starting the VPN please review the log at ${LOGFILE}" - echo "An error has occurred starting the VPN please review the log at ${LOGFILE}" - exit 1 - fi - else - zenity --error --text="Resolvconf is not found on this system this container is not compatible with wireguard" - echo "Resolvconf is not found on this system this container is not compatible with wireguard" - exit 1 - fi - fi - if [ "${VPN_CONFIG:0:5}" == "tskey" ]; then - # Create tun device - if [ ! -c /dev/net/tun ]; then - mkdir -p /dev/net - mknod /dev/net/tun c 10 200 - fi - tailscaled & - sleep 2 - tailscale up --authkey=${VPN_CONFIG} - fi -else - zenity --error --text="VPN_CONFIG is not defined there is no tunnel to start" - echo "VPN_CONFIG is not defined there is no tunnel to start" - exit 1 -fi + process_openvpn $VPN_CONFIG -# Log success -zenity \ - --info \ - --title "VPN configured" \ - --text "VPN connected!" -echo "VPN started using the config file ${VPN_CONFIG}" -cleanup_log + else + msg="VPN Config File or TAILSCALE_KEY is not defined" + echo msg + notify-send -u critical -t 0 -i "${ICON_ERROR}" "VPN Configuration Failed" "${msg}" + exit 1 + fi +fi