pivpn/scripts/uninstall.sh
2022-08-01 22:38:19 +02:00

418 lines
11 KiB
Bash
Executable file

#!/bin/bash
# PiVPN: Uninstall Script
### FIXME:
### global: config storage, refactor all scripts to adhere to the storage
### FIXME:
### use variables where appropriate, reduce magic numbers by 99.9%, at least.
# Find the rows and columns. Will default to 80x24 if it can not be detected.
screen_size="$(stty size 2> /dev/null || echo 24 80)"
rows="$(echo "${screen_size}" | awk '{print $1}')"
columns="$(echo "${screen_size}" | awk '{print $2}')"
# Divide by two so the dialogs take up half of the screen, which looks nice.
r=$((rows / 2))
c=$((columns / 2))
# Unless the screen is tiny
r=$((r < 20 ? 20 : r))
c=$((c < 70 ? 70 : c))
PKG_MANAGER="apt-get"
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
# Two protocols have been installed, check if the script has passed
# an argument, otherwise ask the user which one he wants to remove
if [[ "$#" -ge 1 ]]; then
VPN="${1}"
echo "::: Uninstalling VPN: ${VPN}"
else
chooseVPNCmd=(whiptail
--backtitle "Setup PiVPN"
--title "Uninstall"
--separate-output
--radiolist "Both OpenVPN and WireGuard are installed, \
choose a VPN to uninstall (press space to select):"
"${r}" "${c}" 2)
VPNChooseOptions=(WireGuard "" on
OpenVPN "" off)
if VPN="$("${chooseVPNCmd[@]}" "${VPNChooseOptions[@]}" 2>&1 \
> /dev/tty)"; then
echo "::: Uninstalling VPN: ${VPN}"
VPN="${VPN,,}"
else
err "::: Cancel selected, exiting...."
exit 1
fi
fi
setupVars="${setupConfigDir}/${VPN}/${setupVarsFile}"
else
vpnStillExists=0
if [[ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]]; then
setupVars="${setupConfigDir}/wireguard/${setupVarsFile}"
elif [[ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]]; then
setupVars="${setupConfigDir}/openvpn/${setupVarsFile}"
fi
fi
if [[ ! -f "${setupVars}" ]]; then
err "::: Missing setup vars file!"
exit 1
fi
# shellcheck disable=SC1090
source "${setupVars}"
err() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}
### FIXME: introduce global lib
spinner() {
local pid="${1}"
local delay=0.50
local spinstr='/-\|'
while ps a | awk '{print $1}' | grep -q "${pid}"; do
local temp="${spinstr#?}"
printf " [%c] " "${spinstr}"
local spinstr="${temp}${spinstr%"$temp"}"
sleep "${delay}"
printf "\\b\\b\\b\\b\\b\\b"
done
printf " \\b\\b\\b\\b"
}
removeAll() {
# Stopping and disabling services
echo "::: Stopping and disabling services..."
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.
echo "::: Removing firewall rules..."
if [[ "${USING_UFW}" -eq 1 ]]; then
### Ignoring SC2154, value sourced from setupVars file
# shellcheck disable=SC2154
ufw delete allow "${pivpnPORT}/${pivpnPROTO}" > /dev/null
### Ignoring SC2154, value sourced from setupVars file
# shellcheck disable=SC2154
ufw route delete allow in on "${pivpnDEV}" \
from "${pivpnNET}/${subnetClass}" out on "${IPv4dev}" to any > /dev/null
ufw delete allow in on "${pivpnDEV}" to any port 53 \
from "${pivpnNET}/${subnetClass}" > /dev/null
sed_pattern='/-I POSTROUTING'
sed_pattern="${sed_pattern} -s ${pivpnNET}\\/${subnetClass}"
sed_pattern="${sed_pattern} -o ${IPv4dev}"
sed_pattern="${sed_pattern} -j MASQUERADE"
sed_pattern="${sed_pattern} -m comment"
sed_pattern="${sed_pattern} --comment ${VPN}-nat-rule/d"
sed "${sed_pattern}" -i /etc/ufw/before.rules
unset sed_pattern
iptables \
-t nat \
-D POSTROUTING \
-s "${pivpnNET}/${subnetClass}" \
-o "${IPv4dev}" \
-j MASQUERADE \
-m comment \
--comment "${VPN}-nat-rule"
ufw reload &> /dev/null
elif [[ "${USING_UFW}" -eq 0 ]]; then
if [[ "${INPUT_CHAIN_EDITED}" -eq 1 ]]; then
iptables \
-D INPUT \
-i "${IPv4dev}" \
-p "${pivpnPROTO}" \
--dport "${pivpnPORT}" \
-j ACCEPT \
-m comment \
--comment "${VPN}-input-rule"
fi
if [[ "${FORWARD_CHAIN_EDITED}" -eq 1 ]]; then
iptables \
-D FORWARD \
-d "${pivpnNET}/${subnetClass}" \
-i "${IPv4dev}" \
-o "${pivpnDEV}" \
-m conntrack \
--ctstate RELATED,ESTABLISHED \
-j ACCEPT \
-m comment \
--comment "${VPN}-forward-rule"
iptables \
-D FORWARD \
-s "${pivpnNET}/${subnetClass}" \
-i "${pivpnDEV}" \
-o "${IPv4dev}" \
-j ACCEPT \
-m comment \
--comment "${VPN}-forward-rule"
fi
iptables \
-t nat \
-D POSTROUTING \
-s "${pivpnNET}/${subnetClass}" \
-o "${IPv4dev}" \
-j MASQUERADE \
-m comment \
--comment "${VPN}-nat-rule"
iptables-save > /etc/iptables/rules.v4
fi
# Disable IPv4 forwarding
if [[ "${vpnStillExists}" -eq 0 ]]; then
sed -i '/net.ipv4.ip_forward=1/c\#net.ipv4.ip_forward=1' /etc/sysctl.conf
sysctl -p
fi
# Purge dependencies
echo "::: Purge dependencies..."
for i in "${INSTALLED_PACKAGES[@]}"; do
while true; do
read -rp "::: Do you wish to remove ${i} from your system? [Y/n]: " yn
case "${yn}" in
[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.
tmp_path='/etc/apt/sources.list.d/pivpn-bullseye-repo.list'
if [[ -f "${tmp_path}" ]]; then
echo "::: Removing Debian Bullseye repo..."
rm -f "${tmp_path}"
rm -f /etc/apt/preferences.d/pivpn-limit-bullseye
echo "::: Updating package cache..."
${UPDATE_PKG_CACHE} &> /dev/null &
spinner "$!"
fi
tmp_path='/etc/systemd/system/wg-quick@.service.d/override.conf'
if [[ -f "${tmp_path}" ]]; then
rm -f "${tmp_path}"
fi
unset tmp_path
elif [[ "${i}" == "unattended-upgrades" ]]; then
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 /etc/logrotate.d/openvpn
fi
fi
printf ":::\\tRemoving %s..." "${i}"
${PKG_REMOVE} "${i}" &> /dev/null &
spinner "$!"
printf "done!\\n"
break
;;
[Nn]*)
printf ":::\\tSkipping %s\\n" "${i}"
break
;;
*)
err "::: You must answer yes or no!"
;;
esac
done
done
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}"
pihole restartdns
fi
echo ":::"
echo "::: Removing VPN configuration files..."
if [[ "${VPN}" == "wireguard" ]]; then
rm -f /etc/wireguard/wg0.conf
rm -rf /etc/wireguard/configs
rm -rf /etc/wireguard/keys
### Ignoring SC2154, value sourced from setupVars file
# shellcheck disable=SC2154
rm -rf "${install_home}/configs"
elif [[ "${VPN}" == "openvpn" ]]; then
rm -rf /var/log/*openvpn*
rm -f /etc/openvpn/server.conf
rm -f /etc/openvpn/crl.pem
rm -rf /etc/openvpn/easy-rsa
rm -rf /etc/openvpn/ccd
rm -rf "${install_home}/ovpns"
fi
if [[ "${vpnStillExists}" -eq 0 ]]; then
echo ":::"
echo "::: Removing pivpn system files..."
rm -rf "${setupConfigDir}"
rm -rf "${pivpnFilesDir}"
rm -f /var/log/*pivpn*
rm -f /etc/bash_completion.d/pivpn
unlink "${pivpnScriptDir}"
unlink /usr/local/bin/pivpn
else
if [[ "${VPN}" == 'wireguard' ]]; then
othervpn='openvpn'
else
othervpn='wireguard'
fi
echo ":::"
echo "::: Other VPN ${othervpn} still present, so not"
echo "::: removing pivpn system files"
rm -f "${setupConfigDir}/${VPN}/${setupVarsFile}"
# Restore single pivpn script and bash completion for the remaining VPN
${SUDO} unlink /usr/local/bin/pivpn
${SUDO} ln \
-s \
-T "${pivpnFilesDir}/scripts/${othervpn}/pivpn.sh" \
/usr/local/bin/pivpn
${SUDO} ln \
-s \
-T "${pivpnFilesDir}/scripts/${othervpn}/bash-completion" \
/etc/bash_completion.d/pivpn
# shellcheck disable=SC1091
. /etc/bash_completion.d/pivpn
fi
echo ":::"
printf "::: Finished removing PiVPN from your system.\\n"
printf "::: Reinstall by simply running\\n:::\\n:::\\t"
printf "curl -L https://install.pivpn.io | "
printf "bash\\n:::\\n::: at any time!\\n:::\\n"
}
askreboot() {
printf "It is \\e[1mstrongly\\e[0m recommended to reboot "
printf "after un-installation.\\n"
read -p "Would you like to reboot now? [y/n]: " -n 1 -r
echo
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
printf "\\nRebooting system...\\n"
sleep 3
reboot
fi
}
######### SCRIPT ###########
echo -n "::: Preparing to remove packages, be sure that each may be safely "
echo "removed depending on your operating system."
echo "::: (SAFE TO REMOVE ALL ON RASPBIAN)"
while true; do
echo -n "::: Do you wish to completely remove PiVPN configuration and "
echo -n "installed packages from your system? "
echo -n "(You will be prompted for each package) [y/n]: "
read -r yn
case "${yn}" in
[Yy]*)
removeAll
askreboot
break
;;
[Nn]*)
err "::: Not removing anything, exiting..."
break
;;
esac
done