diff --git a/auto_install/install.sh b/auto_install/install.sh index d260254..fe8c0ff 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -25,7 +25,7 @@ piholeSetupVars="/etc/pihole/setupVars.conf" dnsmasqConfig="/etc/dnsmasq.d/02-pivpn.conf" dhcpcdFile="/etc/dhcpcd.conf" -debianOvpnUserGroup="openvpn:openvpn" +ovpnUserGroup="openvpn:openvpn" ######## PKG Vars ######## PKG_MANAGER="apt-get" @@ -33,10 +33,14 @@ PKG_MANAGER="apt-get" UPDATE_PKG_CACHE="${PKG_MANAGER} update -y" PKG_INSTALL="${PKG_MANAGER} --yes --no-install-recommends install" PKG_COUNT="${PKG_MANAGER} -s -o Debug::NoLocking=true upgrade | grep -c ^Inst || true" +CHECK_PKG_INSTALLED='dpkg-query -s' # Dependencies that are required by the script, regardless of the VPN protocol chosen BASE_DEPS=(git tar curl grep dnsutils grepcidr whiptail net-tools bsdmainutils bash-completion) +BASE_DEPS_ALPINE=(git grep bind-tools newt net-tools bash-completion coreutils openssl) +BASE_DEPS_ALPINE+=(util-linux openrc iptables ip6tables coreutils sed perl) + # Dependencies that where actually installed by the script. For example if the script requires # grep and dnsutils but dnsutils is already installed, we save grep here. This way when uninstalling # PiVPN we won't prompt to remove packages that may have been installed by the user for other reasons @@ -95,11 +99,11 @@ export LC_ALL=C main(){ # Pre install checks and configs + distroCheck rootCheck flagsCheck "$@" unattendedCheck checkExistingInstall "$@" - distroCheck checkHostname # Verify there is enough disk space for the install if [[ "${skipSpaceCheck}" == true ]]; then @@ -110,7 +114,13 @@ main(){ updatePackageCache notifyPackageUpdatesAvailable preconfigurePackages - installDependentPackages BASE_DEPS[@] + + if [ "${PLAT}" == 'Alpine' ]; then + installDependentPackages BASE_DEPS_ALPINE[@] + else + installDependentPackages BASE_DEPS[@] + fi + welcomeDialogs if [ "$pivpnforceipv6" == "1" ]; then @@ -124,7 +134,7 @@ main(){ askforcedipv6route fi fi - + chooseInterface if checkStaticIpSupported; then getStaticIPv4Settings @@ -161,13 +171,13 @@ rootCheck(){ ######## FIRST CHECK ######## # Must be root to install echo ":::" - if [[ $EUID -eq 0 ]];then + if [[ $EUID -eq 0 ]]; then echo "::: You are root." else echo "::: sudo will be used for the install." # Check if it is actually installed # If it isn't, exit because the install cannot complete - if [[ $(dpkg-query -s sudo) ]];then + if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then export SUDO="sudo" export SUDOE="sudo -E" else @@ -216,9 +226,9 @@ unattendedCheck(){ checkExistingInstall(){ # see which setup already exists if [ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]; then - setupVars="${setupConfigDir}/wireguard/${setupVarsFile}" + setupVars="${setupConfigDir}/wireguard/${setupVarsFile}" elif [ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]; then - setupVars="${setupConfigDir}/openvpn/${setupVarsFile}" + setupVars="${setupConfigDir}/openvpn/${setupVarsFile}" fi if [ -r "$setupVars" ]; then @@ -283,6 +293,11 @@ distroCheck(){ VER="$VERSION_ID" declare -A VER_MAP=(["9"]="stretch" ["10"]="buster" ["11"]="bullseye" ["16.04"]="xenial" ["18.04"]="bionic" ["20.04"]="focal") OSCN=${VER_MAP["${VER}"]} + + # Alpine support + if [ -z "${OSCN}" ]; then + OSCN="${VER}" + fi fi case ${PLAT} in @@ -296,6 +311,13 @@ distroCheck(){ ;; esac ;; + Alpine) + PKG_MANAGER='apk' + UPDATE_PKG_CACHE="${PKG_MANAGER} update" + PKG_INSTALL="${PKG_MANAGER} --no-cache add" + PKG_COUNT="${PKG_MANAGER} list -u | wc -l || true" + CHECK_PKG_INSTALLED="${PKG_MANAGER} --no-cache info -e" + ;; *) noOSSupport ;; @@ -351,7 +373,7 @@ checkHostname(){ fi until [[ ${#host_name} -le 28 && $host_name =~ ^[a-zA-Z0-9][a-zA-Z0-9-]{1,28}$ ]]; do host_name=$(whiptail --inputbox "Your hostname is too long.\\nEnter new hostname with less then 28 characters\\nNo special characters allowed." \ - --title "Hostname too long" ${r} ${c} 3>&1 1>&2 2>&3) + --title "Hostname too long" ${r} ${c} 3>&1 1>&2 2>&3) $SUDO hostnamectl set-hostname "${host_name}" if [[ ${#host_name} -le 28 && $host_name =~ ^[a-zA-Z0-9][a-zA-Z0-9-]{1,28}$ ]]; then echo "::: Hostname valid and length OK, proceeding..." @@ -418,8 +440,9 @@ updatePackageCache(){ #update package lists echo ":::" echo -ne "::: Package Cache update is needed, running ${UPDATE_PKG_CACHE} ...\\n" - # shellcheck disable=SC2086 - $SUDO ${UPDATE_PKG_CACHE} &> /dev/null & spinner $! + # shellcheck disable=SC2086 + $SUDO ${UPDATE_PKG_CACHE} &> /dev/null & + spinner $! echo " done!" } @@ -444,7 +467,7 @@ preconfigurePackages(){ # Install packages used by this installation script # If apt is older than 1.5 we need to install an additional package to add # support for https repositories that will be used later on - if [[ -f /etc/apt/sources.list ]]; then + if [ "${PKG_MANAGER}" == 'apt-get' ] && [ -f /etc/apt/sources.list ]; then INSTALLED_APT="$(apt-cache policy apt | grep -m1 'Installed: ' | grep -v '(none)' | awk '{print $2}')" if dpkg --compare-versions "$INSTALLED_APT" lt 1.5; then BASE_DEPS+=("apt-transport-https") @@ -456,31 +479,53 @@ preconfigurePackages(){ BASE_DEPS+=(dhcpcd5) fi - DPKG_ARCH="$(dpkg --print-architecture)" + if [ "${PKG_MANAGER}" == 'apt-get' ]; then + DPKG_ARCH="$(dpkg --print-architecture)" + elif [ "${PKG_MANAGER}" == 'apk' ]; then + DPKG_ARCH="$(apk --print-arch)" + fi + + if [ "${PKG_MANAGER}" == 'apt-get' ]; then + AVAILABLE_OPENVPN="$(apt-cache policy openvpn | grep -m1 'Candidate: ' | grep -v '(none)' | awk '{print $2}')" + elif [ "${PKG_MANAGER}" == 'apk' ]; then + AVAILABLE_OPENVPN="$(apk search -e openvpn | sed -E -e 's/openvpn\-(.*)/\1/')" + fi - AVAILABLE_OPENVPN="$(apt-cache policy openvpn | grep -m1 'Candidate: ' | grep -v '(none)' | awk '{print $2}')" OPENVPN_SUPPORT=0 NEED_OPENVPN_REPO=0 # We require OpenVPN 2.4 or later for ECC support. If not available in the # repositories but we are running x86 Debian or Ubuntu, add the official repo # which provides the updated package. - if [ -n "$AVAILABLE_OPENVPN" ] && dpkg --compare-versions "$AVAILABLE_OPENVPN" ge 2.4; then - OPENVPN_SUPPORT=1 - else - if [ "$PLAT" = "Debian" ] || [ "$PLAT" = "Ubuntu" ]; then - if [ "$DPKG_ARCH" = "amd64" ] || [ "$DPKG_ARCH" = "i386" ]; then - NEED_OPENVPN_REPO=1 - OPENVPN_SUPPORT=1 + if [ "${PKG_MANAGER}" == 'apt-get' ]; then + if [ -n "$AVAILABLE_OPENVPN" ] && dpkg --compare-versions "$AVAILABLE_OPENVPN" ge 2.4; then + OPENVPN_SUPPORT=1 + else + if [ "$PLAT" = "Debian" ] || [ "$PLAT" = "Ubuntu" ]; then + if [ "$DPKG_ARCH" = "amd64" ] || [ "$DPKG_ARCH" = "i386" ]; then + NEED_OPENVPN_REPO=1 + OPENVPN_SUPPORT=1 + else + OPENVPN_SUPPORT=0 + fi else OPENVPN_SUPPORT=0 fi + fi + elif [ "${PKG_MANAGER}" == 'apk' ]; then + if [ -n "${AVAILABLE_OPENVPN}" ] && [ "$(apk version -t "${AVAILABLE_OPENVPN}" 2.4)" == '>' ]; then + OPENVPN_SUPPORT=1 else OPENVPN_SUPPORT=0 fi fi - AVAILABLE_WIREGUARD="$(apt-cache policy wireguard | grep -m1 'Candidate: ' | grep -v '(none)' | awk '{print $2}')" + if [ "${PKG_MANAGER}" == 'apt-get' ]; then + AVAILABLE_WIREGUARD="$(apt-cache policy wireguard | grep -m1 'Candidate: ' | grep -v '(none)' | awk '{print $2}')" + elif [ "${PKG_MANAGER}" == 'apk' ]; then + AVAILABLE_WIREGUARD="$(apk search -e wireguard-tools | sed -E -e 's/wireguard\-tools\-(.*)/\1/')" + fi + WIREGUARD_SUPPORT=0 # If a wireguard kernel object is found and is part of any installed package, then @@ -489,8 +534,11 @@ preconfigurePackages(){ # and not part of the .deb). # Source: https://github.com/MichaIng/DietPi/blob/7bf5e1041f3b2972d7827c48215069d1c90eee07/dietpi/dietpi-software#L1807-L1815 WIREGUARD_BUILTIN=0 - if dpkg-query -S '/lib/modules/*/wireguard.ko*' &> /dev/null || modinfo wireguard 2> /dev/null | grep -q '^filename:[[:blank:]]*(builtin)$'; then - WIREGUARD_BUILTIN=1 + + if [ "${PKG_MANAGER}" == 'apt-get' ]; then + if dpkg-query -S '/lib/modules/*/wireguard.ko*' &> /dev/null || modinfo wireguard 2> /dev/null | grep -q '^filename:[[:blank:]]*(builtin)$'; then + WIREGUARD_BUILTIN=1 + fi fi if @@ -500,13 +548,16 @@ preconfigurePackages(){ [[ $WIREGUARD_BUILTIN == 1 && ( $PLAT == 'Debian' || $PLAT == 'Raspbian' ) ]] || # If the module is not builtin, on Raspbian we know the headers package: raspberrypi-kernel-headers [[ $PLAT == 'Raspbian' ]] || + # On Alpine, the kernel must be linux-lts or linux-virt if we want to load the kernel module + [[ "${PLAT}" == 'Alpine' && ! -f /.dockerenv && "$(uname -mrs)" =~ ^Linux\ +[0-9\.\-]+\-((lts)|(virt))\ +.*$ ]] || + # On Alpine Docker Container, the responsibility to have a WireGuard module on the host system is at user side + [[ "${PLAT}" == 'Alpine' && -f /.dockerenv ]] || # On Debian (and Ubuntu), we can only reliably assume the headers package for amd64: linux-image-amd64 [[ $PLAT == 'Debian' && $DPKG_ARCH == 'amd64' ]] || # On Ubuntu, additionally the WireGuard package needs to be available, since we didn't test mixing Ubuntu repositories. [[ $PLAT == 'Ubuntu' && $DPKG_ARCH == 'amd64' && -n $AVAILABLE_WIREGUARD ]] || # Ubuntu focal has wireguard support - [[ $PLAT == 'Ubuntu' && $DPKG_ARCH == 'arm64' && $OSCN == 'focal' && -n $AVAILABLE_WIREGUARD ]] - then + [[ $PLAT == 'Ubuntu' && $DPKG_ARCH == 'arm64' && $OSCN == 'focal' && -n $AVAILABLE_WIREGUARD ]]; then WIREGUARD_SUPPORT=1 fi @@ -518,7 +569,7 @@ preconfigurePackages(){ # if ufw is enabled, configure that. # running as root because sometimes the executable is not in the user's $PATH if $SUDO bash -c 'command -v ufw' > /dev/null; then - if $SUDO ufw status | grep -q inactive; then + if ! ${SUDO} ufw status || $SUDO ufw status | grep -q inactive; then USING_UFW=0 else USING_UFW=1 @@ -527,12 +578,42 @@ preconfigurePackages(){ USING_UFW=0 fi - if [ "$USING_UFW" -eq 0 ]; then + if [ "${PKG_MANAGER}" == 'apt-get' ] && [ "$USING_UFW" -eq 0 ]; then BASE_DEPS+=(iptables-persistent) echo iptables-persistent iptables-persistent/autosave_v4 boolean true | $SUDO debconf-set-selections echo iptables-persistent iptables-persistent/autosave_v6 boolean false | $SUDO debconf-set-selections fi + if [[ "${PLAT}" == 'Alpine' ]] && ! command -v grepcidr &> /dev/null; then + ## install dependencies + # shellcheck disable=SC2086 + ${SUDO} ${PKG_INSTALL} build-base make curl tar + + ## download binaeries + curl -fLo master.tar.gz https://github.com/pivpn/grepcidr/archive/master.tar.gz + tar -xzf master.tar.gz + + cd grepcidr-master || exit 1 + + ## personalize binaries + sed -i -E -e 's/^PREFIX\=.*/PREFIX\=\/usr\nCC\=gcc/' Makefile + + ## install + make + ${SUDO} make install + + if ! command -v grepcidr &> /dev/null; then + echo "::: Failed to compile and install grepcidr!" + exit 1 + fi + + cd .. + + ## remove useless files + rm master.tar.gz + rm -rf grepcidr-master + fi + echo "USING_UFW=${USING_UFW}" >> ${tempsetupVarsFile} } @@ -547,12 +628,23 @@ installDependentPackages(){ for i in "${argArray1[@]}"; do echo -n "::: Checking for $i..." - if dpkg-query -W -f='${Status}' "${i}" 2>/dev/null | grep -q "ok installed"; then - echo " already installed!" - else - echo " not installed!" - # Add this package to the list of packages in the argument array that need to be installed - TO_INSTALL+=("${i}") + + if [ "${PKG_MANAGER}" == 'apt-get' ]; then + if dpkg-query -W -f='${Status}' "${i}" 2>/dev/null | grep -q "ok installed"; then + echo " already installed!" + else + echo " not installed!" + # Add this package to the list of packages in the argument array that need to be installed + TO_INSTALL+=("${i}") + fi + elif [ "${PKG_MANAGER}" == 'apk' ]; then + if eval "${SUDO} ${CHECK_PKG_INSTALLED} ${i}" &> /dev/null; then + echo " already installed!" + else + echo " not installed!" + # Add this package to the list of packages in the argument array that need to be installed + TO_INSTALL+=("${i}") + fi fi done @@ -570,13 +662,24 @@ installDependentPackages(){ local FAILED=0 for i in "${TO_INSTALL[@]}"; do - if dpkg-query -W -f='${Status}' "${i}" 2>/dev/null | grep -q "ok installed"; then - echo "::: Package $i successfully installed!" - # Add this package to the total list of packages that were actually installed by the script - INSTALLED_PACKAGES+=("${i}") - else - echo "::: Failed to install $i!" - ((FAILED++)) + if [ "${PKG_MANAGER}" == 'apt-get' ]; then + if dpkg-query -W -f='${Status}' "${i}" 2>/dev/null | grep -q "ok installed"; then + echo "::: Package $i successfully installed!" + # Add this package to the total list of packages that were actually installed by the script + INSTALLED_PACKAGES+=("${i}") + else + echo "::: Failed to install $i!" + ((FAILED++)) + fi + elif [ "${PKG_MANAGER}" == 'apk' ]; then + if eval "${SUDO} ${CHECK_PKG_INSTALLED} ${i}" &> /dev/null; then + echo "::: Package $i successfully installed!" + # Add this package to the total list of packages that were actually installed by the script + INSTALLED_PACKAGES+=("${i}") + else + echo "::: Failed to install $i!" + ((FAILED++)) + fi fi done @@ -627,38 +730,38 @@ else fi if [ -z "$availableInterfaces" ]; then - echo "::: Could not find any active network interface, exiting" - exit 1 + echo "::: Could not find any active network interface, exiting" + exit 1 else - while read -r line; do - mode="OFF" - if [[ ${firstloop} -eq 1 ]]; then - firstloop=0 - mode="ON" - fi - interfacesArray+=("${line}" "available" "${mode}") - ((interfaceCount++)) - done <<< "${availableInterfaces}" + while read -r line; do + mode="OFF" + if [[ ${firstloop} -eq 1 ]]; then + firstloop=0 + mode="ON" + fi + interfacesArray+=("${line}" "available" "${mode}") + ((interfaceCount++)) + done <<< "${availableInterfaces}" fi if [ "${runUnattended}" = 'true' ]; then - if [ -z "$IPv4dev" ]; then - if [ "$interfaceCount" -eq 1 ]; then - IPv4dev="${availableInterfaces}" - echo "::: No interface specified for IPv4, but only ${IPv4dev} is available, using it" - else - echo "::: No interface specified for IPv4 and failed to determine one" - exit 1 - fi - else - if ip -o link | grep -qw "${IPv4dev}"; then - echo "::: Using interface: ${IPv4dev} for IPv4" - else - echo "::: Interface ${IPv4dev} for IPv4 does not exist" - exit 1 - fi - fi - echo "IPv4dev=${IPv4dev}" >> ${tempsetupVarsFile} + if [ -z "$IPv4dev" ]; then + if [ "$interfaceCount" -eq 1 ]; then + IPv4dev="${availableInterfaces}" + echo "::: No interface specified for IPv4, but only ${IPv4dev} is available, using it" + else + echo "::: No interface specified for IPv4 and failed to determine one" + exit 1 + fi + else + if ip -o link | grep -qw "${IPv4dev}"; then + echo "::: Using interface: ${IPv4dev} for IPv4" + else + echo "::: Interface ${IPv4dev} for IPv4 does not exist" + exit 1 + fi + fi + echo "IPv4dev=${IPv4dev}" >> ${tempsetupVarsFile} if [ "$pivpnenableipv6" == "1" ]; then if [ -z "$IPv6dev" ]; then if [ "$interfaceCount" -eq 1 ]; then @@ -678,31 +781,31 @@ if [ "${runUnattended}" = 'true' ]; then fi fi if [ "$pivpnenableipv6" == "1" ] && [ -z "$IPv6dev" ]; then - echo "IPv6dev=${IPv6dev}" >> ${tempsetupVarsFile} + echo "IPv6dev=${IPv6dev}" >> ${tempsetupVarsFile} fi - return + return else - if [ "$interfaceCount" -eq 1 ]; then - IPv4dev="${availableInterfaces}" - echo "IPv4dev=${IPv4dev}" >> ${tempsetupVarsFile} + if [ "$interfaceCount" -eq 1 ]; then + IPv4dev="${availableInterfaces}" + echo "IPv4dev=${IPv4dev}" >> ${tempsetupVarsFile} if [ "$pivpnenableipv6" == "1" ]; then IPv6dev="${availableInterfaces}" echo "IPv6dev=${IPv6dev}" >> ${tempsetupVarsFile} - fi + fi return - fi + fi fi chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An interface for IPv4 (press space to select):" "${r}" "${c}" "${interfaceCount}") if chooseInterfaceOptions=$("${chooseInterfaceCmd[@]}" "${interfacesArray[@]}" 2>&1 >/dev/tty) ; then - for desiredInterface in ${chooseInterfaceOptions}; do - IPv4dev=${desiredInterface} - echo "::: Using interface: $IPv4dev" - echo "IPv4dev=${IPv4dev}" >> ${tempsetupVarsFile} - done + for desiredInterface in ${chooseInterfaceOptions}; do + IPv4dev=${desiredInterface} + echo "::: Using interface: $IPv4dev" + echo "IPv4dev=${IPv4dev}" >> ${tempsetupVarsFile} + done else - echo "::: Cancel selected, exiting...." - exit 1 + echo "::: Cancel selected, exiting...." + exit 1 fi if [ "$pivpnenableipv6" == "1" ]; then chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An interface for IPv6, usually the same as used by IPv4 (press space to select):" "${r}" "${c}" "${interfaceCount}") @@ -721,10 +824,10 @@ fi checkStaticIpSupported(){ # Not really robust and correct, we should actually check for dhcpcd, not the distro, but works on Raspbian and Debian. - if [ "$PLAT" = "Raspbian" ]; then + if [ "${PLAT}" = "Raspbian" ]; then return 0 # If we are on 'Debian' but the raspi.list file is present, then we actually are on 64-bit Raspberry Pi OS. - elif [ "$PLAT" = "Debian" ] && [ -s /etc/apt/sources.list.d/raspi.list ]; then + elif [ "${PLAT}" = "Debian" ] && [ -s /etc/apt/sources.list.d/raspi.list ]; then return 0 else return 1 @@ -787,7 +890,7 @@ checkipv6uplink(){ echo "::: IPv6 test connections to google.com successful. Enabling IPv6 support." pivpnenableipv6="1" fi - return + return } askforcedipv6route(){ @@ -893,7 +996,7 @@ Yes: Keep using DHCP reservation No: Setup static IP address Don't know what DHCP Reservation is? Answer No." ${r} ${c}); then dhcpReserv=1 - # shellcheck disable=SC2129 + # shellcheck disable=SC2129 echo "dhcpReserv=${dhcpReserv}" >> ${tempsetupVarsFile} # We don't really need to save them as we won't set a static IP but they might be useful for debugging echo "IPv4addr=${CurrentIPv4addr}" >> ${tempsetupVarsFile} @@ -1021,7 +1124,14 @@ chooseUser(){ echo "::: ${install_user} will hold your ovpn configurations." else echo "::: User ${install_user} does not exist, creating..." - $SUDO useradd -m -s /bin/bash "${install_user}" + + if [ "${PLAT}" == 'Alpine' ]; then + ${SUDO} adduser -s /bin/bash "${install_user}" + ${SUDO} addgroup "${install_user}" wheel + else + ${SUDO} useradd -ms /bin/bash "${install_user}" + fi + echo "::: User created without a password, please do sudo passwd $install_user to create one" fi fi @@ -1036,19 +1146,32 @@ chooseUser(){ whiptail --msgbox --backtitle "Parsing User List" --title "Local Users" "Choose a local user that will hold your ovpn configurations." ${r} ${c} # First, let's check if there is a user available. numUsers=$(awk -F':' 'BEGIN {count=0} $3>=1000 && $3<=60000 { count++ } END{ print count }' /etc/passwd) - if [ "$numUsers" -eq 0 ] - then + if [ "$numUsers" -eq 0 ]; then # We don't have a user, let's ask to add one. - if userToAdd=$(whiptail --title "Choose A User" --inputbox "No non-root user account was found. Please type a new username." ${r} ${c} 3>&1 1>&2 2>&3) - then + if userToAdd=$(whiptail --title "Choose A User" --inputbox "No non-root user account was found. Please type a new username." ${r} ${c} 3>&1 1>&2 2>&3); then # See https://askubuntu.com/a/667842/459815 PASSWORD=$(whiptail --title "password dialog" --passwordbox "Please enter the new user password" ${r} ${c} 3>&1 1>&2 2>&3) CRYPT=$(perl -e 'printf("%s\n", crypt($ARGV[0], "password"))' "${PASSWORD}") - if $SUDO useradd -m -p "${CRYPT}" -s /bin/bash "${userToAdd}" ; then - echo "Succeeded" - ((numUsers+=1)) + + if [ "${PLAT}" == 'Alpine' ]; then + if ${SUDO} adduser -Ds /bin/bash "${userToAdd}"; then + ${SUDO} addgroup "${userToAdd}" wheel + + ${SUDO} chpasswd <<< "${userToAdd}:${PASSWORD}" + ${SUDO} passwd -u "${userToAdd}" + + echo "Succeeded" + ((numUsers+=1)) + else + exit 1 + fi else - exit 1 + if ${SUDO} useradd -mp "${CRYPT}" -s /bin/bash "${userToAdd}"; then + echo "Succeeded" + ((numUsers+=1)) + else + exit 1 + fi fi else exit 1 @@ -1058,8 +1181,7 @@ chooseUser(){ local userArray=() local firstloop=1 - while read -r line - do + while read -r line; do mode="OFF" if [[ $firstloop -eq 1 ]]; then firstloop=0 @@ -1105,7 +1227,8 @@ updateRepo(){ # Go back to /usr/local/src otherwise git will complain when the current working # directory has just been deleted (/usr/local/src/pivpn). cd /usr/local/src && \ - $SUDO git clone -q --depth 1 --no-single-branch "${2}" "${1}" > /dev/null && spinner $! + $SUDO git clone -q --depth 1 --no-single-branch "${2}" "${1}" > /dev/null & + spinner $! cd "${1}" || exit 1 echo " done!" if [ -n "${pivpnGitBranch}" ]; then @@ -1133,7 +1256,8 @@ makeRepo(){ # Go back to /usr/local/src otherwhise git will complain when the current working # directory has just been deleted (/usr/local/src/pivpn). cd /usr/local/src && \ - $SUDO git clone -q --depth 1 --no-single-branch "${2}" "${1}" > /dev/null & spinner $! + $SUDO git clone -q --depth 1 --no-single-branch "${2}" "${1}" > /dev/null & + spinner $! cd "${1}" || exit 1 echo " done!" if [ -n "${pivpnGitBranch}" ]; then @@ -1177,34 +1301,41 @@ installPiVPN(){ askWhichVPN setVPNDefaultVars - if [ "$VPN" = "openvpn" ]; then - + if [ "${VPN}" == 'openvpn' ]; then setOpenVPNDefaultVars askAboutCustomizing installOpenVPN askCustomProto - askCustomPort - askClientDNS + elif [ "${VPN}" == 'wireguard' ]; then + setWireguardDefaultVars + installWireGuard + fi + + askCustomPort + askClientDNS + + if [ "${VPN}" == 'openvpn' ]; then askCustomDomain - askPublicIPOrDNS + fi + + askPublicIPOrDNS + + if [ "${VPN}" == 'openvpn' ]; then askEncryption confOpenVPN confOVPN - confNetwork - confLogging - - elif [ "$VPN" = "wireguard" ]; then - - setWireguardDefaultVars - installWireGuard - askCustomPort - askClientDNS - askPublicIPOrDNS + elif [ "${VPN}" == 'wireguard' ]; then confWireGuard - confNetwork - writeWireguardTempVarsFile - fi + + confNetwork + + if [ "${VPN}" == 'openvpn' ]; then + confLogging + elif [ "${VPN}" == 'wireguard' ]; then + writeWireguardTempVarsFile + fi + writeVPNTempVarsFile } @@ -1220,7 +1351,19 @@ setVPNDefaultVars(){ generateRandomSubnet() { # Source: https://community.openvpn.net/openvpn/wiki/AvoidRoutingConflicts - declare -a SUBNET_EXCLUDE_LIST=(10.0.0.0/24 10.0.1.0/24 10.1.1.0/24 10.1.10.0/24 10.2.0.0/24 10.8.0.0/24 10.10.1.0/24 10.90.90.0/24 10.100.1.0/24 10.255.255.0/24) + declare -a SUBNET_EXCLUDE_LIST + + SUBNET_EXCLUDE_LIST=(10.0.0.0/24) + SUBNET_EXCLUDE_LIST+=(10.0.1.0/24) + SUBNET_EXCLUDE_LIST+=(10.1.1.0/24) + SUBNET_EXCLUDE_LIST+=(10.1.10.0/24) + SUBNET_EXCLUDE_LIST+=(10.2.0.0/24) + SUBNET_EXCLUDE_LIST+=(10.8.0.0/24) + SUBNET_EXCLUDE_LIST+=(10.10.1.0/24) + SUBNET_EXCLUDE_LIST+=(10.90.90.0/24) + SUBNET_EXCLUDE_LIST+=(10.100.1.0/24) + SUBNET_EXCLUDE_LIST+=(10.255.255.0/24) + readarray -t CURRENTLY_USED_SUBNETS <<< "$(ip route show | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}')" SUBNET_EXCLUDE_LIST=("${SUBNET_EXCLUDE_LIST[@]}" "${CURRENTLY_USED_SUBNETS[@]}") @@ -1410,6 +1553,7 @@ installOpenVPN(){ # Expect is used to feed easy-rsa with passwords PIVPN_DEPS=(openvpn expect) + installDependentPackages PIVPN_DEPS[@] } @@ -1473,6 +1617,12 @@ installWireGuard(){ installDependentPackages PIVPN_DEPS[@] + elif [ "${PLAT}" == 'Alpine' ]; then + echo "::: Installing WireGuard... " + + PIVPN_DEPS=(wireguard-tools libqrencode) + + installDependentPackages PIVPN_DEPS[@] fi } @@ -1506,8 +1656,7 @@ askCustomProto(){ if pivpnPROTO=$(whiptail --title "Protocol" --radiolist \ "Choose a protocol (press space to select). Please only choose TCP if you know why you need TCP." ${r} ${c} 2 \ "UDP" "" ON \ - "TCP" "" OFF 3>&1 1>&2 2>&3) - then + "TCP" "" OFF 3>&1 1>&2 2>&3); then # Convert option into lowercase (UDP->udp) pivpnPROTO="${pivpnPROTO,,}" echo "::: Using protocol: $pivpnPROTO" @@ -1545,8 +1694,7 @@ askCustomPort(){ return fi - until [[ $PORTNumCorrect = True ]] - do + until [[ $PORTNumCorrect = True ]]; do portInvalid="Invalid" if [ "$VPN" = "wireguard" ]; then @@ -1559,8 +1707,7 @@ askCustomPort(){ fi fi - if pivpnPORT=$(whiptail --title "Default $VPN Port" --inputbox "You can modify the default $VPN port. \\nEnter a new value or hit 'Enter' to retain the default" ${r} ${c} $DEFAULT_PORT 3>&1 1>&2 2>&3) - then + if pivpnPORT=$(whiptail --title "Default $VPN Port" --inputbox "You can modify the default $VPN port. \\nEnter a new value or hit 'Enter' to retain the default" ${r} ${c} $DEFAULT_PORT 3>&1 1>&2 2>&3); then if [[ "$pivpnPORT" =~ ^[0-9]+$ ]] && [ "$pivpnPORT" -ge 1 ] && [ "$pivpnPORT" -le 65535 ]; then : else @@ -1669,8 +1816,7 @@ askClientDNS(){ PiVPN-is-local-DNS "" off Custom "" off) - if DNSchoices=$("${DNSChoseCmd[@]}" "${DNSChooseOptions[@]}" 2>&1 >/dev/tty) - then + if DNSchoices=$("${DNSChoseCmd[@]}" "${DNSChooseOptions[@]}" 2>&1 >/dev/tty); then if [[ ${DNSchoices} != "Custom" ]]; then @@ -1693,8 +1839,7 @@ askClientDNS(){ until [[ $DNSSettingsCorrect = True ]]; do strInvalid="Invalid" - if pivpnDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\\n\\nFor example '1.1.1.1, 9.9.9.9'" ${r} ${c} "" 3>&1 1>&2 2>&3) - then + if pivpnDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\\n\\nFor example '1.1.1.1, 9.9.9.9'" ${r} ${c} "" 3>&1 1>&2 2>&3); then pivpnDNS1=$(echo "$pivpnDNS" | sed 's/[, \t]\+/,/g' | awk -F, '{print$1}') pivpnDNS2=$(echo "$pivpnDNS" | sed 's/[, \t]\+/,/g' | awk -F, '{print$2}') if ! validIP "$pivpnDNS1" || [ ! "$pivpnDNS1" ]; then @@ -1739,7 +1884,7 @@ askClientDNS(){ #Call this function to use a regex to check user input for a valid custom domain validDomain(){ - local domain="$1" + local domain="$1" grep -qP '(?=^.{4,253}$)(^(?:[a-zA-Z0-9](?:(?:[a-zA-Z0-9\-]){0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$)' <<< "$domain" } @@ -1771,8 +1916,7 @@ askCustomDomain(){ if (whiptail --backtitle "Custom Search Domain" --title "Custom Search Domain" --yesno --defaultno "Would you like to add a custom search domain? \\n (This is only for advanced users who have their own domain)\\n" ${r} ${c}); then - until [[ $DomainSettingsCorrect = True ]] - do + until [[ $DomainSettingsCorrect = True ]]; do if pivpnSEARCHDOMAIN=$(whiptail --inputbox "Enter Custom Domain\\nFormat: mydomain.com" ${r} ${c} --title "Custom Domain" 3>&1 1>&2 2>&3); then if validDomain "$pivpnSEARCHDOMAIN"; then if (whiptail --backtitle "Custom Search Domain" --title "Custom Search Domain" --yesno "Are these settings correct?\\n Custom Search Domain: $pivpnSEARCHDOMAIN" ${r} ${c}); then @@ -2089,10 +2233,18 @@ confOpenVPN(){ # Generate an empty Certificate Revocation List ${SUDOE} ./easyrsa gen-crl ${SUDOE} cp pki/crl.pem /etc/openvpn/crl.pem - if ! getent passwd openvpn; then - ${SUDOE} adduser --system --home /var/lib/openvpn/ --group --disabled-login ${debianOvpnUserGroup%:*} - fi - ${SUDOE} chown "$debianOvpnUserGroup" /etc/openvpn/crl.pem + + if [ "${PLAT}" == 'Alpine' ]; then + if ! getent passwd "${ovpnUserGroup%:*}"; then + ${SUDOE} adduser -SDh /var/lib/openvpn/ -s /sbin/nologin "${ovpnUserGroup%:*}" + fi + else + if ! getent passwd "${ovpnUserGroup%:*}"; then + ${SUDOE} useradd --system --home /var/lib/openvpn/ --shell /usr/sbin/nologin "${ovpnUserGroup%:*}" + fi + fi + + ${SUDOE} chown "${ovpnUserGroup}" /etc/openvpn/crl.pem # Write config file for server using the template.txt file $SUDO install -m 644 "$pivpnFilesDir"/files/etc/openvpn/server_config.txt /etc/openvpn/server.conf @@ -2149,6 +2301,12 @@ confOpenVPN(){ # write out server certs to conf file $SUDO sed -i "s#\\(key /etc/openvpn/easy-rsa/pki/private/\\).*#\\1${SERVER_NAME}.key#" /etc/openvpn/server.conf $SUDO sed -i "s#\\(cert /etc/openvpn/easy-rsa/pki/issued/\\).*#\\1${SERVER_NAME}.crt#" /etc/openvpn/server.conf + + # On Alpine Linux, the default config file for OpenVPN is "/etc/openvpn/openvpn.conf" + # To avoid crash thorugh OpenRC, we symlink this file + if [[ "${PLAT}" == 'Alpine' ]]; then + ${SUDO} ln -sfT /etc/openvpn/server.conf /etc/openvpn/openvpn.conf > /dev/null + fi } confOVPN(){ @@ -2177,10 +2335,16 @@ confOVPN(){ confWireGuard(){ # Reload job type is not yet available in wireguard-tools shipped with Ubuntu 20.04 - if ! grep -q 'ExecReload' /lib/systemd/system/wg-quick@.service; then - echo "::: Adding additional reload job type for wg-quick unit" - $SUDO install -D -m 644 "${pivpnFilesDir}"/files/etc/systemd/system/wg-quick@.service.d/override.conf /etc/systemd/system/wg-quick@.service.d/override.conf - $SUDO systemctl daemon-reload + if [ "${PLAT}" == 'Alpine' ]; then + echo '::: Adding wg-quick unit' + + ${SUDO} install -m 0755 "${pivpnFilesDir}/files/etc/init.d/wg-quick" /etc/init.d/wg-quick + else + if ! grep -q 'ExecReload' /lib/systemd/system/wg-quick@.service; then + echo "::: Adding additional reload job type for wg-quick unit" + $SUDO install -D -m 644 "${pivpnFilesDir}"/files/etc/systemd/system/wg-quick@.service.d/override.conf /etc/systemd/system/wg-quick@.service.d/override.conf + $SUDO systemctl daemon-reload + fi fi if [ -d /etc/wireguard ]; then @@ -2225,34 +2389,34 @@ confWireGuard(){ echo "::: Server Keys have been generated." - if [ "$pivpnenableipv6" == "1" ]; then + { + echo '[Interface]' + echo "PrivateKey = $(${SUDO} cat /etc/wireguard/keys/server_priv)" + echo -n "Address = ${vpnGw}/${subnetClass}" - echo "[Interface] -PrivateKey = $($SUDO cat /etc/wireguard/keys/server_priv) -Address = ${vpnGw}/${subnetClass},${vpnGwv6}/${subnetClassv6} -MTU = ${pivpnMTU} -ListenPort = ${pivpnPORT}" | $SUDO tee /etc/wireguard/wg0.conf &> /dev/null + if [ "$pivpnenableipv6" == "1" ]; then + echo ",${vpnGwv6}/${subnetClassv6}" + else + echo + fi - else + echo "MTU = ${pivpnMTU}" + echo "ListenPort = ${pivpnPORT}" + } | ${SUDO} tee /etc/wireguard/wg0.conf &> /dev/null - echo "[Interface] -PrivateKey = $($SUDO cat /etc/wireguard/keys/server_priv) -Address = ${vpnGw}/${subnetClass} -MTU = ${pivpnMTU} -ListenPort = ${pivpnPORT}" | $SUDO tee /etc/wireguard/wg0.conf &> /dev/null - - fi echo "::: Server config generated." } confNetwork(){ # Enable forwarding of internet traffic - $SUDO sed -i '/net.ipv4.ip_forward=1/s/^#//g' /etc/sysctl.conf + echo 'net.ipv4.ip_forward=1' | $SUDO tee /etc/sysctl.d/99-pivpn.conf > /dev/null + if [ "$pivpnenableipv6" == "1" ]; then - $SUDO sed -i '/net.ipv6.conf.all.forwarding=1/s/^#//g' /etc/sysctl.conf - echo "net.ipv6.conf.${IPv6dev}.accept_ra=2" | $SUDO tee /etc/sysctl.d/99-pivpn.conf > /dev/null + echo "net.ipv6.conf.all.forwarding=1 +net.ipv6.conf.${IPv6dev}.accept_ra=2" | $SUDO tee -a /etc/sysctl.d/99-pivpn.conf > /dev/null fi - $SUDO sysctl -p > /dev/null + + ${SUDO} sysctl -p /etc/sysctl.d/99-pivpn.conf > /dev/null if [ "$USING_UFW" -eq 1 ]; then @@ -2411,8 +2575,14 @@ confLogging() { # Pre-create rsyslog/logrotate config directories if missing, to assure logs are handled as expected when those are installed at a later time $SUDO mkdir -p /etc/{rsyslog,logrotate}.d - echo "if \$programname == 'ovpn-server' then /var/log/openvpn.log -if \$programname == 'ovpn-server' then stop" | $SUDO tee /etc/rsyslog.d/30-openvpn.conf > /dev/null + if [ "${PLAT}" == 'Alpine' ]; then + program_name='openvpn' + else + program_name='ovpn-server' + fi + + echo "if \$programname == '${program_name}' then /var/log/openvpn.log +if \$programname == '${program_name}' then stop" | $SUDO tee /etc/rsyslog.d/30-openvpn.conf > /dev/null echo "/var/log/openvpn.log { @@ -2429,10 +2599,14 @@ if \$programname == 'ovpn-server' then stop" | $SUDO tee /etc/rsyslog.d/30-openv }" | $SUDO tee /etc/logrotate.d/openvpn > /dev/null # Restart the logging service - case ${PLAT} in - Debian|Raspbian|Ubuntu) + case "${PLAT}" in + Debian | Raspbian | Ubuntu) $SUDO systemctl -q is-active rsyslog.service && $SUDO systemctl restart rsyslog.service ;; + Alpine) + ${SUDO} rc-service -is rsyslog restart + ${SUDO} rc-service -iN rsyslog start + ;; esac } @@ -2450,6 +2624,17 @@ restartServices(){ $SUDO systemctl restart wg-quick@wg0.service fi ;; + Alpine) + if [ "${VPN}" == 'openvpn' ]; then + ${SUDO} rc-update add openvpn default &> /dev/null + ${SUDO} rc-service -s openvpn restart + ${SUDO} rc-service -N openvpn start + elif [ "${VPN}" == 'wireguard' ]; then + ${SUDO} rc-update add wg-quick default &> /dev/null + ${SUDO} rc-service -s wg-quick restart + ${SUDO} rc-service -N wg-quick start + fi + ;; esac } @@ -2482,52 +2667,63 @@ askUnattendedUpgrades(){ confUnattendedUpgrades(){ local PIVPN_DEPS - PIVPN_DEPS=(unattended-upgrades) - installDependentPackages PIVPN_DEPS[@] - aptConfDir="/etc/apt/apt.conf.d" - if [ "$PLAT" = "Ubuntu" ]; then + if [[ "${PKG_MANAGER}" == 'apt-get' ]]; then + PIVPN_DEPS=(unattended-upgrades) + installDependentPackages PIVPN_DEPS[@] + aptConfDir="/etc/apt/apt.conf.d" - # Ubuntu 50unattended-upgrades should already just have security enabled - # so we just need to configure the 10periodic file - echo "APT::Periodic::Update-Package-Lists \"1\"; - APT::Periodic::Download-Upgradeable-Packages \"1\"; - APT::Periodic::AutocleanInterval \"5\"; - APT::Periodic::Unattended-Upgrade \"1\";" | $SUDO tee "${aptConfDir}/10periodic" > /dev/null + if [ "$PLAT" = "Ubuntu" ]; then + # Ubuntu 50unattended-upgrades should already just have security enabled + # so we just need to configure the 10periodic file + echo "APT::Periodic::Update-Package-Lists \"1\"; + APT::Periodic::Download-Upgradeable-Packages \"1\"; + APT::Periodic::AutocleanInterval \"5\"; + APT::Periodic::Unattended-Upgrade \"1\";" | $SUDO tee "${aptConfDir}/10periodic" > /dev/null + else - else + # Raspbian's unattended-upgrades package downloads Debian's config, so we copy over the proper config + # Source: https://github.com/mvo5/unattended-upgrades/blob/master/data/50unattended-upgrades.Raspbian + if [ "$PLAT" = "Raspbian" ]; then + $SUDO install -m 644 "${pivpnFilesDir}/files${aptConfDir}/50unattended-upgrades.Raspbian" "${aptConfDir}/50unattended-upgrades" + fi - # Raspbian's unattended-upgrades package downloads Debian's config, so we copy over the proper config - # Source: https://github.com/mvo5/unattended-upgrades/blob/master/data/50unattended-upgrades.Raspbian - if [ "$PLAT" = "Raspbian" ]; then - $SUDO install -m 644 "${pivpnFilesDir}/files${aptConfDir}/50unattended-upgrades.Raspbian" "${aptConfDir}/50unattended-upgrades" + # Add the remaining settings for all other distributions + echo "APT::Periodic::Enable \"1\"; + APT::Periodic::Update-Package-Lists \"1\"; + APT::Periodic::Download-Upgradeable-Packages \"1\"; + APT::Periodic::Unattended-Upgrade \"1\"; + APT::Periodic::AutocleanInterval \"7\"; + APT::Periodic::Verbose \"0\";" | $SUDO tee "${aptConfDir}/02periodic" > /dev/null fi - # Add the remaining settings for all other distributions - echo "APT::Periodic::Enable \"1\"; - APT::Periodic::Update-Package-Lists \"1\"; - APT::Periodic::Download-Upgradeable-Packages \"1\"; - APT::Periodic::Unattended-Upgrade \"1\"; - APT::Periodic::AutocleanInterval \"7\"; - APT::Periodic::Verbose \"0\";" | $SUDO tee "${aptConfDir}/02periodic" > /dev/null - - fi - - # Enable automatic updates via the bullseye repository when installing from debian package - if [ "$VPN" = "wireguard" ]; then - if [ -f /etc/apt/sources.list.d/pivpn-bullseye-repo.list ]; then - if ! grep -q "\"o=$PLAT,n=bullseye\";" "${aptConfDir}/50unattended-upgrades"; then - $SUDO sed -i "/Unattended-Upgrade::Origins-Pattern {/a\"o=$PLAT,n=bullseye\";" "${aptConfDir}/50unattended-upgrades" + # Enable automatic updates via the bullseye repository when installing from debian package + if [ "$VPN" = "wireguard" ]; then + if [ -f /etc/apt/sources.list.d/pivpn-bullseye-repo.list ]; then + if ! grep -q "\"o=$PLAT,n=bullseye\";" "${aptConfDir}/50unattended-upgrades"; then + $SUDO sed -i "/Unattended-Upgrade::Origins-Pattern {/a\"o=$PLAT,n=bullseye\";" "${aptConfDir}/50unattended-upgrades" + fi fi fi + elif [[ "${PKG_MANAGER}" == 'apk' ]]; then + echo 'https://dl-cdn.alpinelinux.org/alpine/edge/testing/' | ${SUDO} tee -a /etc/apk/repositories && ${SUDO} apk -q update + + PIVPN_DEPS=(apk-autoupdate) + + installDependentPackages PIVPN_DEPS[@] + + ${SUDO} sed -i -E -e '/^https:\/\/dl\-cdn\.alpinelinux\.org\/alpine\/edge\/testing\/$/d' /etc/apk/repositories && ${SUDO} apk -q update + + ${SUDO} install -m 0755 "${pivpnFilesDir}/files/etc/apk/personal_autoupdate.conf" /etc/apk/personal_autoupdate.conf + ${SUDO} apk-autoupdate /etc/apk/personal_autoupdate.conf fi } writeConfigFiles(){ # Save installation setting to the final location echo "INSTALLED_PACKAGES=(${INSTALLED_PACKAGES[*]})" >> ${tempsetupVarsFile} - echo "::: Setupfiles copied to ${setupConfigDir}/${VPN}/${setupVarsFile}" - $SUDO mkdir -p "${setupConfigDir}/${VPN}/" + echo "::: Setupfiles copied to ${setupConfigDir}/${VPN}/${setupVarsFile}" + $SUDO mkdir -p "${setupConfigDir}/${VPN}/" $SUDO cp ${tempsetupVarsFile} "${setupConfigDir}/${VPN}/${setupVarsFile}" } @@ -2555,9 +2751,8 @@ installScripts(){ $SUDO ln -sf -T "${pivpnFilesDir}/scripts/pivpn" /usr/local/bin/pivpn else # Check if bash_completion scripts dir exists and creates it if not - if [ ! -d "/etc/bash_completion.d" ]; then - mkdir -p /etc/bash_copletion.d - fi + ${SUDO} mkdir -p /etc/bash_completion.d + # Only one protocol is installed, symlink bash completion, the pivpn script # and the script directory $SUDO ln -sf -T "${pivpnFilesDir}/scripts/${VPN}/bash-completion" /etc/bash_completion.d/pivpn @@ -2597,7 +2792,8 @@ All incomplete posts or bug reports will be ignored or deleted.\\n\\nThank you f whiptail --title "Rebooting" --msgbox "The system will now reboot." ${r} ${c} printf "\\nRebooting system...\\n" $SUDO sleep 3 - $SUDO shutdown -r now + + ${SUDO} reboot fi } diff --git a/ciscripts/startup.sh b/ciscripts/startup.sh index b519866..33a2bc4 100644 --- a/ciscripts/startup.sh +++ b/ciscripts/startup.sh @@ -10,7 +10,7 @@ common(){ sed -i "s|IPADDRESS|$ipaddress|g" "$vpnconfig" sed -i "s/GATEWAY/$gateway/g" "$vpnconfig" } - + openvpn(){ vpnconfig="ciscripts/ci_openvpn.conf" twofour=1 @@ -36,11 +36,11 @@ else cat /etc/os-release while true; do case "$1" in - -o | --openvpn ) openvpn + -o | --openvpn ) openvpn ;; -w | --wireguard ) wireguard ;; - * ) echo "unknown vpn protocol"; exit 1 + * ) echo "unknown vpn protocol"; exit 1 ;; esac done diff --git a/ciscripts/test.sh b/ciscripts/test.sh index 7986b33..c24db6f 100644 --- a/ciscripts/test.sh +++ b/ciscripts/test.sh @@ -1,6 +1,10 @@ #!/bin/bash -systemctl status openvpn +if command -v systemctl > /dev/null; then + systemctl status openvpn +elif command -v rc-service > /dev/null; then + rc-service openvpn status +fi pivpn add -n foo pivpn -qr foo pivpn -bk diff --git a/files/etc/apk/personal_autoupdate.conf b/files/etc/apk/personal_autoupdate.conf new file mode 100755 index 0000000..b15d744 --- /dev/null +++ b/files/etc/apk/personal_autoupdate.conf @@ -0,0 +1,25 @@ +############################################################################################# +# Filename: files/etc/apk/personal_autoupdate.conf # +# Purpose: Configuration file for apk-autoupdate that override the default configs # +# Authors: Giulio Coa <34110430+giulioc008@users.noreply.github.com> # +# License: This file is licensed under the MIT. # +############################################################################################# + +can_upgrade() { + case_match "${_packages_blacklist}" "$1" && return 1 + + case "$1" in + apk-tools) + _apk --quiet --no-cache --simulate upgrade --self-upgrade-only "$1" + ;; + *) + _apk --quiet --no-cache --simulate add --upgrade "$1" + ;; + esac + + return 0 +} + +finalize() { + : +} \ No newline at end of file diff --git a/files/etc/init.d/wg-quick b/files/etc/init.d/wg-quick new file mode 100755 index 0000000..01fabee --- /dev/null +++ b/files/etc/init.d/wg-quick @@ -0,0 +1,23 @@ +#!/sbin/openrc-run + +################################################################################# +# Filename: files/etc/init.d/wg-quick # +# Purpose: OpenRC service that starts WireGuard # +# Authors: Giulio Coa <34110430+giulioc008@users.noreply.github.com> # +# License: This file is licensed under the MIT. # +################################################################################# + +description="WireGuard - Quick version" + +depend() { + need localmount + need net +} + +start() { + wg-quick up wg0 +} + +stop() { + wg-quick down wg0 +} diff --git a/scripts/backup.sh b/scripts/backup.sh index 144a346..793a73d 100755 --- a/scripts/backup.sh +++ b/scripts/backup.sh @@ -18,6 +18,8 @@ date=$(date +%Y%m%d-%H%M%S) setupVarsFile="setupVars.conf" setupConfigDir="/etc/pivpn" +CHECK_PKG_INSTALLED='dpkg-query -s' + if [ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ] && [ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]; then # Two protocols have been installed, check if the script has passed @@ -57,6 +59,10 @@ fi # shellcheck disable=SC1090 source "${setupVars}" +if [ "${PLAT}" == 'Alpine' ]; then + CHECK_PKG_INSTALLED='apk --no-cache info -e' +fi + checkbackupdir(){ # Disabling shellcheck error $install_home sourced from $setupVars @@ -90,8 +96,8 @@ backup_wireguard(){ } -if [[ ! $EUID -eq 0 ]];then - if [[ $(dpkg-query -s sudo) ]];then +if [[ ! $EUID -eq 0 ]]; then + if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then export SUDO="sudo" else echo "::: Please install sudo or run this as root." diff --git a/scripts/openvpn/bash-completion b/scripts/openvpn/bash-completion index 83a321b..1a9cb96 100644 --- a/scripts/openvpn/bash-completion +++ b/scripts/openvpn/bash-completion @@ -7,15 +7,13 @@ _pivpn() prev="${COMP_WORDS[COMP_CWORD-1]}" dashopts="-a -c -d -l -r -h -u -up -bk" opts="debug add clients list revoke uninstall help update backup" - if [ "${#COMP_WORDS[@]}" -eq 2 ] - then + if [ "${#COMP_WORDS[@]}" -eq 2 ]; then if [[ ${cur} == -* ]] ; then COMPREPLY=( "$(compgen -W "${dashopts}" -- "${cur}")" ) else COMPREPLY=( "$(compgen -W "${opts}" -- "${cur}")" ) fi - elif [[ ( "$prev" == "add" || "$prev" == "-a" ) && "${#COMP_WORDS[@]}" -eq 3 ]] - then + elif [[ ( "$prev" == "add" || "$prev" == "-a" ) && "${#COMP_WORDS[@]}" -eq 3 ]]; then COMPREPLY=( "$(compgen -W "nopass" -- "${cur}")" ) fi return 0 diff --git a/scripts/openvpn/listOVPN.sh b/scripts/openvpn/listOVPN.sh index 4718f60..009c82a 100755 --- a/scripts/openvpn/listOVPN.sh +++ b/scripts/openvpn/listOVPN.sh @@ -26,7 +26,7 @@ while read -r line || [ -n "$line" ]; do STATUS=$(echo "$line" | awk '{print $1}') NAME=$(echo "$line" | awk -FCN= '{print $2}') EXPD=$(echo "$line" | awk '{if (length($2) == 15) print $2; else print "20"$2}' | cut -b 1-8 | date +"%b %d %Y" -f -) - + if [ "${STATUS}" == "V" ]; then printf "Valid \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD" elif [ "${STATUS}" == "R" ]; then diff --git a/scripts/openvpn/makeOVPN.sh b/scripts/openvpn/makeOVPN.sh index 0b60ac4..172224c 100755 --- a/scripts/openvpn/makeOVPN.sh +++ b/scripts/openvpn/makeOVPN.sh @@ -42,14 +42,12 @@ if [ -z "$HELP_SHOWN" ]; then fi # Parse input arguments -while test $# -gt 0 -do +while test $# -gt 0; do _key="$1" case "$_key" in -n|--name|--name=*) _val="${_key##--name=}" - if test "$_val" = "$_key" - then + if test "$_val" = "$_key"; then test $# -lt 2 && echo "Missing value for the optional argument '$_key'." && exit 1 _val="$2" shift @@ -58,8 +56,7 @@ do ;; -p|--password|--password=*) _val="${_key##--password=}" - if test "$_val" = "$_key" - then + if test "$_val" = "$_key"; then test $# -lt 2 && echo "Missing value for the optional argument '$_key'." && exit 1 _val="$2" shift @@ -68,8 +65,7 @@ do ;; -d|--days|--days=*) _val="${_key##--days=}" - if test "$_val" = "$_key" - then + if test "$_val" = "$_key"; then test $# -lt 2 && echo "Missing value for the optional argument '$_key'." && exit 1 _val="$2" shift @@ -96,8 +92,20 @@ do if command -v bw > /dev/null; then BITWARDEN="2" else - echo "Bitwarden not found, please install bitwarden" - exit 1 + echo 'Bitwarden not found, please install bitwarden' + + if [ "${PLAT}" == 'Alpine' ]; then + echo 'You can download it through the following commands:' + echo $'\t' 'curl -fLo bitwarden.zip --no-cache https://github.com/bitwarden/clients/releases/download/cli-v2022.6.2/bw-linux-2022.6.2.zip' + echo $'\t' 'apk --no-cache -X https://dl-cdn.alpinelinux.org/alpine/edge/testing/ add atool' + echo $'\t' 'aunpack -F zip bitwarden.zip' + echo $'\t' 'mv bw /opt/bw' + echo $'\t' 'chmod 755 /opt/bw' + echo $'\t' 'rm bitwarden.zip' + echo $'\t' 'apk --no-cache --purge del -r atool' + fi + + exit 1 fi ;; @@ -144,8 +152,7 @@ function useBitwarden() { read -r NAME # check name - until [[ "$NAME" =~ ^[a-zA-Z0-9.@_-]+$ && ${NAME::1} != "." && ${NAME::1} != "-" ]] - do + until [[ "$NAME" =~ ^[a-zA-Z0-9.@_-]+$ && ${NAME::1} != "." && ${NAME::1} != "-" ]]; do echo "Name can only contain alphanumeric characters and these characters (.-@_). The name also cannot start with a dot (.) or a dash (-). Please try again." # ask user for username again printf "Enter the username: " @@ -158,8 +165,7 @@ function useBitwarden() { read -r LENGTH # check length - until [[ "$LENGTH" -gt 11 && "$LENGTH" -lt 129 ]] - do + until [[ "$LENGTH" -gt 11 && "$LENGTH" -lt 129 ]]; do echo "Password must be between from 12 to 128 characters, please try again." # ask user for length of password printf "Enter the length of characters you want your password to be (minimum 12): " @@ -179,8 +185,7 @@ function keyPASS() { if [[ -z "${PASSWD}" ]]; then stty -echo - while true - do + while true; do printf "Enter the password for the client: " read -r PASSWD printf "\n" @@ -198,15 +203,14 @@ function keyPASS() { exit 1 fi fi - if [ ${#PASSWD} -lt 4 ] || [ ${#PASSWD} -gt 1024 ] - then + if [ ${#PASSWD} -lt 4 ] || [ ${#PASSWD} -gt 1024 ]; then echo "Password must be between from 4 to 1024 characters" exit 1 fi #Escape chars in PASSWD PASSWD_UNESCAPED="${PASSWD}" - PASSWD=$(echo -n "${PASSWD}" | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/\$/\\\$/g' -e 's/!/\\!/g' -e 's/\./\\\./g' -e "s/'/\\\'/g" -e 's/"/\\"/g' -e 's/\*/\\\*/g' -e 's/\@/\\\@/g' -e 's/\#/\\\#/g' -e 's/£/\\£/g' -e 's/%/\\%/g' -e 's/\^/\\\^/g' -e 's/\&/\\\&/g' -e 's/(/\\(/g' -e 's/)/\\)/g' -e 's/-/\\-/g' -e 's/_/\\_/g' -e 's/\+/\\\+/g' -e 's/=/\\=/g' -e 's/\[/\\\[/g' -e 's/\]/\\\]/g' -e 's/;/\\;/g' -e 's/:/\\:/g' -e 's/|/\\|/g' -e 's//\\>/g' -e 's/,/\\,/g' -e 's/?/\\?/g' -e 's/~/\\~/g' -e 's/{/\\{/g' -e 's/}/\\}/g') + PASSWD=$(echo -n "${PASSWD}" | sed -E -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/\$/\\\$/g' -e 's/!/\\!/g' -e 's/\./\\\./g' -e "s/'/\\'/g" -e 's/"/\\"/g' -e 's/\*/\\\*/g' -e 's/@/\\@/g' -e 's/#/\\#/g' -e 's/£/\\£/g' -e 's/%/\\%/g' -e 's/\^/\\\^/g' -e 's/&/\\&/g' -e 's/\(/\\\(/g' -e 's/\)/\\\)/g' -e 's/\-/\\\-/g' -e 's/_/\\_/g' -e 's/\+/\\\+/g' -e 's/=/\\=/g' -e 's/\[/\\\[/g' -e 's/\]/\\\]/g' -e 's/;/\\;/g' -e 's/:/\\:/g' -e 's/\|/\\\|/g' -e 's/\/\\\>/g' -e 's/,/\\,/g' -e 's/\?/\\\?/g' -e 's/~/\\~/g' -e 's/\{/\\\{/g' -e 's/\}/\\\}/g') #Build the client key and then encrypt the key @@ -362,7 +366,7 @@ if [ "$iOS" = "1" ]; then #Next append the client Public Cert echo "" - sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' < "issued/${NAME}${CRT}" + sed -n -e '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' < "issued/${NAME}${CRT}" echo "" #Finally, append the tls Private Key @@ -401,7 +405,7 @@ else #Next append the client Public Cert echo "" - sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' < "issued/${NAME}${CRT}" + sed -n -e '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' < "issued/${NAME}${CRT}" echo "" #Then, append the client Private Key diff --git a/scripts/openvpn/pivpn.sh b/scripts/openvpn/pivpn.sh index 1428c34..d8d64fd 100755 --- a/scripts/openvpn/pivpn.sh +++ b/scripts/openvpn/pivpn.sh @@ -1,8 +1,14 @@ #!/bin/bash +CHECK_PKG_INSTALLED='dpkg-query -s' + +if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then + CHECK_PKG_INSTALLED='apk --no-cache info -e' +fi + # Must be root to use this tool -if [[ ! $EUID -eq 0 ]];then - if [[ $(dpkg-query -s sudo) ]];then +if [[ ! $EUID -eq 0 ]]; then + if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then export SUDO="sudo" else echo "::: Please install sudo or run this as root." diff --git a/scripts/openvpn/pivpnDebug.sh b/scripts/openvpn/pivpnDebug.sh index aa53b58..35a39f1 100755 --- a/scripts/openvpn/pivpnDebug.sh +++ b/scripts/openvpn/pivpnDebug.sh @@ -37,16 +37,19 @@ printf "=============================================\n" echo -e ":::: Having trouble connecting? Take a look at the FAQ:" echo -e ":::: \e[1mhttps://docs.pivpn.io/faq\e[0m" printf "=============================================\n" -echo -e ":::: \e[4mSnippet of the server log\e[0m ::::" -OVPNLOG="$(tail -n 20 /var/log/openvpn.log)" -# Regular expession taken from https://superuser.com/a/202835, it will match invalid IPs -# like 123.456.789.012 but it's fine since the log only contains valid ones. -declare -a IPS_TO_HIDE=("$(grepcidr -v 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 <<< "$OVPNLOG" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | uniq)") -for IP in "${IPS_TO_HIDE[@]}"; do - OVPNLOG="${OVPNLOG//"$IP"/REDACTED}" -done +if [ "${PLAT}" != 'Alpine' ]; then + echo -e ":::: \e[4mSnippet of the server log\e[0m ::::" + OVPNLOG="$(tail -n 20 /var/log/openvpn.log)" -echo "$OVPNLOG" -printf "=============================================\n" + # Regular expession taken from https://superuser.com/a/202835, it will match invalid IPs + # like 123.456.789.012 but it's fine since the log only contains valid ones. + declare -a IPS_TO_HIDE=("$(grepcidr -v 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 <<< "$OVPNLOG" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | uniq)") + for IP in "${IPS_TO_HIDE[@]}"; do + OVPNLOG="${OVPNLOG//"$IP"/REDACTED}" + done + + echo "$OVPNLOG" + printf "=============================================\n" +fi echo -e "::::\t\t\e[4mDebug complete\e[0m\t\t ::::" diff --git a/scripts/openvpn/removeOVPN.sh b/scripts/openvpn/removeOVPN.sh index e67ab59..3c50398 100755 --- a/scripts/openvpn/removeOVPN.sh +++ b/scripts/openvpn/removeOVPN.sh @@ -25,8 +25,7 @@ helpFunc() { } # Parse input arguments -while test $# -gt 0 -do +while test $# -gt 0; do _key="$1" case "$_key" in -h|--help) diff --git a/scripts/pivpn b/scripts/pivpn index fa6256f..dd97763 100755 --- a/scripts/pivpn +++ b/scripts/pivpn @@ -1,8 +1,14 @@ #!/bin/bash +CHECK_PKG_INSTALLED='dpkg-query -s' + +if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then + CHECK_PKG_INSTALLED='apk --no-cache info -e' +fi + # Must be root to use this tool -if [ $EUID -ne 0 ];then - if dpkg-query -s sudo &> /dev/null; then +if [ $EUID -ne 0 ]; then + if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then export SUDO="sudo" else echo "::: Please install sudo or run this as root." diff --git a/scripts/self_check.sh b/scripts/self_check.sh index c29f664..bee00b9 100755 --- a/scripts/self_check.sh +++ b/scripts/self_check.sh @@ -1,5 +1,7 @@ #!/bin/bash +PLAT=$(grep -sEe '^NAME\=' /etc/os-release | sed -E -e "s/NAME\=[\'\"]?([^ ]*).*/\1/") + # dual protocol, VPN type supplied as $1 VPN=$1 setupVars="/etc/pivpn/${VPN}/setupVars.conf" @@ -16,6 +18,11 @@ source "${setupVars}" if [ "$VPN" = "wireguard" ]; then VPN_SERVICE="wg-quick@wg0" + + if [ "${PLAT}" == 'Alpine' ]; then + VPN_SERVICE='wg-quick' + fi + VPN_PRETTY_NAME="WireGuard" elif [ "$VPN" = "openvpn" ]; then VPN_SERVICE="openvpn" @@ -135,25 +142,54 @@ else fi -if systemctl is-active -q "${VPN_SERVICE}"; then - echo ":: [OK] ${VPN_PRETTY_NAME} is running" -else - ERR=1 - read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not running, try to start now? [Y/n] " REPLY - if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then - systemctl start "${VPN_SERVICE}" - echo "Done" - fi -fi +if [ "${PLAT}" == 'Alpine' ]; then + if [ "$(rc-service "${VPN_SERVICE}" status | sed -E -e 's/.*status\: (.*)/\1/')" == 'started' ]; then + echo ":: [OK] ${VPN_PRETTY_NAME} is running" + else + ERR=1 + read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not running, try to start now? [Y/n] " REPLY -if systemctl is-enabled -q "${VPN_SERVICE}"; then - echo ":: [OK] ${VPN_PRETTY_NAME} is enabled (it will automatically start on reboot)" + if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then + rc-service -s "${VPN_SERVICE}" restart + rc-service -N "${VPN_SERVICE}" start + + echo "Done" + fi + fi + + if rc-update show default | grep -sEe "\s*${VPN_SERVICE} .*" &> /dev/null; then + echo ":: [OK] ${VPN_PRETTY_NAME} is enabled (it will automatically start on reboot)" + else + ERR=1 + read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not enabled, try to enable now? [Y/n] " REPLY + + if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then + rc-update add "${VPN_SERVICE}" default + + echo "Done" + fi + fi else - ERR=1 - read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not enabled, try to enable now? [Y/n] " REPLY - if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then - systemctl enable "${VPN_SERVICE}" - echo "Done" + if systemctl is-active -q "${VPN_SERVICE}"; then + echo ":: [OK] ${VPN_PRETTY_NAME} is running" + else + ERR=1 + read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not running, try to start now? [Y/n] " REPLY + if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then + systemctl start "${VPN_SERVICE}" + echo "Done" + fi + fi + + if systemctl is-enabled -q "${VPN_SERVICE}"; then + echo ":: [OK] ${VPN_PRETTY_NAME} is enabled (it will automatically start on reboot)" + else + ERR=1 + read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not enabled, try to enable now? [Y/n] " REPLY + if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then + systemctl enable "${VPN_SERVICE}" + echo "Done" + fi fi fi @@ -163,8 +199,15 @@ if netstat -antu | grep -wqE "${pivpnPROTO}.*${pivpnPORT}"; then else ERR=1 read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not listening, try to restart now? [Y/n] " REPLY + if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then - systemctl restart "${VPN_SERVICE}" + if [ "${PLAT}" == 'Alpine' ]; then + rc-service -s "${VPN_SERVICE}" restart + rc-service -N "${VPN_SERVICE}" start + else + systemctl restart "${VPN_SERVICE}" + fi + echo "Done" fi fi diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh index 84acb5e..9c4c4d8 100755 --- a/scripts/uninstall.sh +++ b/scripts/uninstall.sh @@ -17,13 +17,22 @@ r=$(( r < 20 ? 20 : r )) c=$(( c < 70 ? 70 : c )) PKG_MANAGER="apt-get" -UPDATE_PKG_CACHE="${PKG_MANAGER} update" +PKG_REMOVE="${PKG_MANAGER} -y remove --purge" dnsmasqConfig="/etc/dnsmasq.d/02-pivpn.conf" setupVarsFile="setupVars.conf" setupConfigDir="/etc/pivpn" pivpnFilesDir="/usr/local/src/pivpn" pivpnScriptDir="/opt/pivpn" +PLAT=$(grep -sEe '^NAME\=' /etc/os-release | sed -E -e "s/NAME\=[\'\"]?([^ ]*).*/\1/") + +if [ "${PLAT}" == 'Alpine' ]; then + PKG_MANAGER='apk' + PKG_REMOVE="${PKG_MANAGER} --no-cache --purge del -r" +fi + +UPDATE_PKG_CACHE="${PKG_MANAGER} update" + if [ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ] && [ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]; then vpnStillExists=1 @@ -84,12 +93,22 @@ removeAll(){ # Stopping and disabling services echo "::: Stopping and disabling services..." - if [ "$VPN" = "wireguard" ]; then - systemctl stop wg-quick@wg0 - systemctl disable wg-quick@wg0 &> /dev/null - elif [ "$VPN" = "openvpn" ]; then - systemctl stop openvpn - systemctl disable openvpn &> /dev/null + if [ "${PLAT}" == 'Alpine' ]; then + if [ "${VPN}" = "wireguard" ]; then + rc-service wg-quick stop + rc-update del wg-quick default &> /dev/null + elif [ "${VPN}" = "openvpn" ]; then + rc-service openvpn stop + rc-update del openvpn default &> /dev/null + fi + else + if [ "${VPN}" = "wireguard" ]; then + systemctl stop wg-quick@wg0 + systemctl disable wg-quick@wg0 &> /dev/null + elif [ "${VPN}" = "openvpn" ]; then + systemctl stop openvpn + systemctl disable openvpn &> /dev/null + fi fi # Removing firewall rules. @@ -137,58 +156,85 @@ removeAll(){ while true; do read -rp "::: Do you wish to remove $i from your system? [Y/n]: " yn case $yn in - [Yy]* ) if [ "${i}" = "wireguard-tools" ]; then - + [Yy]* ) + if [ "${PLAT}" == 'Alpine' ]; then + if [ "${i}" == 'openvpn' ]; then + deluser openvpn + rm -f /etc/rsyslog.d/30-openvpn.conf /etc/logrotate.d/openvpn + fi + else + if [ "${i}" == "wireguard-tools" ]; then # The bullseye repo may not exist if wireguard was available at the # time of installation. if [ -f /etc/apt/sources.list.d/pivpn-bullseye-repo.list ]; then echo "::: Removing Debian Bullseye repo..." + rm -f /etc/apt/sources.list.d/pivpn-bullseye-repo.list rm -f /etc/apt/preferences.d/pivpn-limit-bullseye + echo "::: Updating package cache..." - ${UPDATE_PKG_CACHE} &> /dev/null & spinner $! + + ${UPDATE_PKG_CACHE} &> /dev/null & + spinner $! fi if [ -f /etc/systemd/system/wg-quick@.service.d/override.conf ]; then rm -f /etc/systemd/system/wg-quick@.service.d/override.conf fi - elif [ "${i}" = "unattended-upgrades" ]; then - - rm -rf /var/log/unattended-upgrades - rm -rf /etc/apt/apt.conf.d/*periodic + rm -rf /var/log/unattended-upgrades /etc/apt/apt.conf.d/*periodic rm -rf /etc/apt/apt.conf.d/*unattended-upgrades - elif [ "${i}" = "openvpn" ]; then - if [ -f /etc/apt/sources.list.d/pivpn-openvpn-repo.list ]; then echo "::: Removing OpenVPN software repo..." - rm -f /etc/apt/sources.list.d/pivpn-openvpn-repo.list - echo "::: Updating package cache..." - ${UPDATE_PKG_CACHE} &> /dev/null & spinner $! - fi - deluser openvpn - rm -f /etc/rsyslog.d/30-openvpn.conf - rm -f /etc/logrotate.d/openvpn + rm -f /etc/apt/sources.list.d/pivpn-openvpn-repo.list + + echo "::: Updating package cache..." + + ${UPDATE_PKG_CACHE} &> /dev/null & + spinner $! + fi + + deluser openvpn + rm -f /etc/rsyslog.d/30-openvpn.conf /etc/logrotate.d/openvpn fi - printf ":::\\tRemoving %s..." "$i"; $PKG_MANAGER -y remove --purge "$i" &> /dev/null & spinner $!; printf "done!\\n"; - break - ;; - [Nn]* ) printf ":::\\tSkipping %s\\n" "$i"; - break - ;; - * ) printf "::: You must answer yes or no!\\n";; + fi + + printf ":::\\tRemoving %s..." "$i" + + "${PKG_REMOVE}" "$i" &> /dev/null & + spinner $! + + printf "done!\\n"; + break + ;; + [Nn]* ) + printf ":::\\tSkipping %s\\n" "$i"; + break + ;; + * ) + printf "::: You must answer yes or no!\\n" + ;; esac done done - # Take care of any additional package cleaning - printf "::: Auto removing remaining dependencies..." - $PKG_MANAGER -y autoremove &> /dev/null & spinner $!; printf "done!\\n"; - printf "::: Auto cleaning remaining dependencies..." - $PKG_MANAGER -y autoclean &> /dev/null & spinner $!; printf "done!\\n"; + if [ "${PLAT}" != 'Alpine' ]; then + # Take care of any additional package cleaning + printf "::: Auto removing remaining dependencies..." + "${PKG_MANAGER}" -y autoremove &> /dev/null & + spinner $! + + printf "done!\\n"; + printf "::: Auto cleaning remaining dependencies..." + + "${PKG_MANAGER}" -y autoclean &> /dev/null & + spinner $! + + printf "done!\\n"; + fi if [ -f "$dnsmasqConfig" ]; then rm -f "$dnsmasqConfig" @@ -255,7 +301,7 @@ askreboot(){ if [[ ${REPLY} =~ ^[Yy]$ ]]; then printf "\\nRebooting system...\\n" sleep 3 - shutdown -r now + reboot fi } diff --git a/scripts/wireguard/bash-completion b/scripts/wireguard/bash-completion index c25a0ec..eda7a14 100644 --- a/scripts/wireguard/bash-completion +++ b/scripts/wireguard/bash-completion @@ -6,8 +6,7 @@ _pivpn() cur="${COMP_WORDS[COMP_CWORD]}" dashopts="-a -c -d -l -qr -r -h -u -up -bk -off -on" opts="add clients debug list qrcode remove help uninstall update backup (temp) off (temp) on" - if [ "${#COMP_WORDS[@]}" -eq 2 ] - then + if [ "${#COMP_WORDS[@]}" -eq 2 ]; then if [[ ${cur} == -* ]] ; then COMPREPLY=( "$(compgen -W "${dashopts}" -- "${cur}")" ) else diff --git a/scripts/wireguard/disableCONF.sh b/scripts/wireguard/disableCONF.sh index 9753e89..4fe5147 100755 --- a/scripts/wireguard/disableCONF.sh +++ b/scripts/wireguard/disableCONF.sh @@ -3,119 +3,126 @@ setupVars="/etc/pivpn/wireguard/setupVars.conf" if [ ! -f "${setupVars}" ]; then - echo "::: Missing setup vars file!" - exit 1 + echo "::: Missing setup vars file!" + exit 1 fi # shellcheck disable=SC1090 source "${setupVars}" helpFunc(){ - echo "::: Disable client conf profiles" - echo ":::" - echo "::: Usage: pivpn <-off|off> [-h|--help] [-v] [ ... [] ...] " - echo ":::" - echo "::: Commands:" - echo "::: [none] Interactive mode" - echo "::: Client" - echo "::: -y,--yes Disable client(s) without confirmation" - echo "::: -v Show disabled clients only" - echo "::: -h,--help Show this help dialog" + echo "::: Disable client conf profiles" + echo ":::" + echo "::: Usage: pivpn <-off|off> [-h|--help] [-v] [ ... [] ...] " + echo ":::" + echo "::: Commands:" + echo "::: [none] Interactive mode" + echo "::: Client" + echo "::: -y,--yes Disable client(s) without confirmation" + echo "::: -v Show disabled clients only" + echo "::: -h,--help Show this help dialog" } # Parse input arguments -while test $# -gt 0 -do - _key="$1" - case "$_key" in - -h|--help) - helpFunc - exit 0 - ;; - -y|--yes) - CONFIRM=true - ;; - -v) - DISPLAY_DISABLED=true - ;; +while test $# -gt 0; do + _key="$1" + case "$_key" in + -h|--help) + helpFunc + exit 0 + ;; + -y|--yes) + CONFIRM=true + ;; + -v) + DISPLAY_DISABLED=true + ;; *) - CLIENTS_TO_CHANGE+=("$1") - ;; - esac - shift + CLIENTS_TO_CHANGE+=("$1") + ;; + esac + shift done cd /etc/wireguard || exit if [ ! -s configs/clients.txt ]; then - echo "::: There are no clients to change" - exit 1 + echo "::: There are no clients to change" + exit 1 fi if [ "$DISPLAY_DISABLED" ]; then - grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//' - exit 1 + grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//' + exit 1 fi mapfile -t LIST < <(awk '{print $1}' configs/clients.txt) if [ "${#CLIENTS_TO_CHANGE[@]}" -eq 0 ]; then - echo -e "::\e[4m Client list \e[0m::" - len=${#LIST[@]} - COUNTER=1 - while [ $COUNTER -le "${len}" ]; do - printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER-1))]}" - ((COUNTER++)) - done + echo -e "::\e[4m Client list \e[0m::" + len=${#LIST[@]} + COUNTER=1 + while [ $COUNTER -le "${len}" ]; do + printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER-1))]}" + ((COUNTER++)) + done - read -r -p "Please enter the Index/Name of the Client to be removed from the list above: " CLIENTS_TO_CHANGE + read -r -p "Please enter the Index/Name of the Client to be removed from the list above: " CLIENTS_TO_CHANGE - if [ -z "${CLIENTS_TO_CHANGE}" ]; then - echo "::: You can not leave this blank!" - exit 1 - fi + if [ -z "${CLIENTS_TO_CHANGE}" ]; then + echo "::: You can not leave this blank!" + exit 1 + fi fi CHANGED_COUNT=0 for CLIENT_NAME in "${CLIENTS_TO_CHANGE[@]}"; do - re='^[0-9]+$' - if [[ ${CLIENT_NAME} =~ $re ]] ; then - CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]} - fi + re='^[0-9]+$' + if [[ ${CLIENT_NAME} =~ $re ]] ; then + CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]} + fi - if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then - echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist" - elif grep -q "#\[disabled\] ### begin ${CLIENT_NAME}" wg0.conf; then - echo -e "::: \e[1m${CLIENT_NAME}\e[0m is already disabled" - else - if [ -n "$CONFIRM" ]; then - REPLY="y" - else - read -r -p "Confirm you want to disable $CLIENT_NAME? [Y/n] " - fi + if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then + echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist" + elif grep -q "#\[disabled\] ### begin ${CLIENT_NAME}" wg0.conf; then + echo -e "::: \e[1m${CLIENT_NAME}\e[0m is already disabled" + else + if [ -n "$CONFIRM" ]; then + REPLY="y" + else + read -r -p "Confirm you want to disable $CLIENT_NAME? [Y/n] " + fi - if [[ $REPLY =~ ^[Yy]$ ]]; then + if [[ $REPLY =~ ^[Yy]$ ]]; then - # Disable the peer section from the server config - echo "${CLIENT_NAME}" - sed -e "/### begin ${CLIENT_NAME}/,/end ${CLIENT_NAME}/ s/^/#\[disabled\] /" -i wg0.conf - echo "::: Updated server config" + # Disable the peer section from the server config + echo "${CLIENT_NAME}" + sed -e "/### begin ${CLIENT_NAME}/,/end ${CLIENT_NAME}/ s/^/#\[disabled\] /" -i wg0.conf + echo "::: Updated server config" - ((CHANGED_COUNT++)) - echo "::: Successfully disabled ${CLIENT_NAME}" + ((CHANGED_COUNT++)) + echo "::: Successfully disabled ${CLIENT_NAME}" - fi - fi + fi + fi done # Restart WireGuard only if some clients were actually deleted if [ "${CHANGED_COUNT}" -gt 0 ]; then - if systemctl reload wg-quick@wg0; then - echo "::: WireGuard reloaded" - else - echo "::: Failed to reload WireGuard" - fi + if [ "${PLAT}" == 'Alpine' ]; then + if rc-service wg-quick restart; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi + else + if systemctl reload wg-quick@wg0; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi + fi fi diff --git a/scripts/wireguard/enableCONF.sh b/scripts/wireguard/enableCONF.sh index 8ba3d76..dbfd02a 100755 --- a/scripts/wireguard/enableCONF.sh +++ b/scripts/wireguard/enableCONF.sh @@ -3,115 +3,122 @@ setupVars="/etc/pivpn/wireguard/setupVars.conf" if [ ! -f "${setupVars}" ]; then - echo "::: Missing setup vars file!" - exit 1 + echo "::: Missing setup vars file!" + exit 1 fi # shellcheck disable=SC1090 source "${setupVars}" helpFunc(){ - echo "::: Enables client conf profiles" - echo ":::" - echo "::: Usage: pivpn <-on|on> [-h|--help] [-v] [ ... [] ...] " - echo ":::" - echo "::: Commands:" - echo "::: [none] Interactive mode" - echo "::: Client" - echo "::: -y,--yes Enable client(s) without confirmation" - echo "::: -v Show disabled clients only" - echo "::: -h,--help Show this help dialog" + echo "::: Enables client conf profiles" + echo ":::" + echo "::: Usage: pivpn <-on|on> [-h|--help] [-v] [ ... [] ...] " + echo ":::" + echo "::: Commands:" + echo "::: [none] Interactive mode" + echo "::: Client" + echo "::: -y,--yes Enable client(s) without confirmation" + echo "::: -v Show disabled clients only" + echo "::: -h,--help Show this help dialog" } # Parse input arguments -while test $# -gt 0 -do - _key="$1" - case "$_key" in - -h|--help) - helpFunc - exit 0 - ;; - -y|--yes) - CONFIRM=true - ;; - -v) - DISPLAY_DISABLED=true - ;; +while test $# -gt 0; do + _key="$1" + case "$_key" in + -h|--help) + helpFunc + exit 0 + ;; + -y|--yes) + CONFIRM=true + ;; + -v) + DISPLAY_DISABLED=true + ;; *) - CLIENTS_TO_CHANGE+=("$1") - ;; - esac - shift + CLIENTS_TO_CHANGE+=("$1") + ;; + esac + shift done cd /etc/wireguard || exit if [ ! -s configs/clients.txt ]; then - echo "::: There are no clients to change" - exit 1 + echo "::: There are no clients to change" + exit 1 fi if [ "$DISPLAY_DISABLED" ]; then - grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//' - exit 1 + grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//' + exit 1 fi mapfile -t LIST < <(awk '{print $1}' configs/clients.txt) if [ "${#CLIENTS_TO_CHANGE[@]}" -eq 0 ]; then - echo -e "::\e[4m Client list \e[0m::" - len=${#LIST[@]} - COUNTER=1 - while [ $COUNTER -le "${len}" ]; do - printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER-1))]}" - ((COUNTER++)) - done + echo -e "::\e[4m Client list \e[0m::" + len=${#LIST[@]} + COUNTER=1 + while [ $COUNTER -le "${len}" ]; do + printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER-1))]}" + ((COUNTER++)) + done - read -r -p "Please enter the Index/Name of the Client to be enabled from the list above: " CLIENTS_TO_CHANGE + read -r -p "Please enter the Index/Name of the Client to be enabled from the list above: " CLIENTS_TO_CHANGE - if [ -z "${CLIENTS_TO_CHANGE}" ]; then - echo "::: You can not leave this blank!" - exit 1 - fi + if [ -z "${CLIENTS_TO_CHANGE}" ]; then + echo "::: You can not leave this blank!" + exit 1 + fi fi CHANGED_COUNT=0 for CLIENT_NAME in "${CLIENTS_TO_CHANGE[@]}"; do - re='^[0-9]+$' - if [[ ${CLIENT_NAME} =~ $re ]] ; then - CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]} - fi + re='^[0-9]+$' + if [[ ${CLIENT_NAME} =~ $re ]] ; then + CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]} + fi - if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then - echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist" - else - if [ -n "$CONFIRM" ]; then - REPLY="y" - else - read -r -p "Confirm you want to enable $CLIENT_NAME? [Y/n] " - fi + if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then + echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist" + else + if [ -n "$CONFIRM" ]; then + REPLY="y" + else + read -r -p "Confirm you want to enable $CLIENT_NAME? [Y/n] " + fi - if [[ $REPLY =~ ^[Yy]$ ]]; then + if [[ $REPLY =~ ^[Yy]$ ]]; then - # Enable the peer section from the server config - echo "${CLIENT_NAME}" - sed -e "/begin ${CLIENT_NAME}/,/end ${CLIENT_NAME}/ s/#\[disabled\] //" -i wg0.conf - echo "::: Updated server config" + # Enable the peer section from the server config + echo "${CLIENT_NAME}" + sed -e "/begin ${CLIENT_NAME}/,/end ${CLIENT_NAME}/ s/#\[disabled\] //" -i wg0.conf + echo "::: Updated server config" - ((CHANGED_COUNT++)) - echo "::: Successfully enabled ${CLIENT_NAME}" + ((CHANGED_COUNT++)) + echo "::: Successfully enabled ${CLIENT_NAME}" - fi - fi + fi + fi done # Restart WireGuard only if some clients were actually deleted if [ "${CHANGED_COUNT}" -gt 0 ]; then - if systemctl reload wg-quick@wg0; then - echo "::: WireGuard reloaded" - else - echo "::: Failed to reload WireGuard" - fi + if [ "${PLAT}" == 'Alpine' ]; then + if rc-service wg-quick restart; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi + else + if systemctl reload wg-quick@wg0; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi + fi fi diff --git a/scripts/wireguard/makeCONF.sh b/scripts/wireguard/makeCONF.sh index b5bc61f..25f5ee0 100755 --- a/scripts/wireguard/makeCONF.sh +++ b/scripts/wireguard/makeCONF.sh @@ -171,10 +171,18 @@ if [ -f /etc/pivpn/hosts.wireguard ]; then fi fi -if systemctl reload wg-quick@wg0; then - echo "::: WireGuard reloaded" +if [ "${PLAT}" == 'Alpine' ]; then + if rc-service wg-quick restart; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi else - echo "::: Failed to reload WireGuard" + if systemctl reload wg-quick@wg0; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi fi cp "configs/${CLIENT_NAME}.conf" "${install_home}/configs/${CLIENT_NAME}.conf" diff --git a/scripts/wireguard/pivpn.sh b/scripts/wireguard/pivpn.sh index 623c79b..27a5138 100755 --- a/scripts/wireguard/pivpn.sh +++ b/scripts/wireguard/pivpn.sh @@ -1,8 +1,14 @@ #!/bin/bash +CHECK_PKG_INSTALLED='dpkg-query -s' + +if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then + CHECK_PKG_INSTALLED='apk --no-cache info -e' +fi + # Must be root to use this tool -if [ $EUID -ne 0 ];then - if dpkg-query -s sudo &> /dev/null; then +if [ $EUID -ne 0 ]; then + if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then export SUDO="sudo" else echo "::: Please install sudo or run this as root." diff --git a/scripts/wireguard/qrcodeCONF.sh b/scripts/wireguard/qrcodeCONF.sh index a1600f8..8f707f5 100755 --- a/scripts/wireguard/qrcodeCONF.sh +++ b/scripts/wireguard/qrcodeCONF.sh @@ -15,8 +15,7 @@ helpFunc(){ # Parse input arguments encoding="ansiutf8" -while test $# -gt 0 -do +while test $# -gt 0; do _key="$1" case "$_key" in -h|--help) @@ -65,7 +64,7 @@ for CLIENT_NAME in "${CLIENTS_TO_SHOW[@]}"; do exit 1 elif [[ ${CLIENT_NAME} =~ $re ]] ; then CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]} - fi + fi if grep -qw "${CLIENT_NAME}" clients.txt; then echo -e "::: Showing client \e[1m${CLIENT_NAME}\e[0m below" echo "=====================================================================" diff --git a/scripts/wireguard/removeCONF.sh b/scripts/wireguard/removeCONF.sh index 6b71efb..ad1af7c 100755 --- a/scripts/wireguard/removeCONF.sh +++ b/scripts/wireguard/removeCONF.sh @@ -144,9 +144,17 @@ done # Restart WireGuard only if some clients were actually deleted if [ "${DELETED_COUNT}" -gt 0 ]; then - if systemctl reload wg-quick@wg0; then - echo "::: WireGuard reloaded" + if [ "${PLAT}" == 'Alpine' ]; then + if rc-service wg-quick restart; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi else - echo "::: Failed to reload WireGuard" + if systemctl reload wg-quick@wg0; then + echo "::: WireGuard reloaded" + else + echo "::: Failed to reload WireGuard" + fi fi fi