mirror of
https://github.com/pivpn/pivpn.git
synced 2024-12-18 10:50:16 +00:00
Merge pull request #1572 from giulio-coa/formatting_enhancements
Reformatted the code according to google bash code style.
This commit is contained in:
commit
f59c693ba6
27 changed files with 5861 additions and 4353 deletions
26
.travis.yml
26
.travis.yml
|
@ -3,15 +3,13 @@ language: shell
|
||||||
addons:
|
addons:
|
||||||
hosts:
|
hosts:
|
||||||
- pivpn.test
|
- pivpn.test
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- shellcheck
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- lint
|
- lint
|
||||||
|
- style
|
||||||
- test
|
- test
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
|
@ -24,11 +22,29 @@ jobs:
|
||||||
- stage: lint
|
- stage: lint
|
||||||
name: "Shellcheck lint"
|
name: "Shellcheck lint"
|
||||||
dist: focal
|
dist: focal
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- shellcheck
|
||||||
virt: vm
|
virt: vm
|
||||||
arch: amd64
|
arch: amd64
|
||||||
script:
|
script:
|
||||||
- shellcheck auto_install/install.sh
|
- shellcheck -x auto_install/install.sh
|
||||||
- find scripts/ -type f | xargs shellcheck
|
- find ciscripts/ -type f -regex '.*\.sh' -exec shellcheck -x {} \;
|
||||||
|
- find scripts/ -type f -exec shellcheck -x {} \;
|
||||||
|
|
||||||
|
- stage: style
|
||||||
|
name: "Shell Style Guide"
|
||||||
|
dist: xenial
|
||||||
|
addons:
|
||||||
|
snaps:
|
||||||
|
- shfmt
|
||||||
|
virt: vm
|
||||||
|
arch: amd64
|
||||||
|
script:
|
||||||
|
- shfmt -d -i 2 -ci -sr -bn auto_install/install.sh
|
||||||
|
- find ciscripts/ -type f -regex '.*\.sh' -exec shfmt -d -i 2 -ci -sr -bn {} \;
|
||||||
|
- find scripts/ -type f -exec shfmt -d -i 2 -ci -sr -bn {} \;
|
||||||
|
|
||||||
- stage: test
|
- stage: test
|
||||||
name: "OpenVPN Xenial & Commands"
|
name: "OpenVPN Xenial & Commands"
|
||||||
|
|
|
@ -22,6 +22,11 @@ Please report unacceptable behavior to any project maintainer.
|
||||||
|
|
||||||
* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
|
* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
|
||||||
|
|
||||||
|
* Use the following [commit rules](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-format).
|
||||||
|
|
||||||
|
* Use the following [code style rules](https://google.github.io/styleguide/shellguide.html).
|
||||||
|
We suggest you to use `shfmt` with the options `-i 2 -ci -sr -w -bn`
|
||||||
|
|
||||||
### **PiVPN Website**
|
### **PiVPN Website**
|
||||||
|
|
||||||
* Yes the site is open source as well! You can find and contribute to [pivpn.io](https://github.com/pivpn/pivpn.io) directly.
|
* Yes the site is open source as well! You can find and contribute to [pivpn.io](https://github.com/pivpn/pivpn.io) directly.
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,47 +1,62 @@
|
||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
interface=$(ip -o link | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1 | grep -v -w 'lo' | head -1)
|
interface=$(ip -o link \
|
||||||
ipaddress=$(ip addr show "$interface" | grep -o -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}/[0-9]{2}")
|
| awk '{print $2}' \
|
||||||
|
| cut -d ':' -f 1 \
|
||||||
|
| cut -d '@' -f 1 \
|
||||||
|
| grep -v -w 'lo' \
|
||||||
|
| head -1)
|
||||||
|
ipaddress=$(ip addr show "${interface}" \
|
||||||
|
| grep -o -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}/[0-9]{2}")
|
||||||
gateway=$(ip route show | awk '/default/ {print $3}')
|
gateway=$(ip route show | awk '/default/ {print $3}')
|
||||||
hostname="pivpn.test"
|
hostname="pivpn.test"
|
||||||
|
|
||||||
common(){
|
err() {
|
||||||
sed -i "s/INTERFACE/$interface/g" "$vpnconfig"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
sed -i "s|IPADDRESS|$ipaddress|g" "$vpnconfig"
|
|
||||||
sed -i "s/GATEWAY/$gateway/g" "$vpnconfig"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
openvpn(){
|
common() {
|
||||||
vpnconfig="ciscripts/ci_openvpn.conf"
|
sed -i "s/INTERFACE/${interface}/g" "${vpnconfig}"
|
||||||
twofour=1
|
sed -i "s|IPADDRESS|${ipaddress}|g" "${vpnconfig}"
|
||||||
common
|
sed -i "s/GATEWAY/${gateway}/g" "${vpnconfig}"
|
||||||
sed -i "s/2POINT4/$twofour/g" "$vpnconfig"
|
|
||||||
cat $vpnconfig
|
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wireguard(){
|
openvpn() {
|
||||||
vpnconfig="ciscripts/ci_wireguard.conf"
|
vpnconfig="ciscripts/ci_openvpn.conf"
|
||||||
common
|
twofour=1
|
||||||
cat $vpnconfig
|
common
|
||||||
exit 0
|
sed -i "s/2POINT4/${twofour}/g" "${vpnconfig}"
|
||||||
|
cat "${vpnconfig}"
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ $# -lt 1 ]; then
|
wireguard() {
|
||||||
echo "specifiy a VPN protocol to prepare"
|
vpnconfig="ciscripts/ci_wireguard.conf"
|
||||||
exit 1
|
common
|
||||||
|
cat "${vpnconfig}"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$#" -lt 1 ]]; then
|
||||||
|
err "specifiy a VPN protocol to prepare"
|
||||||
|
exit 1
|
||||||
else
|
else
|
||||||
chmod +x auto_install/install.sh
|
chmod +x auto_install/install.sh
|
||||||
sudo hostnamectl set-hostname $hostname
|
sudo hostnamectl set-hostname "${hostname}"
|
||||||
cat /etc/os-release
|
cat /etc/os-release
|
||||||
while true; do
|
|
||||||
case "$1" in
|
while true; do
|
||||||
-o | --openvpn ) openvpn
|
case "${1}" in
|
||||||
;;
|
-o | --openvpn)
|
||||||
-w | --wireguard ) wireguard
|
openvpn
|
||||||
;;
|
;;
|
||||||
* ) echo "unknown vpn protocol"; exit 1
|
-w | --wireguard)
|
||||||
;;
|
wireguard
|
||||||
esac
|
;;
|
||||||
done
|
*)
|
||||||
|
err "unknown vpn protocol"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if command -v systemctl > /dev/null; then
|
if command -v systemctl > /dev/null; then
|
||||||
systemctl status openvpn
|
systemctl status openvpn
|
||||||
elif command -v rc-service > /dev/null; then
|
elif command -v rc-service > /dev/null; then
|
||||||
rc-service openvpn status
|
rc-service openvpn status
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pivpn add -n foo
|
pivpn add -n foo
|
||||||
pivpn -qr foo
|
pivpn -qr foo
|
||||||
pivpn -bk
|
pivpn -bk
|
||||||
|
|
|
@ -2,111 +2,125 @@
|
||||||
# PiVPN: Backup Script
|
# PiVPN: Backup Script
|
||||||
|
|
||||||
# Find the rows and columns. Will default to 80x24 if it can not be detected.
|
# 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)
|
screen_size="$(stty size 2> /dev/null || echo 24 80)"
|
||||||
rows=$(echo "$screen_size" | awk '{print $1}')
|
rows="$(echo "${screen_size}" | awk '{print $1}')"
|
||||||
columns=$(echo "$screen_size" | awk '{print $2}')
|
columns="$(echo "${screen_size}" | awk '{print $2}')"
|
||||||
|
|
||||||
# Divide by two so the dialogs take up half of the screen, which looks nice.
|
# Divide by two so the dialogs take up half of the screen, which looks nice.
|
||||||
r=$(( rows / 2 ))
|
r=$((rows / 2))
|
||||||
c=$(( columns / 2 ))
|
c=$((columns / 2))
|
||||||
# Unless the screen is tiny
|
# Unless the screen is tiny
|
||||||
r=$(( r < 20 ? 20 : r ))
|
r=$((r < 20 ? 20 : r))
|
||||||
c=$(( c < 70 ? 70 : c ))
|
c=$((c < 70 ? 70 : c))
|
||||||
|
|
||||||
backupdir=pivpnbackup
|
backupdir=pivpnbackup
|
||||||
date=$(date +%Y%m%d-%H%M%S)
|
date="$(date +%Y%m%d-%H%M%S)"
|
||||||
setupVarsFile="setupVars.conf"
|
setupVarsFile="setupVars.conf"
|
||||||
setupConfigDir="/etc/pivpn"
|
setupConfigDir="/etc/pivpn"
|
||||||
|
|
||||||
CHECK_PKG_INSTALLED='dpkg-query -s'
|
CHECK_PKG_INSTALLED='dpkg-query -s'
|
||||||
|
|
||||||
if [ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ] && [ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]; then
|
if [[ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]] \
|
||||||
|
&& [[ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]]; then
|
||||||
|
# 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 "::: Backing up VPN: ${VPN}"
|
||||||
|
else
|
||||||
|
chooseVPNCmd=(whiptail
|
||||||
|
--backtitle "Setup PiVPN"
|
||||||
|
--title "Backup"
|
||||||
|
--separate-output
|
||||||
|
--radiolist "Both OpenVPN and WireGuard are installed, choose a VPN to \
|
||||||
|
backup (press space to select):"
|
||||||
|
"${r}" "${c}" 2)
|
||||||
|
VPNChooseOptions=(WireGuard "" on
|
||||||
|
OpenVPN "" off)
|
||||||
|
|
||||||
# Two protocols have been installed, check if the script has passed
|
if VPN="$("${chooseVPNCmd[@]}" "${VPNChooseOptions[@]}" 2>&1 \
|
||||||
# an argument, otherwise ask the user which one he wants to remove
|
> /dev/tty)"; then
|
||||||
if [ $# -ge 1 ]; then
|
echo "::: Backing up VPN: ${VPN}"
|
||||||
VPN="$1"
|
VPN="${VPN,,}"
|
||||||
echo "::: Backing up VPN: $VPN"
|
else
|
||||||
else
|
err "::: Cancel selected, exiting...."
|
||||||
chooseVPNCmd=(whiptail --backtitle "Setup PiVPN" --title "Backup" --separate-output --radiolist "Both OpenVPN and WireGuard are installed, choose a VPN to backup (press space to select):" "${r}" "${c}" 2)
|
exit 1
|
||||||
VPNChooseOptions=(WireGuard "" on
|
fi
|
||||||
OpenVPN "" off)
|
fi
|
||||||
|
|
||||||
if VPN=$("${chooseVPNCmd[@]}" "${VPNChooseOptions[@]}" 2>&1 >/dev/tty) ; then
|
setupVars="${setupConfigDir}/${VPN}/${setupVarsFile}"
|
||||||
echo "::: Backing up VPN: $VPN"
|
|
||||||
VPN="${VPN,,}"
|
|
||||||
else
|
|
||||||
echo "::: Cancel selected, exiting...."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
setupVars="${setupConfigDir}/${VPN}/${setupVarsFile}"
|
|
||||||
else
|
else
|
||||||
|
if [[ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]]; then
|
||||||
if [ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]; then
|
setupVars="${setupConfigDir}/wireguard/${setupVarsFile}"
|
||||||
setupVars="${setupConfigDir}/wireguard/${setupVarsFile}"
|
elif [[ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]]; then
|
||||||
elif [ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]; then
|
setupVars="${setupConfigDir}/openvpn/${setupVarsFile}"
|
||||||
setupVars="${setupConfigDir}/openvpn/${setupVarsFile}"
|
fi
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
checkbackupdir(){
|
err() {
|
||||||
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
# Disabling shellcheck error $install_home sourced from $setupVars
|
|
||||||
# shellcheck disable=SC2154
|
|
||||||
if [[ ! -d $install_home/$backupdir ]]; then
|
|
||||||
mkdir -p "$install_home"/"$backupdir"
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backup_openvpn(){
|
checkbackupdir() {
|
||||||
|
# Disabling shellcheck error $install_home sourced from $setupVars
|
||||||
openvpndir=/etc/openvpn
|
# shellcheck disable=SC2154
|
||||||
ovpnsdir=${install_home}/ovpns
|
mkdir -p "${install_home}/${backupdir}"
|
||||||
checkbackupdir
|
|
||||||
backupzip=$date-pivpnovpnbackup.tgz
|
|
||||||
# shellcheck disable=SC2210
|
|
||||||
tar czpf "$install_home"/"$backupdir"/"$backupzip" "$openvpndir" "$ovpnsdir" > /dev/null 2>&1
|
|
||||||
echo -e "Backup created in $install_home/$backupdir/$backupzip \nTo restore the backup, follow instructions at:\nhttps://docs.pivpn.io/openvpn/#migrating-pivpn-openvpn\n"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backup_wireguard(){
|
backup_openvpn() {
|
||||||
|
openvpndir=/etc/openvpn
|
||||||
|
ovpnsdir="${install_home}/ovpns"
|
||||||
|
backupzip="${date}-pivpnovpnbackup.tgz"
|
||||||
|
|
||||||
wireguarddir=/etc/wireguard
|
checkbackupdir
|
||||||
configsdir=${install_home}/configs
|
# shellcheck disable=SC2210
|
||||||
checkbackupdir
|
tar czpf "${install_home}/${backupdir}/${backupzip}" "${openvpndir}" \
|
||||||
backupzip=$date-pivpnwgbackup.tgz
|
"${ovpnsdir}" > /dev/null 2>&1
|
||||||
tar czpf "$install_home"/"$backupdir"/"$backupzip" "$wireguarddir" "$configsdir" > /dev/null 2>&1
|
|
||||||
echo -e "Backup created in $install_home/$backupdir/$backupzip \nTo restore the backup, follow instructions at:\nhttps://docs.pivpn.io/wireguard/#migrating-pivpn-wireguard\n"
|
|
||||||
|
|
||||||
|
echo -e "Backup created in ${install_home}/${backupdir}/${backupzip} "
|
||||||
|
echo -e "To restore the backup, follow instructions at:"
|
||||||
|
echo -ne "https://docs.pivpn.io/openvpn/"
|
||||||
|
echo -e "#migrating-pivpn-openvpn"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ ! $EUID -eq 0 ]]; then
|
backup_wireguard() {
|
||||||
if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then
|
wireguarddir=/etc/wireguard
|
||||||
export SUDO="sudo"
|
configsdir="${install_home}/configs"
|
||||||
else
|
backupzip="${date}-pivpnwgbackup.tgz"
|
||||||
echo "::: Please install sudo or run this as root."
|
|
||||||
|
checkbackupdir
|
||||||
|
tar czpf "${install_home}/${backupdir}/${backupzip}" "${wireguarddir}" \
|
||||||
|
"${configsdir}" > /dev/null 2>&1
|
||||||
|
|
||||||
|
echo -e "Backup created in ${install_home}/${backupdir}/${backupzip} "
|
||||||
|
echo -e "To restore the backup, follow instructions at:"
|
||||||
|
echo -ne "https://docs.pivpn.io/openvpn/"
|
||||||
|
echo -e "wireguard/#migrating-pivpn-wireguard"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${EUID}" -ne 0 ]]; then
|
||||||
|
if ${CHECK_PKG_INSTALLED} sudo &> /dev/null; then
|
||||||
|
export SUDO="sudo"
|
||||||
|
else
|
||||||
|
err "::: Please install sudo or run this as root."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${VPN}" == "wireguard" ]]; then
|
if [[ "${VPN}" == "wireguard" ]]; then
|
||||||
backup_wireguard
|
backup_wireguard
|
||||||
else
|
else
|
||||||
backup_openvpn
|
backup_openvpn
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,21 +1,25 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
_pivpn()
|
|
||||||
{
|
_pivpn() {
|
||||||
local cur prev opts
|
local cur prev opts
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
prev="${COMP_WORDS[COMP_CWORD - 1]}"
|
||||||
dashopts="-a -c -d -l -r -h -u -up -bk"
|
dashopts="-a -c -d -l -r -h -u -up -bk"
|
||||||
opts="debug add clients list revoke uninstall help update backup"
|
opts="debug add clients list revoke uninstall help update backup"
|
||||||
if [ "${#COMP_WORDS[@]}" -eq 2 ]; then
|
|
||||||
if [[ ${cur} == -* ]] ; then
|
if [[ "${#COMP_WORDS[@]}" -eq 2 ]]; then
|
||||||
COMPREPLY=( "$(compgen -W "${dashopts}" -- "${cur}")" )
|
if [[ "${cur}" == -* ]]; then
|
||||||
else
|
COMPREPLY=("$(compgen -W "${dashopts}" -- "${cur}")")
|
||||||
COMPREPLY=( "$(compgen -W "${opts}" -- "${cur}")" )
|
else
|
||||||
fi
|
COMPREPLY=("$(compgen -W "${opts}" -- "${cur}")")
|
||||||
elif [[ ( "$prev" == "add" || "$prev" == "-a" ) && "${#COMP_WORDS[@]}" -eq 3 ]]; then
|
|
||||||
COMPREPLY=( "$(compgen -W "nopass" -- "${cur}")" )
|
|
||||||
fi
|
fi
|
||||||
return 0
|
elif [[ ("${prev}" == "add" || "${prev}" == "-a") ]] \
|
||||||
|
&& [[ "${#COMP_WORDS[@]}" -eq 3 ]]; then
|
||||||
|
COMPREPLY=("$(compgen -W "nopass" -- "${cur}")")
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
complete -F _pivpn pivpn
|
complete -F _pivpn pivpn
|
||||||
|
|
|
@ -1,84 +1,97 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
# PiVPN: client status script
|
# PiVPN: client status script
|
||||||
|
|
||||||
STATUS_LOG="/var/log/openvpn-status.log"
|
STATUS_LOG="/var/log/openvpn-status.log"
|
||||||
|
|
||||||
if [ ! -f "${STATUS_LOG}" ]; then
|
if [[ ! -f "${STATUS_LOG}" ]]; then
|
||||||
echo "The file: $STATUS_LOG was not found!"
|
err "The file: ${STATUS_LOG} was not found!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
scriptusage(){
|
err() {
|
||||||
echo "::: List any connected clients to the server"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
|
||||||
echo "::: Usage: pivpn <-c|clients> [-b|bytes]"
|
|
||||||
echo ":::"
|
|
||||||
echo "::: Commands:"
|
|
||||||
echo "::: [none] List clients with human readable format"
|
|
||||||
echo "::: -b, bytes List clients with dotted decimal notation"
|
|
||||||
echo "::: -h, help Show this usage dialog"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr(){
|
scriptusage() {
|
||||||
numfmt --to=iec-i --suffix=B "$1"
|
echo "::: List any connected clients to the server"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Usage: pivpn <-c|clients> [-b|bytes]"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] List clients with human readable format"
|
||||||
|
echo "::: -b, bytes List clients with dotted decimal notation"
|
||||||
|
echo "::: -h, help Show this usage dialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr() {
|
||||||
|
numfmt --to=iec-i --suffix=B "${1}"
|
||||||
|
}
|
||||||
|
|
||||||
listClients(){
|
listClients() {
|
||||||
printf ": NOTE : The output below is NOT real-time!\n"
|
printf ": NOTE : The output below is NOT real-time!\n"
|
||||||
printf ": : It may be off by a few minutes.\n"
|
printf ": : It may be off by a few minutes.\n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
printf "\e[1m::: Client Status List :::\e[0m\n"
|
printf "\e[1m::: Client Status List :::\e[0m\n"
|
||||||
|
|
||||||
{
|
{
|
||||||
printf "\e[4mName\e[0m \t \e[4mRemote IP\e[0m \t \e[4mVirtual IP\e[0m \t \e[4mBytes Received\e[0m \t \e[4mBytes Sent\e[0m \t \e[4mConnected Since\e[0m\n"
|
printf "\e[4mName\e[0m \t \e[4mRemote IP\e[0m \t "
|
||||||
|
printf "\e[4mVirtual IP\e[0m \t \e[4mBytes Received\e[0m \t "
|
||||||
|
printf "\e[4mBytes Sent\e[0m \t \e[4mConnected Since\e[0m\n"
|
||||||
|
|
||||||
if grep -q "^CLIENT_LIST" "${STATUS_LOG}"; then
|
if grep -q "^CLIENT_LIST" "${STATUS_LOG}"; then
|
||||||
if [ -n "$(type -t numfmt)" ]; then
|
if [[ -n "$(type -t numfmt)" ]]; then
|
||||||
if [ "$HR" = 1 ]; then
|
while read -r line; do
|
||||||
while read -r line; do
|
read -r -a array <<< "${line}"
|
||||||
read -r -a array <<< "$line"
|
|
||||||
[[ ${array[0]} = CLIENT_LIST ]] || continue
|
[[ "${array[0]}" == 'CLIENT_LIST' ]] || continue
|
||||||
printf "%s \t %s \t %s \t %s \t %s \t %s %s %s - %s\n" "${array[1]}" "${array[2]}" "${array[3]}" "$(hr "${array[4]}")" "$(hr "${array[5]}")" "${array[7]}" "${array[8]}" "${array[10]}" "${array[9]}"
|
|
||||||
done <$STATUS_LOG
|
printf "%s \t %s \t " "${array[1]}" "${array[2]}"
|
||||||
else
|
printf "%s \t " "${array[3]}"
|
||||||
while read -r line; do
|
|
||||||
read -r -a array <<< "$line"
|
if [[ "${HR}" == 1 ]]; then
|
||||||
[[ ${array[0]} = CLIENT_LIST ]] || continue
|
printf "%s \t %s" "$(hr "${array[4]}")" "$(hr "${array[5]}")"
|
||||||
printf "%s \t %s \t %s \t %'d \t %'d \t %s %s %s - %s\n" "${array[1]}" "${array[2]}" "${array[3]}" "${array[4]}" "${array[5]}" "${array[7]}" "${array[8]}" "${array[10]}" "${array[9]}"
|
else
|
||||||
done <$STATUS_LOG
|
printf "%'d \t %'d" "${array[4]}" "${array[5]}"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
awk -F' ' -v s='CLIENT_LIST' '$1 == s {print $2"\t\t"$3"\t"$4"\t"$5"\t\t"$6"\t\t"$8" "$9" "$11" - "$10"\n"}' ${STATUS_LOG}
|
printf " \t %s %s %s " "${array[7]}" "${array[8]}" "${array[10]}"
|
||||||
fi
|
printf "- %s\n" "${array[9]}"
|
||||||
|
done < "${STATUS_LOG}"
|
||||||
|
else
|
||||||
|
awk -F ' ' -v s='CLIENT_LIST' \
|
||||||
|
'$1 == s {
|
||||||
|
print $2"\t\t"$3"\t"$4"\t"$5"\t\t"$6"\t\t"$8" "$9" "$11" - "$10"\n"
|
||||||
|
}' \
|
||||||
|
"${STATUS_LOG}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
printf "\nNo Clients Connected!\n"
|
printf "\nNo Clients Connected!\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "\n"
|
printf "\n"
|
||||||
} | column -t -s $'\t'
|
} | column -t -s $'\t'
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $# -eq 0 ]]; then
|
if [[ "$#" -eq 0 ]]; then
|
||||||
HR=1
|
HR=1
|
||||||
listClients
|
listClients
|
||||||
else
|
else
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "${1}" in
|
||||||
-b|bytes)
|
-b | bytes)
|
||||||
HR=0
|
HR=0
|
||||||
listClients
|
listClients
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
-h|help)
|
-h | help)
|
||||||
scriptusage
|
scriptusage
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
HR=0
|
HR=0
|
||||||
listClients
|
listClients
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,42 +1,57 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
# PiVPN: list clients script
|
# PiVPN: list clients script
|
||||||
# Updated Script to include Expiration Dates and Clean up Escape Seq -- psgoundar
|
# Updated Script to include Expiration Dates and
|
||||||
|
# Clean up Escape Seq -- psgoundar
|
||||||
|
|
||||||
INDEX="/etc/openvpn/easy-rsa/pki/index.txt"
|
INDEX="/etc/openvpn/easy-rsa/pki/index.txt"
|
||||||
if [ ! -f "${INDEX}" ]; then
|
|
||||||
echo "The file: $INDEX was not found!"
|
err() {
|
||||||
exit 1
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ! -f "${INDEX}" ]]; then
|
||||||
|
err "The file: ${INDEX} was not found!"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
EASYRSA="/etc/openvpn/easy-rsa/easyrsa"
|
EASYRSA="/etc/openvpn/easy-rsa/easyrsa"
|
||||||
if [ ! -f "${EASYRSA}" ]; then
|
|
||||||
echo "The file: $EASYRSA was not found!"
|
if [[ ! -f "${EASYRSA}" ]]; then
|
||||||
exit 1
|
err "The file: ${EASYRSA} was not found!"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$EASYRSA update-db >> /dev/null 2>&1
|
"${EASYRSA}" update-db >> /dev/null 2>&1
|
||||||
|
|
||||||
printf ": NOTE : The first entry is your server, which should always be valid!\n"
|
printf ": NOTE : The first entry is your server, "
|
||||||
|
printf "which should always be valid!\n"
|
||||||
printf "\\n"
|
printf "\\n"
|
||||||
printf "\\e[1m::: Certificate Status List :::\\e[0m\\n"
|
printf "\\e[1m::: Certificate Status List :::\\e[0m\\n"
|
||||||
|
|
||||||
{
|
{
|
||||||
printf "\\e[4mStatus\\e[0m \t \\e[4mName\\e[0m\\e[0m \t \\e[4mExpiration\\e[0m\\n"
|
printf "\\e[4mStatus\\e[0m \t \\e[4mName\\e[0m\\e[0m \t "
|
||||||
|
printf "\\e[4mExpiration\\e[0m\\n"
|
||||||
|
|
||||||
while read -r line || [ -n "$line" ]; do
|
while read -r line || [[ -n "${line}" ]]; do
|
||||||
STATUS=$(echo "$line" | awk '{print $1}')
|
STATUS="$(echo "${line}" | awk '{print $1}')"
|
||||||
NAME=$(echo "$line" | awk -FCN= '{print $2}')
|
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 -)
|
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
|
if [[ "${STATUS}" == "V" ]]; then
|
||||||
printf "Valid \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD"
|
printf "Valid"
|
||||||
elif [ "${STATUS}" == "R" ]; then
|
elif [[ "${STATUS}" == "R" ]]; then
|
||||||
printf "Revoked \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD"
|
printf "Revoked"
|
||||||
elif [ "${STATUS}" == "E" ]; then
|
elif [[ "${STATUS}" == "E" ]]; then
|
||||||
printf "Expired \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD"
|
printf "Expired"
|
||||||
else
|
else
|
||||||
printf "Unknown \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD"
|
printf "Unknown"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
done <${INDEX}
|
printf " \t %s \t %s\\n" "$(echo -e "${NAME}")" "${EXPD}"
|
||||||
printf "\\n"
|
done < "${INDEX}"
|
||||||
|
|
||||||
|
printf "\\n"
|
||||||
} | column -t -s $'\t'
|
} | column -t -s $'\t'
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Create OVPN Client
|
# Create OVPN Client
|
||||||
# Default Variable Declarations
|
# Default Variable Declarations
|
||||||
setupVars="/etc/pivpn/openvpn/setupVars.conf"
|
setupVars="/etc/pivpn/openvpn/setupVars.conf"
|
||||||
|
@ -10,429 +11,497 @@ CA="ca.crt"
|
||||||
TA="ta.key"
|
TA="ta.key"
|
||||||
INDEX="/etc/openvpn/easy-rsa/pki/index.txt"
|
INDEX="/etc/openvpn/easy-rsa/pki/index.txt"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
helpFunc() {
|
err() {
|
||||||
echo "::: Create a client ovpn profile, optional nopass"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
|
||||||
echo "::: Usage: pivpn <-a|add> [-n|--name <arg>] [-p|--password <arg>]|[nopass] [-d|--days <number>] [-b|--bitwarden] [-i|--iOS] [-o|--ovpn] [-h|--help]"
|
|
||||||
echo ":::"
|
|
||||||
echo "::: Commands:"
|
|
||||||
echo "::: [none] Interactive mode"
|
|
||||||
echo "::: nopass Create a client without a password"
|
|
||||||
echo "::: -n,--name Name for the Client (default: \"$(hostname)\")"
|
|
||||||
echo "::: -p,--password Password for the Client (no default)"
|
|
||||||
echo "::: -d,--days Expire the certificate after specified number of days (default: 1080)"
|
|
||||||
echo "::: -b,--bitwarden Create and save a client through Bitwarden"
|
|
||||||
echo "::: -i,--iOS Generate a certificate that leverages iOS keychain"
|
|
||||||
echo "::: -o,--ovpn Regenerate a .ovpn config file for an existing client"
|
|
||||||
echo "::: -h,--help Show this help dialog"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -z "$HELP_SHOWN" ]; then
|
helpFunc() {
|
||||||
helpFunc
|
echo "::: Create a client ovpn profile, optional nopass"
|
||||||
echo
|
echo ":::"
|
||||||
echo "HELP_SHOWN=1" >> "$setupVars"
|
echo -n "::: Usage: pivpn <-a|add> [-n|--name <arg>] "
|
||||||
|
echo -n "[-p|--password <arg>]|[nopass] [-d|--days <number>] "
|
||||||
|
echo "[-b|--bitwarden] [-i|--iOS] [-o|--ovpn] [-h|--help]"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] Interactive mode"
|
||||||
|
echo "::: nopass Create a client without a password"
|
||||||
|
echo -n "::: -n,--name Name for the Client "
|
||||||
|
echo "(default: \"$(hostname)\")"
|
||||||
|
echo "::: -p,--password Password for the Client (no default)"
|
||||||
|
echo -n "::: -d,--days Expire the certificate after specified "
|
||||||
|
echo "number of days (default: 1080)"
|
||||||
|
echo "::: -b,--bitwarden Create and save a client through Bitwarden"
|
||||||
|
echo -n "::: -i,--iOS Generate a certificate that leverages iOS "
|
||||||
|
echo "keychain"
|
||||||
|
echo -n "::: -o,--ovpn Regenerate a .ovpn config file for an "
|
||||||
|
echo "existing client"
|
||||||
|
echo "::: -h,--help Show this help dialog"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -z "${HELP_SHOWN}" ]]; then
|
||||||
|
helpFunc
|
||||||
|
echo
|
||||||
|
echo "HELP_SHOWN=1" >> "${setupVars}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Parse input arguments
|
# Parse input arguments
|
||||||
while test $# -gt 0; do
|
while [[ "$#" -gt 0 ]]; do
|
||||||
_key="$1"
|
_key="${1}"
|
||||||
case "$_key" in
|
|
||||||
-n|--name|--name=*)
|
|
||||||
_val="${_key##--name=}"
|
|
||||||
if test "$_val" = "$_key"; then
|
|
||||||
test $# -lt 2 && echo "Missing value for the optional argument '$_key'." && exit 1
|
|
||||||
_val="$2"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
NAME="$_val"
|
|
||||||
;;
|
|
||||||
-p|--password|--password=*)
|
|
||||||
_val="${_key##--password=}"
|
|
||||||
if test "$_val" = "$_key"; then
|
|
||||||
test $# -lt 2 && echo "Missing value for the optional argument '$_key'." && exit 1
|
|
||||||
_val="$2"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
PASSWD="$_val"
|
|
||||||
;;
|
|
||||||
-d|--days|--days=*)
|
|
||||||
_val="${_key##--days=}"
|
|
||||||
if test "$_val" = "$_key"; then
|
|
||||||
test $# -lt 2 && echo "Missing value for the optional argument '$_key'." && exit 1
|
|
||||||
_val="$2"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
DAYS="$_val"
|
|
||||||
;;
|
|
||||||
-i|--iOS)
|
|
||||||
if [ "$TWO_POINT_FOUR" -ne 1 ]; then
|
|
||||||
iOS=1
|
|
||||||
else
|
|
||||||
echo "Sorry, can't generate iOS-specific configs for ECDSA certificates"
|
|
||||||
echo "Generate traditional certificates using 'pivpn -a' or reinstall PiVPN without opting in for OpenVPN 2.4 features"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
helpFunc
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
nopass)
|
|
||||||
NO_PASS="1"
|
|
||||||
;;
|
|
||||||
-b|--bitwarden)
|
|
||||||
if command -v bw > /dev/null; then
|
|
||||||
BITWARDEN="2"
|
|
||||||
else
|
|
||||||
echo 'Bitwarden not found, please install bitwarden'
|
|
||||||
|
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
case "${_key}" in
|
||||||
echo 'You can download it through the following commands:'
|
-n | --name | --name=*)
|
||||||
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'
|
_val="${_key##--name=}"
|
||||||
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
|
if [[ "${_val}" == "${_key}" ]]; then
|
||||||
fi
|
[[ "$#" -lt 2 ]] \
|
||||||
|
&& err "Missing value for the optional argument '${_key}'." \
|
||||||
|
&& exit 1
|
||||||
|
|
||||||
;;
|
_val="${2}"
|
||||||
-o|--ovpn)
|
shift
|
||||||
GENOVPNONLY=1
|
fi
|
||||||
;;
|
|
||||||
*)
|
NAME="${_val}"
|
||||||
echo "Error: Got an unexpected argument '$1'"
|
;;
|
||||||
helpFunc
|
-p | --password | --password=*)
|
||||||
exit 1
|
_val="${_key##--password=}"
|
||||||
;;
|
|
||||||
esac
|
if [[ "${_val}" == "${_key}" ]]; then
|
||||||
shift
|
[[ "$#" -lt 2 ]] \
|
||||||
|
&& err "Missing value for the optional argument '${_key}'." \
|
||||||
|
&& exit 1
|
||||||
|
|
||||||
|
_val="${2}"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
PASSWD="${_val}"
|
||||||
|
;;
|
||||||
|
-d | --days | --days=*)
|
||||||
|
_val="${_key##--days=}"
|
||||||
|
|
||||||
|
if [[ "${_val}" == "${_key}" ]]; then
|
||||||
|
[[ "$#" -lt 2 ]] \
|
||||||
|
&& err "Missing value for the optional argument '${_key}'." \
|
||||||
|
&& exit 1
|
||||||
|
|
||||||
|
_val="${2}"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
DAYS="${_val}"
|
||||||
|
;;
|
||||||
|
-i | --iOS)
|
||||||
|
if [[ "${TWO_POINT_FOUR}" -ne 1 ]]; then
|
||||||
|
iOS=1
|
||||||
|
else
|
||||||
|
err "Sorry, can't generate iOS-specific configs for ECDSA certificates"
|
||||||
|
err "Generate traditional certificates using 'pivpn -a' or reinstall PiVPN without opting in for OpenVPN 2.4 features"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
-h | --help)
|
||||||
|
helpFunc
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
nopass)
|
||||||
|
NO_PASS="1"
|
||||||
|
;;
|
||||||
|
-b | --bitwarden)
|
||||||
|
if command -v bw > /dev/null; then
|
||||||
|
BITWARDEN="2"
|
||||||
|
else
|
||||||
|
echo 'Bitwarden not found, please install bitwarden'
|
||||||
|
|
||||||
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
|
echo 'You can download it through the following commands:'
|
||||||
|
echo -n $'\t''curl -fLo bitwarden.zip --no-cache https://github.com/'
|
||||||
|
echo -n 'bitwarden/clients/releases/download/cli-v2022.6.2/'
|
||||||
|
echo 'bw-linux-2022.6.2.zip'
|
||||||
|
echo $'\t''apk --no-cache unzip'
|
||||||
|
echo $'\t''unzip 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 unzip'
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
;;
|
||||||
|
-o | --ovpn)
|
||||||
|
GENOVPNONLY=1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
err "Error: Got an unexpected argument '${1}'"
|
||||||
|
helpFunc
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
# Functions def
|
# Functions def
|
||||||
|
|
||||||
function keynoPASS() {
|
keynoPASS() {
|
||||||
|
# Build the client key
|
||||||
#Build the client key
|
expect << EOF
|
||||||
expect << EOF
|
|
||||||
set timeout -1
|
set timeout -1
|
||||||
set env(EASYRSA_CERT_EXPIRE) "${DAYS}"
|
set env(EASYRSA_CERT_EXPIRE) "${DAYS}"
|
||||||
spawn ./easyrsa build-client-full "${NAME}" nopass
|
spawn ./easyrsa build-client-full "${NAME}" nopass
|
||||||
expect eof
|
expect eof
|
||||||
EOF
|
EOF
|
||||||
|
cd pki || exit
|
||||||
cd pki || exit
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function useBitwarden() {
|
useBitwarden() {
|
||||||
|
# login and unlock vault
|
||||||
|
printf "****Bitwarden Login****"
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
# login and unlock vault
|
SESSION_KEY="$(bw login --raw)"
|
||||||
printf "****Bitwarden Login****"
|
export BW_SESSION="${SESSION_KEY}"
|
||||||
printf "\n"
|
|
||||||
SESSION_KEY=$(bw login --raw)
|
|
||||||
export BW_SESSION=$SESSION_KEY
|
|
||||||
printf "Successfully Logged in!"
|
|
||||||
printf "\n"
|
|
||||||
|
|
||||||
# ask user for username
|
printf "Successfully Logged in!"
|
||||||
printf "Enter the username: "
|
printf "\n"
|
||||||
|
|
||||||
|
# ask user for username
|
||||||
|
printf "Enter the username: "
|
||||||
|
read -r NAME
|
||||||
|
|
||||||
|
# check name
|
||||||
|
until [[ "${NAME}" =~ ^[a-zA-Z0-9.@_-]+$ ]] \
|
||||||
|
&& [[ "${NAME::1}" != "." ]] \
|
||||||
|
&& [[ "${NAME::1}" != "-" ]]; do
|
||||||
|
echo -n "Name can only contain alphanumeric characters and these "
|
||||||
|
echo -n "characters (.-@_). The name also cannot start with a dot (.)"
|
||||||
|
echo " or a dash (-). Please try again."
|
||||||
|
# ask user for username again
|
||||||
|
printf "Enter the username: "
|
||||||
read -r NAME
|
read -r NAME
|
||||||
|
done
|
||||||
|
|
||||||
# check name
|
# ask user for length of password
|
||||||
until [[ "$NAME" =~ ^[a-zA-Z0-9.@_-]+$ && ${NAME::1} != "." && ${NAME::1} != "-" ]]; do
|
printf "Please enter the length of characters you want your password to be "
|
||||||
echo "Name can only contain alphanumeric characters and these characters (.-@_). The name also cannot start with a dot (.) or a dash (-). Please try again."
|
printf "(minimum 12): "
|
||||||
# ask user for username again
|
read -r LENGTH
|
||||||
printf "Enter the username: "
|
|
||||||
read -r NAME
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
|
# check length
|
||||||
|
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
|
# ask user for length of password
|
||||||
printf "Please enter the length of characters you want your password to be (minimum 12): "
|
printf "Please enter the length of characters you want your password to be "
|
||||||
|
printf "(minimum 12): "
|
||||||
read -r LENGTH
|
read -r LENGTH
|
||||||
|
done
|
||||||
|
|
||||||
# check length
|
printf "Creating a PiVPN item for your vault..."
|
||||||
until [[ "$LENGTH" -gt 11 && "$LENGTH" -lt 129 ]]; do
|
printf "\n"
|
||||||
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): "
|
|
||||||
read -r LENGTH
|
|
||||||
done
|
|
||||||
|
|
||||||
printf "Creating a PiVPN item for your vault..."
|
|
||||||
printf "\n"
|
|
||||||
# create a new item for your PiVPN Password
|
|
||||||
PASSWD=$(bw generate -usln --length "$LENGTH")
|
|
||||||
bw get template item | jq '.login.type = "1"'| jq '.name = "PiVPN"' | jq -r --arg NAME "$NAME" '.login.username = $NAME' | jq -r --arg PASSWD "$PASSWD" '.login.password = $PASSWD' | bw encode | bw create item
|
|
||||||
bw logout
|
|
||||||
|
|
||||||
|
# create a new item for your PiVPN Password
|
||||||
|
PASSWD="$(bw generate -usln --length "${LENGTH}")"
|
||||||
|
bw get template item \
|
||||||
|
| jq '.login.type = "1"' \
|
||||||
|
| jq '.name = "PiVPN"' \
|
||||||
|
| jq -r --arg NAME "${NAME}" '.login.username = $NAME' \
|
||||||
|
| jq -r --arg PASSWD "${PASSWD}" '.login.password = $PASSWD' \
|
||||||
|
| bw encode \
|
||||||
|
| bw create item
|
||||||
|
bw logout
|
||||||
}
|
}
|
||||||
|
|
||||||
function keyPASS() {
|
keyPASS() {
|
||||||
|
if [[ -z "${PASSWD}" ]]; then
|
||||||
|
stty -echo
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
printf "Enter the password for the client: "
|
||||||
|
read -r PASSWD
|
||||||
|
printf "\n"
|
||||||
|
printf "Enter the password again to verify: "
|
||||||
|
read -r PASSWD2
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
|
[[ "${PASSWD}" == "${PASSWD2}" ]] && break
|
||||||
|
|
||||||
|
printf "Passwords do not match! Please try again.\n"
|
||||||
|
done
|
||||||
|
|
||||||
|
stty echo
|
||||||
|
|
||||||
if [[ -z "${PASSWD}" ]]; then
|
if [[ -z "${PASSWD}" ]]; then
|
||||||
stty -echo
|
err "You left the password blank"
|
||||||
while true; do
|
err "If you don't want a password, please run:"
|
||||||
printf "Enter the password for the client: "
|
err "pivpn add nopass"
|
||||||
read -r PASSWD
|
exit 1
|
||||||
printf "\n"
|
|
||||||
printf "Enter the password again to verify: "
|
|
||||||
read -r PASSWD2
|
|
||||||
printf "\n"
|
|
||||||
[ "${PASSWD}" = "${PASSWD2}" ] && break
|
|
||||||
printf "Passwords do not match! Please try again.\n"
|
|
||||||
done
|
|
||||||
stty echo
|
|
||||||
if [[ -z "${PASSWD}" ]]; then
|
|
||||||
echo "You left the password blank"
|
|
||||||
echo "If you don't want a password, please run:"
|
|
||||||
echo "pivpn add nopass"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [ ${#PASSWD} -lt 4 ] || [ ${#PASSWD} -gt 1024 ]; then
|
|
||||||
echo "Password must be between from 4 to 1024 characters"
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
#Escape chars in PASSWD
|
if [[ "${#PASSWD}" -lt 4 ]] || [[ "${#PASSWD}" -gt 1024 ]]; then
|
||||||
PASSWD_UNESCAPED="${PASSWD}"
|
err "Password must be between from 4 to 1024 characters"
|
||||||
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' -e 's/\}/\\\}/g')
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
#Build the client key and then encrypt the key
|
# Escape chars in PASSWD
|
||||||
|
PASSWD_UNESCAPED="${PASSWD}"
|
||||||
|
|
||||||
expect << EOF
|
PASSWD="${PASSWD//\\/\\\\}"
|
||||||
set timeout -1
|
PASSWD="${PASSWD//\//\\\/}"
|
||||||
set env(EASYRSA_CERT_EXPIRE) "${DAYS}"
|
PASSWD="${PASSWD//\$/\\\$}"
|
||||||
spawn ./easyrsa build-client-full "${NAME}"
|
PASSWD="${PASSWD//!/\\!}"
|
||||||
expect "Enter PEM pass phrase" { sleep 0.1; send -- "${PASSWD}\r" }
|
PASSWD="${PASSWD//\./\\\.}"
|
||||||
expect "Verifying - Enter PEM pass phrase" { sleep 0.1; send -- "${PASSWD}\r" }
|
PASSWD="${PASSWD//\'/\\\'}"
|
||||||
expect eof
|
PASSWD="${PASSWD//\"/\\\"}"
|
||||||
|
PASSWD="${PASSWD//*/\\*}"
|
||||||
|
PASSWD="${PASSWD//@/\\@}"
|
||||||
|
PASSWD="${PASSWD//#/\\#}"
|
||||||
|
PASSWD="${PASSWD//\£/\\\£}"
|
||||||
|
PASSWD="${PASSWD//%/\\%}"
|
||||||
|
PASSWD="${PASSWD//\^/\\\^}"
|
||||||
|
PASSWD="${PASSWD//\&/\\\&}"
|
||||||
|
PASSWD="${PASSWD//\(/\\\(}"
|
||||||
|
PASSWD="${PASSWD//\)/\\\)}"
|
||||||
|
PASSWD="${PASSWD//\-/\\\-}"
|
||||||
|
PASSWD="${PASSWD//\_/\\\_}"
|
||||||
|
PASSWD="${PASSWD//\+/\\\+}"
|
||||||
|
PASSWD="${PASSWD//\=/\\\=}"
|
||||||
|
PASSWD="${PASSWD//\[/\\\[}"
|
||||||
|
PASSWD="${PASSWD//\]/\\\]}"
|
||||||
|
PASSWD="${PASSWD//:/\\:}"
|
||||||
|
PASSWD="${PASSWD//\;/\\\;}"
|
||||||
|
PASSWD="${PASSWD//\|/\\\|}"
|
||||||
|
PASSWD="${PASSWD//\</\\\<}"
|
||||||
|
PASSWD="${PASSWD//\>/\\\>}"
|
||||||
|
PASSWD="${PASSWD//\,/\\\,}"
|
||||||
|
PASSWD="${PASSWD//\~/\\\~}"
|
||||||
|
PASSWD="${PASSWD//\?/\\\?}"
|
||||||
|
PASSWD="${PASSWD//\{/\\\{}"
|
||||||
|
PASSWD="${PASSWD//\}/\\\}}"
|
||||||
|
|
||||||
|
# Build the client key and then encrypt the key
|
||||||
|
expect << EOF
|
||||||
|
set timeout -1
|
||||||
|
set env(EASYRSA_CERT_EXPIRE) "${DAYS}"
|
||||||
|
spawn ./easyrsa build-client-full "${NAME}"
|
||||||
|
expect "Enter PEM pass phrase" {sleep 0.1; send -- "${PASSWD}\r"}
|
||||||
|
expect "Verifying - Enter PEM pass phrase" {sleep 0.1; send -- "${PASSWD}\r"}
|
||||||
|
expect eof
|
||||||
EOF
|
EOF
|
||||||
cd pki || exit
|
cd pki || exit
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#make sure ovpns dir exists
|
#make sure ovpns dir exists
|
||||||
# Disabling warning for SC2154, var sourced externaly
|
# Disabling warning for SC2154, var sourced externaly
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
if [ ! -d "$install_home/ovpns" ]; then
|
if [[ ! -d "${install_home}/ovpns" ]]; then
|
||||||
mkdir "$install_home/ovpns"
|
mkdir "${install_home}/ovpns"
|
||||||
chown "$install_user":"$install_user" "$install_home/ovpns"
|
chown "${install_user}:${install_user}" "${install_home}/ovpns"
|
||||||
chmod 0750 "$install_home/ovpns"
|
chmod 0750 "${install_home}/ovpns"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#bitWarden
|
#bitWarden
|
||||||
if [[ "${BITWARDEN}" =~ "2" ]]; then
|
if [[ "${BITWARDEN}" =~ "2" ]]; then
|
||||||
useBitwarden
|
useBitwarden
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${NAME}" ]; then
|
|
||||||
printf "Enter a Name for the Client: "
|
|
||||||
read -r NAME
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${NAME::1} == "." ]] || [[ ${NAME::1} == "-" ]]; then
|
|
||||||
echo "Names cannot start with a dot (.) or a dash (-)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${NAME}" =~ [^a-zA-Z0-9.@_-] ]]; then
|
|
||||||
echo "Name can only contain alphanumeric characters and these characters (.-@_)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${NAME}" =~ ^[0-9]+$ ]]; then
|
|
||||||
echo "Names cannot be integers."
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "${NAME}" ]]; then
|
if [[ -z "${NAME}" ]]; then
|
||||||
echo "You cannot leave the name blank."
|
printf "Enter a Name for the Client: "
|
||||||
exit 1
|
read -r NAME
|
||||||
|
elif [[ "${NAME::1}" == "." ]] || [[ "${NAME::1}" == "-" ]]; then
|
||||||
|
err "Names cannot start with a dot (.) or a dash (-)."
|
||||||
|
exit 1
|
||||||
|
elif [[ "${NAME}" =~ [^a-zA-Z0-9.@_-] ]]; then
|
||||||
|
err "Name can only contain alphanumeric characters and these symbols (.-@_)."
|
||||||
|
exit 1
|
||||||
|
elif [[ "${NAME}" =~ ^[0-9]+$ ]]; then
|
||||||
|
err "Names cannot be integers."
|
||||||
|
exit 1
|
||||||
|
elif [[ -z "${NAME}" ]]; then
|
||||||
|
err "You cannot leave the name blank."
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${GENOVPNONLY}" == "1" ]; then
|
if [[ "${GENOVPNONLY}" == 1 ]]; then
|
||||||
# Generate .ovpn configuration file
|
# Generate .ovpn configuration file
|
||||||
cd /etc/openvpn/easy-rsa/pki || exit
|
cd /etc/openvpn/easy-rsa/pki || exit
|
||||||
else
|
else
|
||||||
# Check if name is already in use
|
# Check if name is already in use
|
||||||
while read -r line || [ -n "${line}" ]; do
|
while read -r line || [[ -n "${line}" ]]; do
|
||||||
STATUS=$(echo "$line" | awk '{print $1}')
|
STATUS=$(echo "${line}" | awk '{print $1}')
|
||||||
|
|
||||||
if [ "${STATUS}" == "V" ]; then
|
if [[ "${STATUS}" == "V" ]]; then
|
||||||
# Disabling SC2001 as ${variable//search/replace} doesn't go well with regexp
|
# Disabling SC2001 as ${variable//search/replace}
|
||||||
# shellcheck disable=SC2001
|
# doesn't go well with regexp
|
||||||
CERT=$(echo "$line" | sed -e 's:.*/CN=::')
|
# shellcheck disable=SC2001
|
||||||
if [ "${CERT}" == "${NAME}" ]; then
|
CERT="$(echo "${line}" | sed -e 's:.*/CN=::')"
|
||||||
INUSE="1"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done <${INDEX}
|
|
||||||
|
|
||||||
if [ "${INUSE}" == "1" ]; then
|
if [[ "${CERT}" == "${NAME}" ]]; then
|
||||||
printf "\n!! This name is already in use by a Valid Certificate."
|
INUSE="1"
|
||||||
printf "\nPlease choose another name or revoke this certificate first.\n"
|
break
|
||||||
exit 1
|
fi
|
||||||
fi
|
fi
|
||||||
|
done < "${INDEX}"
|
||||||
|
|
||||||
# Check if name is reserved
|
if [[ "${INUSE}" == 1 ]]; then
|
||||||
if [ "${NAME}" == "ta" ] || [ "${NAME}" == "server" ] || [ "${NAME}" == "ca" ]; then
|
err "!! This name is already in use by a Valid Certificate."
|
||||||
echo "Sorry, this is in use by the server and cannot be used by clients."
|
err "Please choose another name or revoke this certificate first."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
# Check if name is reserved
|
||||||
|
elif [[ "${NAME}" == "ta" ]] \
|
||||||
|
|| [[ "${NAME}" == "server" ]] \
|
||||||
|
|| [[ "${NAME}" == "ca" ]]; then
|
||||||
|
err "Sorry, this is in use by the server and cannot be used by clients."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
#As of EasyRSA 3.0.6, by default certificates last 1080 days, see https://github.com/OpenVPN/easy-rsa/blob/6b7b6bf1f0d3c9362b5618ad18c66677351cacd1/easyrsa3/vars.example
|
# As of EasyRSA 3.0.6, by default certificates last 1080 days,
|
||||||
if [ -z "${DAYS}" ]; then
|
# see https://github.com/OpenVPN/easy-rsa/blob/6b7b6bf1f0d3c9362b5618ad18c66677351cacd1/easyrsa3/vars.example
|
||||||
read -r -e -p "How many days should the certificate last? " -i 1080 DAYS
|
if [[ -z "${DAYS}" ]]; then
|
||||||
fi
|
read -r -e -p "How many days should the certificate last? " -i 1080 DAYS
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! "$DAYS" =~ ^[0-9]+$ ]] || [ "$DAYS" -lt 1 ] || [ "$DAYS" -gt 3650 ]; then
|
if [[ ! "${DAYS}" =~ ^[0-9]+$ ]] \
|
||||||
#The CRL lasts 3650 days so it doesn't make much sense that certificates would last longer
|
|| [[ "${DAYS}" -lt 1 ]] \
|
||||||
echo "Please input a valid number of days, between 1 and 3650 inclusive."
|
|| [[ "${DAYS}" -gt 3650 ]]; then
|
||||||
exit 1
|
# The CRL lasts 3650 days so it doesn't make much sense
|
||||||
fi
|
# that certificates would last longer
|
||||||
|
err "Please input a valid number of days, between 1 and 3650 inclusive."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
cd /etc/openvpn/easy-rsa || exit
|
cd /etc/openvpn/easy-rsa || exit
|
||||||
|
|
||||||
if [[ "${NO_PASS}" =~ "1" ]]; then
|
if [[ "${NO_PASS}" =~ "1" ]]; then
|
||||||
if [[ -n "${PASSWD}" ]]; then
|
if [[ -n "${PASSWD}" ]]; then
|
||||||
echo "Both nopass and password arguments passed to the script. Please use either one."
|
err "Both nopass and password arguments passed to the script. Please use either one."
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
keynoPASS
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
keyPASS
|
keynoPASS
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
keyPASS
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#1st Verify that clients Public Key Exists
|
#1st Verify that clients Public Key Exists
|
||||||
if [ ! -f "issued/${NAME}${CRT}" ]; then
|
if [[ ! -f "issued/${NAME}${CRT}" ]]; then
|
||||||
echo "[ERROR]: Client Public Key Certificate not found: $NAME$CRT"
|
err "[ERROR]: Client Public Key Certificate not found: ${NAME}${CRT}"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
echo "Client's cert found: $NAME$CRT"
|
|
||||||
|
echo "Client's cert found: ${NAME}${CRT}"
|
||||||
|
|
||||||
#Then, verify that there is a private key for that client
|
#Then, verify that there is a private key for that client
|
||||||
if [ ! -f "private/${NAME}${KEY}" ]; then
|
if [[ ! -f "private/${NAME}${KEY}" ]]; then
|
||||||
echo "[ERROR]: Client Private Key not found: $NAME$KEY"
|
err "[ERROR]: Client Private Key not found: ${NAME}${KEY}"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
echo "Client's Private Key found: $NAME$KEY"
|
|
||||||
|
echo "Client's Private Key found: ${NAME}${KEY}"
|
||||||
|
|
||||||
#Confirm the CA public key exists
|
#Confirm the CA public key exists
|
||||||
if [ ! -f "${CA}" ]; then
|
if [[ ! -f "${CA}" ]]; then
|
||||||
echo "[ERROR]: CA Public Key not found: $CA"
|
err "[ERROR]: CA Public Key not found: ${CA}"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
echo "CA public Key found: $CA"
|
|
||||||
|
echo "CA public Key found: ${CA}"
|
||||||
|
|
||||||
#Confirm the tls key file exists
|
#Confirm the tls key file exists
|
||||||
if [ ! -f "${TA}" ]; then
|
if [[ ! -f "${TA}" ]]; then
|
||||||
echo "[ERROR]: tls Private Key not found: $TA"
|
err "[ERROR]: tls Private Key not found: ${TA}"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
echo "tls Private Key found: $TA"
|
|
||||||
|
|
||||||
|
echo "tls Private Key found: ${TA}"
|
||||||
|
|
||||||
## Added new step to create an .ovpn12 file that can be stored on iOS keychain
|
## Added new step to create an .ovpn12 file that can be stored on iOS keychain
|
||||||
## This step is more secure method and does not require the end-user to keep entering passwords, or storing the client private cert where it can be easily tampered
|
## This step is more secure method and does not require the end-user to keep
|
||||||
|
## entering passwords, or storing the client private cert where it can be easily
|
||||||
|
## tampered
|
||||||
## https://openvpn.net/faq/how-do-i-use-a-client-certificate-and-private-key-from-the-ios-keychain/
|
## https://openvpn.net/faq/how-do-i-use-a-client-certificate-and-private-key-from-the-ios-keychain/
|
||||||
if [ "$iOS" = "1" ]; then
|
|
||||||
#Generates the .ovpn file WITHOUT the client private key
|
|
||||||
{
|
|
||||||
# Start by populating with the default file
|
|
||||||
cat "${DEFAULT}"
|
|
||||||
|
|
||||||
#Now, append the CA Public Cert
|
# Generates the .ovpn file WITHOUT the client private key
|
||||||
echo "<ca>"
|
{
|
||||||
cat "${CA}"
|
# Start by populating with the default file
|
||||||
echo "</ca>"
|
cat "${DEFAULT}"
|
||||||
|
|
||||||
#Next append the client Public Cert
|
# Now, append the CA Public Cert
|
||||||
echo "<cert>"
|
echo "<ca>"
|
||||||
sed -n -e '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' < "issued/${NAME}${CRT}"
|
cat "${CA}"
|
||||||
echo "</cert>"
|
echo "</ca>"
|
||||||
|
|
||||||
#Finally, append the tls Private Key
|
# Next append the client Public Cert
|
||||||
echo "<tls-auth>"
|
echo "<cert>"
|
||||||
cat "${TA}"
|
sed -n \
|
||||||
echo "</tls-auth>"
|
-e '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' \
|
||||||
|
< "issued/${NAME}${CRT}"
|
||||||
|
echo "</cert>"
|
||||||
|
|
||||||
} > "${NAME}${FILEEXT}"
|
if [[ "${iOS}" != 1 ]]; then
|
||||||
|
# Then, append the client Private Key
|
||||||
# Copy the .ovpn profile to the home directory for convenient remote access
|
|
||||||
|
|
||||||
printf "========================================================\n"
|
|
||||||
printf "Generating an .ovpn12 file for use with iOS devices\n"
|
|
||||||
printf "Please remember the export password\n"
|
|
||||||
printf "as you will need this import the certificate on your iOS device\n"
|
|
||||||
printf "========================================================\n"
|
|
||||||
openssl pkcs12 -passin pass:"$PASSWD_UNESCAPED" -export -in "issued/${NAME}${CRT}" -inkey "private/${NAME}${KEY}" -certfile ${CA} -name "${NAME}" -out "$install_home/ovpns/$NAME.ovpn12"
|
|
||||||
chown "$install_user":"$install_user" "$install_home/ovpns/$NAME.ovpn12"
|
|
||||||
chmod 640 "$install_home/ovpns/$NAME.ovpn12"
|
|
||||||
printf "========================================================\n"
|
|
||||||
printf "\e[1mDone! %s successfully created!\e[0m \n" "$NAME.ovpn12"
|
|
||||||
printf "You will need to transfer both the .ovpn and .ovpn12 files\n"
|
|
||||||
printf "to your iOS device.\n"
|
|
||||||
printf "========================================================\n\n"
|
|
||||||
else
|
|
||||||
#This is the standard non-iOS configuration
|
|
||||||
#Ready to make a new .ovpn file
|
|
||||||
{
|
|
||||||
# Start by populating with the default file
|
|
||||||
cat "${DEFAULT}"
|
|
||||||
|
|
||||||
#Now, append the CA Public Cert
|
|
||||||
echo "<ca>"
|
|
||||||
cat "${CA}"
|
|
||||||
echo "</ca>"
|
|
||||||
|
|
||||||
#Next append the client Public Cert
|
|
||||||
echo "<cert>"
|
|
||||||
sed -n -e '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' < "issued/${NAME}${CRT}"
|
|
||||||
echo "</cert>"
|
|
||||||
|
|
||||||
#Then, append the client Private Key
|
|
||||||
echo "<key>"
|
echo "<key>"
|
||||||
cat "private/${NAME}${KEY}"
|
cat "private/${NAME}${KEY}"
|
||||||
echo "</key>"
|
echo "</key>"
|
||||||
|
fi
|
||||||
|
|
||||||
#Finally, append the tls Private Key
|
# Finally, append the tls Private Key
|
||||||
if [ "$TWO_POINT_FOUR" -eq 1 ]; then
|
if [[ "${iOS}" != 1 ]] && [[ "${TWO_POINT_FOUR}" -eq 1 ]]; then
|
||||||
echo "<tls-crypt>"
|
echo "<tls-crypt>"
|
||||||
cat "${TA}"
|
cat "${TA}"
|
||||||
echo "</tls-crypt>"
|
echo "</tls-crypt>"
|
||||||
else
|
else
|
||||||
echo "<tls-auth>"
|
echo "<tls-auth>"
|
||||||
cat "${TA}"
|
cat "${TA}"
|
||||||
echo "</tls-auth>"
|
echo "</tls-auth>"
|
||||||
fi
|
fi
|
||||||
|
} > "${NAME}${FILEEXT}"
|
||||||
|
|
||||||
} > "${NAME}${FILEEXT}"
|
if [[ "${iOS}" == 1 ]]; then
|
||||||
|
# Copy the .ovpn profile to the home directory for convenient remote access
|
||||||
|
printf "========================================================\n"
|
||||||
|
printf "Generating an .ovpn12 file for use with iOS devices\n"
|
||||||
|
printf "Please remember the export password\n"
|
||||||
|
printf "as you will need this import the certificate on your iOS device\n"
|
||||||
|
printf "========================================================\n"
|
||||||
|
|
||||||
|
openssl pkcs12 \
|
||||||
|
-passin pass:"${PASSWD_UNESCAPED}" \
|
||||||
|
-export \
|
||||||
|
-in "issued/${NAME}${CRT}" \
|
||||||
|
-inkey "private/${NAME}${KEY}" \
|
||||||
|
-certfile "${CA}" \
|
||||||
|
-name "${NAME}" \
|
||||||
|
-out "${install_home}/ovpns/${NAME}.ovpn12"
|
||||||
|
|
||||||
|
chown "${install_user}:${install_user}" "${install_home}/ovpns/${NAME}.ovpn12"
|
||||||
|
chmod 640 "${install_home}/ovpns/${NAME}.ovpn12"
|
||||||
|
|
||||||
|
printf "========================================================\n"
|
||||||
|
printf "\e[1mDone! %s successfully created!\e[0m \n" "${NAME}.ovpn12"
|
||||||
|
printf "You will need to transfer both the .ovpn and .ovpn12 files\n"
|
||||||
|
printf "to your iOS device.\n"
|
||||||
|
printf "========================================================\n\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cidrToMask(){
|
cidrToMask() {
|
||||||
# Source: https://stackoverflow.com/a/20767392
|
# Source: https://stackoverflow.com/a/20767392
|
||||||
set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
|
set -- $((5 - (${1} / 8))) \
|
||||||
shift "$1"
|
255 255 255 255 \
|
||||||
echo "${1-0}"."${2-0}"."${3-0}"."${4-0}"
|
$(((255 << (8 - (${1} % 8))) & 255)) \
|
||||||
|
0 0 0
|
||||||
|
shift "${1}"
|
||||||
|
echo "${1-0}.${2-0}.${3-0}.${4-0}"
|
||||||
}
|
}
|
||||||
|
|
||||||
#disabling SC2514, variable sourced externaly
|
#disabling SC2514, variable sourced externaly
|
||||||
|
@ -441,37 +510,44 @@ NET_REDUCED="${pivpnNET::-2}"
|
||||||
|
|
||||||
# Find an unused number for the last octet of the client IP
|
# Find an unused number for the last octet of the client IP
|
||||||
for i in {2..254}; do
|
for i in {2..254}; do
|
||||||
# find returns 0 if the folder is empty, so we create the 'ls -A [...]'
|
# find returns 0 if the folder is empty, so we create the 'ls -A [...]'
|
||||||
# exception to stop at the first static IP (10.8.0.2). Otherwise it would
|
# exception to stop at the first static IP (10.8.0.2). Otherwise it would
|
||||||
# cycle to the end without finding and available octet.
|
# cycle to the end without finding and available octet.
|
||||||
# disabling SC2514, variable sourced externaly
|
# disabling SC2514, variable sourced externaly
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
if [ -z "$(ls -A /etc/openvpn/ccd)" ] || ! find /etc/openvpn/ccd -type f -exec grep -q "${NET_REDUCED}.${i}" {} +; then
|
if [[ -z "$(ls -A /etc/openvpn/ccd)" ]] \
|
||||||
COUNT="${i}"
|
|| ! find /etc/openvpn/ccd -type f \
|
||||||
echo "ifconfig-push ${NET_REDUCED}.${i} $(cidrToMask "$subnetClass")" >> /etc/openvpn/ccd/"${NAME}"
|
-exec grep -q "${NET_REDUCED}.${i}" {} +; then
|
||||||
break
|
COUNT="${i}"
|
||||||
fi
|
echo -n "ifconfig-push ${NET_REDUCED}.${i}" >> /etc/openvpn/ccd/"${NAME}"
|
||||||
|
cidrToMask "${subnetClass}" >> /etc/openvpn/ccd/"${NAME}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -f /etc/pivpn/hosts.openvpn ]; then
|
if [[ -f /etc/pivpn/hosts.openvpn ]]; then
|
||||||
echo "${NET_REDUCED}.${COUNT} ${NAME}.pivpn" >> /etc/pivpn/hosts.openvpn
|
echo "${NET_REDUCED}.${COUNT} ${NAME}.pivpn" >> /etc/pivpn/hosts.openvpn
|
||||||
if killall -SIGHUP pihole-FTL; then
|
|
||||||
echo "::: Updated hosts file for Pi-hole"
|
if killall -SIGHUP pihole-FTL; then
|
||||||
else
|
echo "::: Updated hosts file for Pi-hole"
|
||||||
echo "::: Failed to reload pihole-FTL configuration"
|
else
|
||||||
fi
|
err "::: Failed to reload pihole-FTL configuration"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy the .ovpn profile to the home directory for convenient remote access
|
# Copy the .ovpn profile to the home directory for convenient remote access
|
||||||
cp "/etc/openvpn/easy-rsa/pki/$NAME$FILEEXT" "$install_home/ovpns/$NAME$FILEEXT"
|
dest_path="${install_home}/ovpns/${NAME}${FILEEXT}"
|
||||||
chown "$install_user":"$install_user" "$install_home/ovpns/$NAME$FILEEXT"
|
cp "/etc/openvpn/easy-rsa/pki/${NAME}${FILEEXT}" "${dest_path}"
|
||||||
chmod 640 "/etc/openvpn/easy-rsa/pki/$NAME$FILEEXT"
|
chown "${install_user}:${install_user}" "${dest_path}"
|
||||||
chmod 640 "$install_home/ovpns/$NAME$FILEEXT"
|
chmod 640 "/etc/openvpn/easy-rsa/pki/${NAME}${FILEEXT}"
|
||||||
|
chmod 640 "${dest_path}"
|
||||||
|
unset dest_path
|
||||||
|
|
||||||
printf "\n\n"
|
printf "\n\n"
|
||||||
printf "========================================================\n"
|
printf "========================================================\n"
|
||||||
printf "\e[1mDone! %s successfully created!\e[0m \n" "$NAME$FILEEXT"
|
printf "\e[1mDone! %s successfully created!\e[0m \n" "${NAME}${FILEEXT}"
|
||||||
printf "%s was copied to:\n" "$NAME$FILEEXT"
|
printf "%s was copied to:\n" "${NAME}${FILEEXT}"
|
||||||
printf " %s/ovpns\n" "$install_home"
|
printf " %s/ovpns\n" "${install_home}"
|
||||||
printf "for easy transfer. Please use this profile only on one\n"
|
printf "for easy transfer. Please use this profile only on one\n"
|
||||||
printf "device and create additional profiles for other devices.\n"
|
printf "device and create additional profiles for other devices.\n"
|
||||||
printf "========================================================\n\n"
|
printf "========================================================\n\n"
|
||||||
|
|
|
@ -3,15 +3,15 @@
|
||||||
CHECK_PKG_INSTALLED='dpkg-query -s'
|
CHECK_PKG_INSTALLED='dpkg-query -s'
|
||||||
|
|
||||||
if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then
|
if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then
|
||||||
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Must be root to use this tool
|
# Must be root to use this tool
|
||||||
if [[ ! $EUID -eq 0 ]]; then
|
if [[ "${EUID}" -ne 0 ]]; then
|
||||||
if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then
|
if ${CHECK_PKG_INSTALLED} sudo &> /dev/null; then
|
||||||
export SUDO="sudo"
|
export SUDO="sudo"
|
||||||
else
|
else
|
||||||
echo "::: Please install sudo or run this as root."
|
err "::: Please install sudo or run this as root."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
@ -19,88 +19,113 @@ fi
|
||||||
scriptDir="/opt/pivpn"
|
scriptDir="/opt/pivpn"
|
||||||
vpn="openvpn"
|
vpn="openvpn"
|
||||||
|
|
||||||
function makeOVPNFunc {
|
err() {
|
||||||
shift
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
$SUDO ${scriptDir}/${vpn}/makeOVPN.sh "$@"
|
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function listClientsFunc {
|
makeOVPNFunc() {
|
||||||
shift
|
shift
|
||||||
$SUDO ${scriptDir}/${vpn}/clientStat.sh "$@"
|
${SUDO} "${scriptDir}/${vpn}/makeOVPN.sh" "$@"
|
||||||
exit "$?"
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function listOVPNFunc {
|
listClientsFunc() {
|
||||||
$SUDO ${scriptDir}/${vpn}/listOVPN.sh
|
shift
|
||||||
exit "$?"
|
${SUDO} "${scriptDir}/${vpn}/clientStat.sh" "$@"
|
||||||
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugFunc {
|
listOVPNFunc() {
|
||||||
echo "::: Generating Debug Output"
|
${SUDO} "${scriptDir}/${vpn}/listOVPN.sh"
|
||||||
$SUDO ${scriptDir}/${vpn}/pivpnDebug.sh | tee /tmp/debug.log
|
exit "${?}"
|
||||||
echo "::: "
|
|
||||||
echo "::: Debug output completed above."
|
|
||||||
echo "::: Copy saved to /tmp/debug.log"
|
|
||||||
echo "::: "
|
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeOVPNFunc {
|
debugFunc() {
|
||||||
shift
|
echo "::: Generating Debug Output"
|
||||||
$SUDO ${scriptDir}/${vpn}/removeOVPN.sh "$@"
|
|
||||||
exit "$?"
|
${SUDO} "${scriptDir}/${vpn}/pivpnDebug.sh" | tee /tmp/debug.log
|
||||||
|
|
||||||
|
echo "::: "
|
||||||
|
echo "::: Debug output completed above."
|
||||||
|
echo "::: Copy saved to /tmp/debug.log"
|
||||||
|
echo "::: "
|
||||||
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function uninstallFunc {
|
removeOVPNFunc() {
|
||||||
$SUDO ${scriptDir}/uninstall.sh "${vpn}"
|
shift
|
||||||
exit "$?"
|
${SUDO} "${scriptDir}/${vpn}/removeOVPN.sh" "$@"
|
||||||
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function update {
|
uninstallFunc() {
|
||||||
shift
|
${SUDO} "${scriptDir}/uninstall.sh" "${vpn}"
|
||||||
$SUDO ${scriptDir}/update.sh "$@"
|
exit "${?}"
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function backup {
|
update() {
|
||||||
$SUDO ${scriptDir}/backup.sh "${vpn}"
|
shift
|
||||||
exit "$?"
|
${SUDO} "${scriptDir}/update.sh" "$@"
|
||||||
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backup() {
|
||||||
function helpFunc {
|
${SUDO} "${scriptDir}/backup.sh" "${vpn}"
|
||||||
echo "::: Control all PiVPN specific functions!"
|
exit "${?}"
|
||||||
echo ":::"
|
|
||||||
echo "::: Usage: pivpn <command> [option]"
|
|
||||||
echo ":::"
|
|
||||||
echo "::: Commands:"
|
|
||||||
echo "::: -a, add [nopass] Create a client ovpn profile, optional nopass"
|
|
||||||
echo "::: -c, clients List any connected clients to the server"
|
|
||||||
echo "::: -d, debug Start a debugging session if having trouble"
|
|
||||||
echo "::: -l, list List all valid and revoked certificates"
|
|
||||||
echo "::: -r, revoke Revoke a client ovpn profile"
|
|
||||||
echo "::: -h, help Show this help dialog"
|
|
||||||
echo "::: -u, uninstall Uninstall PiVPN from your system!"
|
|
||||||
echo "::: -up, update Updates PiVPN Scripts"
|
|
||||||
echo "::: -bk, backup Backup Openvpn and ovpns dir"
|
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $# = 0 ]]; then
|
helpFunc() {
|
||||||
helpFunc
|
echo "::: Control all PiVPN specific functions!"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Usage: pivpn <command> [option]"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: -a, add [nopass] Create a client ovpn profile, optional nopass"
|
||||||
|
echo "::: -c, clients List any connected clients to the server"
|
||||||
|
echo "::: -d, debug Start a debugging session if having trouble"
|
||||||
|
echo "::: -l, list List all valid and revoked certificates"
|
||||||
|
echo "::: -r, revoke Revoke a client ovpn profile"
|
||||||
|
echo "::: -h, help Show this help dialog"
|
||||||
|
echo "::: -u, uninstall Uninstall PiVPN from your system!"
|
||||||
|
echo "::: -up, update Updates PiVPN Scripts"
|
||||||
|
echo "::: -bk, backup Backup Openvpn and ovpns dir"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$#" == 0 ]]; then
|
||||||
|
helpFunc
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Handle redirecting to specific functions based on arguments
|
# Handle redirecting to specific functions based on arguments
|
||||||
case "$1" in
|
case "${1}" in
|
||||||
"-a" | "add" ) makeOVPNFunc "$@";;
|
"-a" | "add")
|
||||||
"-c" | "clients" ) listClientsFunc "$@";;
|
makeOVPNFunc "$@"
|
||||||
"-d" | "debug" ) debugFunc;;
|
;;
|
||||||
"-l" | "list" ) listOVPNFunc;;
|
"-c" | "clients")
|
||||||
"-r" | "revoke" ) removeOVPNFunc "$@";;
|
listClientsFunc "$@"
|
||||||
"-h" | "help" ) helpFunc;;
|
;;
|
||||||
"-u" | "uninstall" ) uninstallFunc;;
|
"-d" | "debug")
|
||||||
"-up"| "update" ) update "$@" ;;
|
debugFunc
|
||||||
"-bk"| "backup" ) backup;;
|
;;
|
||||||
* ) helpFunc;;
|
"-l" | "list")
|
||||||
|
listOVPNFunc
|
||||||
|
;;
|
||||||
|
"-r" | "revoke")
|
||||||
|
removeOVPNFunc "$@"
|
||||||
|
;;
|
||||||
|
"-h" | "help")
|
||||||
|
helpFunc
|
||||||
|
;;
|
||||||
|
"-u" | "uninstall")
|
||||||
|
uninstallFunc
|
||||||
|
;;
|
||||||
|
"-up" | "update")
|
||||||
|
update "$@"
|
||||||
|
;;
|
||||||
|
"-bk" | "backup")
|
||||||
|
backup
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
helpFunc
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
# This scripts runs as root
|
# This scripts runs as root
|
||||||
|
|
||||||
setupVars="/etc/pivpn/openvpn/setupVars.conf"
|
setupVars="/etc/pivpn/openvpn/setupVars.conf"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
err() {
|
||||||
echo "::: Missing setup vars file!"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
exit 1
|
}
|
||||||
|
|
||||||
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
|
err "::: Missing setup vars file!"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
|
@ -15,41 +19,62 @@ echo -e "::::\t\t\e[4mPiVPN debug\e[0m\t\t ::::"
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e "::::\t\t\e[4mLatest commit\e[0m\t\t ::::"
|
echo -e "::::\t\t\e[4mLatest commit\e[0m\t\t ::::"
|
||||||
echo -n "Branch: "
|
echo -n "Branch: "
|
||||||
|
|
||||||
git --git-dir /usr/local/src/pivpn/.git rev-parse --abbrev-ref HEAD
|
git --git-dir /usr/local/src/pivpn/.git rev-parse --abbrev-ref HEAD
|
||||||
git --git-dir /usr/local/src/pivpn/.git log -n 1 --format='Commit: %H%nAuthor: %an%nDate: %ad%nSummary: %s'
|
git \
|
||||||
|
--git-dir /usr/local/src/pivpn/.git log -n 1 \
|
||||||
|
--format='Commit: %H%nAuthor: %an%nDate: %ad%nSummary: %s'
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e "::::\t \e[4mInstallation settings\e[0m \t ::::"
|
echo -e "::::\t \e[4mInstallation settings\e[0m \t ::::"
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
sed "s/$pivpnHOST/REDACTED/" < ${setupVars}
|
sed "s/${pivpnHOST}/REDACTED/" < "${setupVars}"
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: \e[4mServer configuration shown below\e[0m ::::"
|
echo -e ":::: \e[4mServer configuration shown below\e[0m ::::"
|
||||||
|
|
||||||
cat /etc/openvpn/server.conf
|
cat /etc/openvpn/server.conf
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: \e[4mClient template file shown below\e[0m ::::"
|
echo -e ":::: \e[4mClient template file shown below\e[0m ::::"
|
||||||
sed "s/$pivpnHOST/REDACTED/" < /etc/openvpn/easy-rsa/pki/Default.txt
|
|
||||||
|
sed "s/${pivpnHOST}/REDACTED/" < /etc/openvpn/easy-rsa/pki/Default.txt
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: \t\e[4mRecursive list of files in\e[0m\t ::::\n::: \e[4m/etc/openvpn/easy-rsa/pki shows below\e[0m :::"
|
echo -e ":::: \t\e[4mRecursive list of files in\e[0m\t ::::\n"
|
||||||
|
echo -e "::: \e[4m/etc/openvpn/easy-rsa/pki shows below\e[0m :::"
|
||||||
|
|
||||||
ls -LR /etc/openvpn/easy-rsa/pki/ -Ireqs -Icerts_by_serial
|
ls -LR /etc/openvpn/easy-rsa/pki/ -Ireqs -Icerts_by_serial
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e "::::\t\t\e[4mSelf check\e[0m\t\t ::::"
|
echo -e "::::\t\t\e[4mSelf check\e[0m\t\t ::::"
|
||||||
|
|
||||||
/opt/pivpn/self_check.sh "${VPN}"
|
/opt/pivpn/self_check.sh "${VPN}"
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: Having trouble connecting? Take a look at the FAQ:"
|
echo -e ":::: Having trouble connecting? Take a look at the FAQ:"
|
||||||
echo -e ":::: \e[1mhttps://docs.pivpn.io/faq\e[0m"
|
echo -e ":::: \e[1mhttps://docs.pivpn.io/faq\e[0m"
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
|
|
||||||
if [ "${PLAT}" != 'Alpine' ]; then
|
if [[ "${PLAT}" != 'Alpine' ]]; then
|
||||||
echo -e ":::: \e[4mSnippet of the server log\e[0m ::::"
|
echo -e ":::: \e[4mSnippet of the server log\e[0m ::::"
|
||||||
OVPNLOG="$(tail -n 20 /var/log/openvpn.log)"
|
OVPNLOG="$(tail -n 20 /var/log/openvpn.log)"
|
||||||
|
|
||||||
# Regular expession taken from https://superuser.com/a/202835, it will match invalid IPs
|
# Regular expession taken from https://superuser.com/a/202835,
|
||||||
# like 123.456.789.012 but it's fine since the log only contains valid ones.
|
# it will match invalid IPs like 123.456.789.012 but it's fine
|
||||||
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)")
|
# since the log only contains valid ones.
|
||||||
for IP in "${IPS_TO_HIDE[@]}"; do
|
declare -a IPS_TO_HIDE=("$(echo "${OVPNLOG}" \
|
||||||
OVPNLOG="${OVPNLOG//"$IP"/REDACTED}"
|
| grepcidr -v 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 \
|
||||||
done
|
| grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' \
|
||||||
|
| uniq)")
|
||||||
|
|
||||||
echo "$OVPNLOG"
|
for IP in "${IPS_TO_HIDE[@]}"; do
|
||||||
printf "=============================================\n"
|
OVPNLOG="${OVPNLOG//"$IP"/REDACTED}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "${OVPNLOG}"
|
||||||
|
printf "=============================================\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "::::\t\t\e[4mDebug complete\e[0m\t\t ::::"
|
echo -e "::::\t\t\e[4mDebug complete\e[0m\t\t ::::"
|
||||||
|
|
|
@ -1,172 +1,195 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
# PiVPN: revoke client script
|
# PiVPN: revoke client script
|
||||||
|
|
||||||
setupVars="/etc/pivpn/openvpn/setupVars.conf"
|
setupVars="/etc/pivpn/openvpn/setupVars.conf"
|
||||||
INDEX="/etc/openvpn/easy-rsa/pki/index.txt"
|
INDEX="/etc/openvpn/easy-rsa/pki/index.txt"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
|
err() {
|
||||||
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
helpFunc() {
|
helpFunc() {
|
||||||
echo "::: Revoke a client ovpn profile"
|
echo "::: Revoke a client ovpn profile"
|
||||||
echo ":::"
|
echo ":::"
|
||||||
echo "::: Usage: pivpn <-r|revoke> [-y|--yes] [-h|--help] [<client-1>] ... [<client-n>] ..."
|
echo -n "::: Usage: pivpn <-r|revoke> [-y|--yes] [-h|--help] "
|
||||||
echo ":::"
|
echo "[<client-1> ... [<client-2>] ...]"
|
||||||
echo "::: Commands:"
|
echo ":::"
|
||||||
echo "::: [none] Interactive mode"
|
echo "::: Commands:"
|
||||||
echo "::: <client> Client(s) to to revoke"
|
echo "::: [none] Interactive mode"
|
||||||
echo "::: -y,--yes Remove Client(s) without confirmation"
|
echo "::: <client> Client(s) to to revoke"
|
||||||
echo "::: -h,--help Show this help dialog"
|
echo "::: -y,--yes Remove Client(s) without confirmation"
|
||||||
|
echo "::: -h,--help Show this help dialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse input arguments
|
# Parse input arguments
|
||||||
while test $# -gt 0; do
|
while [[ "$#" -gt 0 ]]; do
|
||||||
_key="$1"
|
_key="${1}"
|
||||||
case "$_key" in
|
|
||||||
-h|--help)
|
case "${_key}" in
|
||||||
helpFunc
|
-h | --help)
|
||||||
exit 0
|
helpFunc
|
||||||
;;
|
exit 0
|
||||||
-y|--yes)
|
;;
|
||||||
CONFIRM=true
|
-y | --yes)
|
||||||
;;
|
CONFIRM=true
|
||||||
*)
|
;;
|
||||||
CERTS_TO_REVOKE+=("$1")
|
*)
|
||||||
;;
|
CERTS_TO_REVOKE+=("${1}")
|
||||||
esac
|
;;
|
||||||
shift
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ! -f "${INDEX}" ]; then
|
if [[ ! -f "${INDEX}" ]]; then
|
||||||
printf "The file: %s was not found\n" "$INDEX"
|
err "The file: ${INDEX} was not found"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Disabling SC2128, just checking if variable is empty or not
|
# Disabling SC2128, just checking if variable is empty or not
|
||||||
# shellcheck disable=SC2128
|
# shellcheck disable=SC2128
|
||||||
if [[ -z "${CERTS_TO_REVOKE}" ]]; then
|
if [[ -z "${CERTS_TO_REVOKE}" ]]; then
|
||||||
printf "\n"
|
printf "\n"
|
||||||
printf " ::\e[4m Certificate List \e[0m:: \n"
|
printf " ::\e[4m Certificate List \e[0m:: \n"
|
||||||
|
|
||||||
i=0
|
i=0
|
||||||
while read -r line || [ -n "$line" ]; do
|
while read -r line || [[ -n "${line}" ]]; do
|
||||||
STATUS=$(echo "$line" | awk '{print $1}')
|
STATUS=$(echo "${line}" | awk '{print $1}')
|
||||||
if [[ "${STATUS}" = "V" ]]; then
|
|
||||||
# Disabling SC2001 warning, suggested method doesn't work with regexp
|
|
||||||
# shellcheck disable=SC2001
|
|
||||||
NAME=$(echo "$line" | sed -e 's:.*/CN=::')
|
|
||||||
if [ "$i" != 0 ]; then
|
|
||||||
# Prevent printing "server" certificate
|
|
||||||
CERTS[$i]=$(echo -e "${NAME}")
|
|
||||||
fi
|
|
||||||
((i++))
|
|
||||||
fi
|
|
||||||
done <${INDEX}
|
|
||||||
|
|
||||||
i=1
|
if [[ "${STATUS}" == "V" ]]; then
|
||||||
len=${#CERTS[@]}
|
# Disabling SC2001 warning, suggested method doesn't work with regexp
|
||||||
while [ $i -le "${len}" ]; do
|
# shellcheck disable=SC2001
|
||||||
printf "%0${#len}s) %s\r\n" ${i} "${CERTS[(($i))]}"
|
NAME=$(echo "${line}" | sed -e 's:.*/CN=::')
|
||||||
((i++))
|
|
||||||
done
|
|
||||||
printf "\n"
|
|
||||||
|
|
||||||
echo -n "::: Please enter the Index/Name of the client to be revoked from the list above: "
|
if [[ "${i}" != 0 ]]; then
|
||||||
read -r NAME
|
# Prevent printing "server" certificate
|
||||||
|
CERTS["${i}"]=$(echo -e "${NAME}")
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -z "${NAME}" ]]; then
|
((i++))
|
||||||
echo "You can not leave this blank!"
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
done < "${INDEX}"
|
||||||
|
|
||||||
re='^[0-9]+$'
|
i=1
|
||||||
if [[ ${NAME} =~ $re ]] ; then
|
len="${#CERTS[@]}"
|
||||||
NAME=${CERTS[$((NAME))]}
|
while [[ "${i}" -le "${len}" ]]; do
|
||||||
|
printf "%0${#len}s) %s\r\n" "${i}" "${CERTS[(($i))]}"
|
||||||
|
((i++))
|
||||||
|
done
|
||||||
|
|
||||||
|
printf "\n"
|
||||||
|
echo -n "::: Please enter the Index/Name of the client to be revoked "
|
||||||
|
echo -n "from the list above: "
|
||||||
|
read -r NAME
|
||||||
|
|
||||||
|
if [[ -z "${NAME}" ]]; then
|
||||||
|
err "You can not leave this blank!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
re='^[0-9]+$'
|
||||||
|
if [[ "${NAME}" =~ $re ]]; then
|
||||||
|
NAME="${CERTS[$((NAME))]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for ((x = 1; x <= i; ++x)); do
|
||||||
|
if [[ "${CERTS[$x]}" == "${NAME}" ]]; then
|
||||||
|
VALID=1
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
for((x=1;x<=i;++x)); do
|
if [[ -z "${VALID}" ]]; then
|
||||||
if [ "${CERTS[$x]}" = "${NAME}" ]; then
|
err "You didn't enter a valid cert name!"
|
||||||
VALID=1
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "${VALID}" ]; then
|
CERTS_TO_REVOKE=("${NAME}")
|
||||||
printf "You didn't enter a valid cert name!\n"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
CERTS_TO_REVOKE=( "${NAME}" )
|
|
||||||
else
|
else
|
||||||
i=0
|
i=0
|
||||||
while read -r line || [ -n "$line" ]; do
|
while read -r line || [[ -n "${line}" ]]; do
|
||||||
STATUS=$(echo "$line" | awk '{print $1}')
|
STATUS=$(echo "${line}" | awk '{print $1}')
|
||||||
if [[ "${STATUS}" = "V" ]]; then
|
|
||||||
NAME=$(echo -e "$line" | sed -e 's:.*/CN=::')
|
|
||||||
CERTS[$i]=${NAME}
|
|
||||||
((i++))
|
|
||||||
fi
|
|
||||||
done <${INDEX}
|
|
||||||
|
|
||||||
for (( ii = 0; ii < ${#CERTS_TO_REVOKE[@]}; ii++)); do
|
if [[ "${STATUS}" == "V" ]]; then
|
||||||
VALID=0
|
NAME=$(echo -e "${line}" | sed -e 's:.*/CN=::')
|
||||||
for((x=1;x<=i;++x)); do
|
CERTS["${i}"]="${NAME}"
|
||||||
if [ "${CERTS[$x]}" = "${CERTS_TO_REVOKE[ii]}" ]; then
|
((i++))
|
||||||
VALID=1
|
fi
|
||||||
fi
|
done < "${INDEX}"
|
||||||
done
|
|
||||||
|
|
||||||
if [ "${VALID}" != 1 ]; then
|
for ((ii = 0; ii < ${#CERTS_TO_REVOKE[@]}; ii++)); do
|
||||||
printf "You passed an invalid cert name: '%s'! \n" "${CERTS_TO_REVOKE[ii]}"
|
VALID=0
|
||||||
exit 1
|
|
||||||
fi
|
for ((x = 1; x <= i; ++x)); do
|
||||||
|
if [[ "${CERTS[$x]}" == "${CERTS_TO_REVOKE[ii]}" ]]; then
|
||||||
|
VALID=1
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [[ "${VALID}" != 1 ]]; then
|
||||||
|
err "You passed an invalid cert name: '${CERTS_TO_REVOKE[ii]}'!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd /etc/openvpn/easy-rsa || exit
|
cd /etc/openvpn/easy-rsa || exit
|
||||||
|
|
||||||
for (( ii = 0; ii < ${#CERTS_TO_REVOKE[@]}; ii++)); do
|
for ((ii = 0; ii < ${#CERTS_TO_REVOKE[@]}; ii++)); do
|
||||||
if [ -n "$CONFIRM" ]; then
|
if [[ -n "${CONFIRM}" ]]; then
|
||||||
REPLY="y"
|
REPLY="y"
|
||||||
else
|
else
|
||||||
read -r -p "Do you really want to revoke '${CERTS_TO_REVOKE[ii]}'? [y/N] "
|
read -r -p "Do you really want to revoke '${CERTS_TO_REVOKE[ii]}'? [y/N] "
|
||||||
fi
|
fi
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
printf "\n::: Revoking certificate '%s'. \n" "${CERTS_TO_REVOKE[ii]}"
|
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
|
||||||
./easyrsa --batch revoke "${CERTS_TO_REVOKE[ii]}"
|
printf "\n::: Revoking certificate '%s'. \n" "${CERTS_TO_REVOKE[ii]}"
|
||||||
./easyrsa gen-crl
|
|
||||||
printf "\n::: Certificate revoked, and CRL file updated.\n"
|
./easyrsa --batch revoke "${CERTS_TO_REVOKE[ii]}"
|
||||||
printf "::: Removing certs and client configuration for this profile.\n"
|
./easyrsa gen-crl
|
||||||
rm -rf "pki/reqs/${CERTS_TO_REVOKE[ii]}.req"
|
|
||||||
rm -rf "pki/private/${CERTS_TO_REVOKE[ii]}.key"
|
printf "\n::: Certificate revoked, and CRL file updated.\n"
|
||||||
rm -rf "pki/issued/${CERTS_TO_REVOKE[ii]}.crt"
|
printf "::: Removing certs and client configuration for this profile.\n"
|
||||||
|
|
||||||
# Disabling SC2154 $pivpnNET sourced externally
|
rm -rf "pki/reqs/${CERTS_TO_REVOKE[ii]}.req"
|
||||||
# shellcheck disable=SC2154
|
rm -rf "pki/private/${CERTS_TO_REVOKE[ii]}.key"
|
||||||
# Grab the client IP address
|
rm -rf "pki/issued/${CERTS_TO_REVOKE[ii]}.crt"
|
||||||
NET_REDUCED="${pivpnNET::-2}"
|
|
||||||
STATIC_IP=$(grep -v "^#" /etc/openvpn/ccd/"${CERTS_TO_REVOKE[ii]}" | grep -w ifconfig-push | grep -oE "${NET_REDUCED}\.[0-9]{1,3}")
|
# Disabling SC2154 $pivpnNET sourced externally
|
||||||
rm -rf /etc/openvpn/ccd/"${CERTS_TO_REVOKE[ii]}"
|
# shellcheck disable=SC2154
|
||||||
|
# Grab the client IP address
|
||||||
# disablung warning SC2154, $install_home sourced externally
|
NET_REDUCED="${pivpnNET::-2}"
|
||||||
# shellcheck disable=SC2154
|
STATIC_IP="$(grep -v "^#" /etc/openvpn/ccd/"${CERTS_TO_REVOKE[ii]}" \
|
||||||
rm -rf "${install_home}/ovpns/${CERTS_TO_REVOKE[ii]}.ovpn"
|
| grep -w ifconfig-push \
|
||||||
rm -rf "/etc/openvpn/easy-rsa/pki/${CERTS_TO_REVOKE[ii]}.ovpn"
|
| grep -oE "${NET_REDUCED}\.[0-9]{1,3}")"
|
||||||
cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
|
rm -rf /etc/openvpn/ccd/"${CERTS_TO_REVOKE[ii]}"
|
||||||
|
|
||||||
# If using Pi-hole, remove the client from the hosts file
|
# disablung warning SC2154, $install_home sourced externally
|
||||||
if [ -f /etc/pivpn/hosts.openvpn ]; then
|
# shellcheck disable=SC2154
|
||||||
sed "\#${STATIC_IP} ${CERTS_TO_REVOKE[ii]}.pivpn#d" -i /etc/pivpn/hosts.openvpn
|
rm -rf "${install_home}/ovpns/${CERTS_TO_REVOKE[ii]}.ovpn"
|
||||||
if killall -SIGHUP pihole-FTL; then
|
rm -rf "/etc/openvpn/easy-rsa/pki/${CERTS_TO_REVOKE[ii]}.ovpn"
|
||||||
echo "::: Updated hosts file for Pi-hole"
|
cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
|
||||||
else
|
|
||||||
echo "::: Failed to reload pihole-FTL configuration"
|
# If using Pi-hole, remove the client from the hosts file
|
||||||
fi
|
if [[ -f /etc/pivpn/hosts.openvpn ]]; then
|
||||||
fi
|
sed \
|
||||||
|
-e "\#${STATIC_IP} ${CERTS_TO_REVOKE[ii]}.pivpn#d" \
|
||||||
|
-i /etc/pivpn/hosts.openvpn
|
||||||
|
|
||||||
|
if killall -SIGHUP pihole-FTL; then
|
||||||
|
echo "::: Updated hosts file for Pi-hole"
|
||||||
|
else
|
||||||
|
err "::: Failed to reload pihole-FTL configuration"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
printf "::: Completed!\n"
|
printf "::: Completed!\n"
|
||||||
|
|
|
@ -3,53 +3,69 @@
|
||||||
CHECK_PKG_INSTALLED='dpkg-query -s'
|
CHECK_PKG_INSTALLED='dpkg-query -s'
|
||||||
|
|
||||||
if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then
|
if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then
|
||||||
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Must be root to use this tool
|
# Must be root to use this tool
|
||||||
if [ $EUID -ne 0 ]; then
|
if [[ "${EUID}" -ne 0 ]]; then
|
||||||
if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then
|
if ${CHECK_PKG_INSTALLED} sudo &> /dev/null; then
|
||||||
export SUDO="sudo"
|
export SUDO="sudo"
|
||||||
else
|
else
|
||||||
echo "::: Please install sudo or run this as root."
|
err "::: Please install sudo or run this as root."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
scriptDir="/opt/pivpn"
|
scriptDir="/opt/pivpn"
|
||||||
|
|
||||||
uninstallServer(){
|
err() {
|
||||||
$SUDO ${scriptDir}/uninstall.sh
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backup(){
|
uninstallServer() {
|
||||||
$SUDO ${scriptDir}/backup.sh
|
${SUDO} "${scriptDir}/uninstall.sh"
|
||||||
exit "$?"
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
showHelp(){
|
backup() {
|
||||||
echo "::: To pass off to the pivpn command for each protocol"
|
${SUDO} "${scriptDir}/backup.sh"
|
||||||
echo ":::"
|
exit "${?}"
|
||||||
echo "::: Usage: pivpn wg <command> [option]"
|
|
||||||
echo "::: Usage: pivpn ovpn <command> [option]"
|
|
||||||
echo ":::"
|
|
||||||
echo "::: -h, help Show this help dialog"
|
|
||||||
echo "::: -u, uninstall Uninstall pivpn from your system!"
|
|
||||||
echo "::: -bk, backup Backup VPN configs and user profiles"
|
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ $# = 0 ]; then
|
showHelp() {
|
||||||
showHelp
|
echo "::: To pass off to the pivpn command for each protocol"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Usage: pivpn wg <command> [option]"
|
||||||
|
echo "::: Usage: pivpn ovpn <command> [option]"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: -h, help Show this help dialog"
|
||||||
|
echo "::: -u, uninstall Uninstall pivpn from your system!"
|
||||||
|
echo "::: -bk, backup Backup VPN configs and user profiles"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$#" == 0 ]]; then
|
||||||
|
showHelp
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Handle redirecting to specific functions based on arguments
|
# Handle redirecting to specific functions based on arguments
|
||||||
case "$1" in
|
case "${1}" in
|
||||||
wg ) "${scriptDir}/wireguard/pivpn.sh" "${@:2}";;
|
wg)
|
||||||
ovpn ) "${scriptDir}/openvpn/pivpn.sh" "${@:2}";;
|
"${scriptDir}/wireguard/pivpn.sh" "${@:2}"
|
||||||
"-h" | "help" ) showHelp;;
|
;;
|
||||||
"-u" | "uninstall" ) uninstallServer;;
|
ovpn)
|
||||||
"-bk" | "backup" ) backup ;;
|
"${scriptDir}/openvpn/pivpn.sh" "${@:2}"
|
||||||
* ) showHelp;;
|
;;
|
||||||
|
"-h" | "help")
|
||||||
|
showHelp
|
||||||
|
;;
|
||||||
|
"-u" | "uninstall")
|
||||||
|
uninstallServer
|
||||||
|
;;
|
||||||
|
"-bk" | "backup")
|
||||||
|
backup
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
showHelp
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -1,217 +1,340 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
PLAT=$(grep -sEe '^NAME\=' /etc/os-release | sed -E -e "s/NAME\=[\'\"]?([^ ]*).*/\1/")
|
PLAT="$(grep -sEe '^NAME\=' /etc/os-release \
|
||||||
|
| sed -E -e "s/NAME\=[\'\"]?([^ ]*).*/\1/")"
|
||||||
|
|
||||||
# dual protocol, VPN type supplied as $1
|
# dual protocol, VPN type supplied as $1
|
||||||
VPN=$1
|
VPN="${1}"
|
||||||
setupVars="/etc/pivpn/${VPN}/setupVars.conf"
|
setupVars="/etc/pivpn/${VPN}/setupVars.conf"
|
||||||
ERR=0
|
ERR=0
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
err() {
|
||||||
echo "::: Missing setup vars file!"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
exit 1
|
}
|
||||||
|
|
||||||
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
|
err "::: Missing setup vars file!"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# SC1090 disabled as setupVars file differs from system to system
|
# SC1090 disabled as setupVars file differs from system to system
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
if [ "$VPN" = "wireguard" ]; then
|
if [[ "${VPN}" == "wireguard" ]]; then
|
||||||
VPN_SERVICE="wg-quick@wg0"
|
VPN_PRETTY_NAME="WireGuard"
|
||||||
|
VPN_SERVICE="wg-quick@wg0"
|
||||||
|
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
VPN_SERVICE='wg-quick'
|
VPN_SERVICE='wg-quick'
|
||||||
fi
|
fi
|
||||||
|
elif [[ "${VPN}" == "openvpn" ]]; then
|
||||||
VPN_PRETTY_NAME="WireGuard"
|
VPN_SERVICE="openvpn"
|
||||||
elif [ "$VPN" = "openvpn" ]; then
|
VPN_PRETTY_NAME="OpenVPN"
|
||||||
VPN_SERVICE="openvpn"
|
|
||||||
VPN_PRETTY_NAME="OpenVPN"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(</proc/sys/net/ipv4/ip_forward)" -eq 1 ]; then
|
if [[ "$(< /proc/sys/net/ipv4/ip_forward)" -eq 1 ]]; then
|
||||||
echo ":: [OK] IP forwarding is enabled"
|
echo ":: [OK] IP forwarding is enabled"
|
||||||
else
|
else
|
||||||
ERR=1
|
ERR=1
|
||||||
read -r -p ":: [ERR] IP forwarding is not enabled, attempt fix now? [Y/n] " REPLY
|
read -r \
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
-p ":: [ERR] IP forwarding is not enabled, attempt fix now? [Y/n] " \
|
||||||
sed -i '/net.ipv4.ip_forward=1/s/^#//g' /etc/sysctl.conf
|
REPLY
|
||||||
sysctl -p
|
|
||||||
echo "Done"
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
fi
|
sed -i '/net.ipv4.ip_forward=1/s/^#//g' /etc/sysctl.conf
|
||||||
|
sysctl -p
|
||||||
|
echo "Done"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$USING_UFW" -eq 0 ]; then
|
if [[ "${USING_UFW}" -eq 0 ]]; then
|
||||||
|
# Disabled SC Warnings for SC2154, values
|
||||||
|
# for variables are sourced from setupVars
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
if iptables \
|
||||||
|
-t nat \
|
||||||
|
-C POSTROUTING \
|
||||||
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
|
-o "${IPv4dev}" \
|
||||||
|
-j MASQUERADE \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-nat-rule" &> /dev/null; then
|
||||||
|
echo ":: [OK] Iptables MASQUERADE rule set"
|
||||||
|
else
|
||||||
|
ERR=1
|
||||||
|
echo -n ":: [ERR] Iptables MASQUERADE rule is not set, "
|
||||||
|
echo -n "attempt fix now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
# Disabled SC Warnings for SC2154, values for variables are sourced from setupVars
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
# shellcheck disable=SC2154
|
iptables \
|
||||||
if iptables -t nat -C POSTROUTING -s "${pivpnNET}/${subnetClass}" -o "${IPv4dev}" -j MASQUERADE -m comment --comment "${VPN}-nat-rule" &> /dev/null; then
|
-t nat \
|
||||||
echo ":: [OK] Iptables MASQUERADE rule set"
|
-I POSTROUTING \
|
||||||
else
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
ERR=1
|
-o "${IPv4dev}" \
|
||||||
read -r -p ":: [ERR] Iptables MASQUERADE rule is not set, attempt fix now? [Y/n] " REPLY
|
-j MASQUERADE \
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
-m comment \
|
||||||
iptables -t nat -I POSTROUTING -s "${pivpnNET}/${subnetClass}" -o "${IPv4dev}" -j MASQUERADE -m comment --comment "${VPN}-nat-rule"
|
--comment "${VPN}-nat-rule"
|
||||||
iptables-save > /etc/iptables/rules.v4
|
|
||||||
echo "Done"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$INPUT_CHAIN_EDITED" -eq 1 ]; then
|
iptables-save > /etc/iptables/rules.v4
|
||||||
|
echo "Done"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Disabled SC Warnings for SC2154, values for variables are sourced from setupVars
|
if [[ "${INPUT_CHAIN_EDITED}" -eq 1 ]]; then
|
||||||
# shellcheck disable=SC2154
|
# Disabled SC Warnings for SC2154, values
|
||||||
if iptables -C INPUT -i "${IPv4dev}" -p "${pivpnPROTO}" --dport "${pivpnPORT}" -j ACCEPT -m comment --comment "${VPN}-input-rule" &> /dev/null; then
|
# for variables are sourced from setupVars
|
||||||
echo ":: [OK] Iptables INPUT rule set"
|
# shellcheck disable=SC2154
|
||||||
else
|
if iptables \
|
||||||
ERR=1
|
-C INPUT \
|
||||||
read -r -p ":: [ERR] Iptables INPUT rule is not set, attempt fix now? [Y/n] " REPLY
|
-i "${IPv4dev}" \
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
-p "${pivpnPROTO}" \
|
||||||
iptables -I INPUT 1 -i "${IPv4dev}" -p "${pivpnPROTO}" --dport "${pivpnPORT}" -j ACCEPT -m comment --comment "${VPN}-input-rule"
|
--dport "${pivpnPORT}" \
|
||||||
iptables-save > /etc/iptables/rules.v4
|
-j ACCEPT \
|
||||||
echo "Done"
|
-m comment \
|
||||||
fi
|
--comment "${VPN}-input-rule" &> /dev/null; then
|
||||||
fi
|
echo ":: [OK] Iptables INPUT rule set"
|
||||||
fi
|
else
|
||||||
|
ERR=1
|
||||||
|
read -r \
|
||||||
|
-p ":: [ERR] Iptables INPUT rule is not set, attempt fix now? [Y/n] " \
|
||||||
|
REPLY
|
||||||
|
|
||||||
if [ "$FORWARD_CHAIN_EDITED" -eq 1 ]; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
|
iptables \
|
||||||
|
-I INPUT 1 \
|
||||||
|
-i "${IPv4dev}" \
|
||||||
|
-p "${pivpnPROTO}" \
|
||||||
|
--dport "${pivpnPORT}" \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-input-rule"
|
||||||
|
|
||||||
# Disabled SC Warnings for SC2154, values for variables are sourced from setupVars
|
iptables-save > /etc/iptables/rules.v4
|
||||||
# shellcheck disable=SC2154
|
echo "Done"
|
||||||
if iptables -C FORWARD -s "${pivpnNET}/${subnetClass}" -i "${pivpnDEV}" -o "${IPv4dev}" -j ACCEPT -m comment --comment "${VPN}-forward-rule" &> /dev/null; then
|
fi
|
||||||
echo ":: [OK] Iptables FORWARD rule set"
|
fi
|
||||||
else
|
fi
|
||||||
ERR=1
|
|
||||||
read -r -p ":: [ERR] Iptables FORWARD rule is not set, attempt fix now? [Y/n] " REPLY
|
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
|
||||||
iptables -I FORWARD 1 -d "${pivpnNET}/${subnetClass}" -i "${IPv4dev}" -o "${pivpnDEV}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "${VPN}-forward-rule"
|
|
||||||
iptables -I FORWARD 2 -s "${pivpnNET}/${subnetClass}" -i "${pivpnDEV}" -o "${IPv4dev}" -j ACCEPT -m comment --comment "${VPN}-forward-rule"
|
|
||||||
iptables-save > /etc/iptables/rules.v4
|
|
||||||
echo "Done"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
if [[ "${FORWARD_CHAIN_EDITED}" -eq 1 ]]; then
|
||||||
|
# Disabled SC Warnings for SC2154, values
|
||||||
|
# for variables are sourced from setupVars
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
if iptables \
|
||||||
|
-C FORWARD \
|
||||||
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
|
-i "${pivpnDEV}" \
|
||||||
|
-o "${IPv4dev}" \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-forward-rule" &> /dev/null; then
|
||||||
|
echo ":: [OK] Iptables FORWARD rule set"
|
||||||
|
else
|
||||||
|
ERR=1
|
||||||
|
echo -n ":: [ERR] Iptables FORWARD rule is not set, "
|
||||||
|
echo -n "attempt fix now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
|
iptables \
|
||||||
|
-I FORWARD 1 \
|
||||||
|
-d "${pivpnNET}/${subnetClass}" \
|
||||||
|
-i "${IPv4dev}" \
|
||||||
|
-o "${pivpnDEV}" \
|
||||||
|
-m conntrack \
|
||||||
|
--ctstate RELATED,ESTABLISHED \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-forward-rule"
|
||||||
|
|
||||||
|
iptables \
|
||||||
|
-I FORWARD 2 \
|
||||||
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
|
-i "${pivpnDEV}" \
|
||||||
|
-o "${IPv4dev}" \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-forward-rule"
|
||||||
|
|
||||||
|
iptables-save > /etc/iptables/rules.v4
|
||||||
|
echo "Done"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
|
if LANG="en_US.UTF-8" ufw status | grep -qw 'active'; then
|
||||||
|
echo ":: [OK] Ufw is enabled"
|
||||||
|
else
|
||||||
|
ERR=1
|
||||||
|
echo -n ":: [ERR] Ufw is not enabled, "
|
||||||
|
echo -n "try to enable now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
if LANG="en_US.UTF-8" ufw status | grep -qw 'active'; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
echo ":: [OK] Ufw is enabled"
|
ufw enable
|
||||||
else
|
fi
|
||||||
ERR=1
|
fi
|
||||||
read -r -p ":: [ERR] Ufw is not enabled, try to enable now? [Y/n] " REPLY
|
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
|
||||||
ufw enable
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if iptables -t nat -C POSTROUTING -s "${pivpnNET}/${subnetClass}" -o "${IPv4dev}" -j MASQUERADE -m comment --comment "${VPN}-nat-rule" &> /dev/null; then
|
if iptables \
|
||||||
echo ":: [OK] Iptables MASQUERADE rule set"
|
-t nat \
|
||||||
else
|
-C POSTROUTING \
|
||||||
ERR=1
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
read -r -p ":: [ERR] Iptables MASQUERADE rule is not set, attempt fix now? [Y/n] " REPLY
|
-o "${IPv4dev}" \
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
-j MASQUERADE \
|
||||||
sed "/delete these required/i *nat\n:POSTROUTING ACCEPT [0:0]\n-I POSTROUTING -s ${pivpnNET}/${subnetClass} -o ${IPv4dev} -j MASQUERADE -m comment --comment ${VPN}-nat-rule\nCOMMIT\n" -i /etc/ufw/before.rules
|
-m comment \
|
||||||
ufw reload
|
--comment "${VPN}-nat-rule" &> /dev/null; then
|
||||||
echo "Done"
|
echo ":: [OK] Iptables MASQUERADE rule set"
|
||||||
fi
|
else
|
||||||
fi
|
ERR=1
|
||||||
|
echo -n ":: [ERR] Iptables MASQUERADE rule is not set, "
|
||||||
|
echo -n "attempt fix now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
if iptables -C ufw-user-input -p "${pivpnPROTO}" --dport "${pivpnPORT}" -j ACCEPT &> /dev/null; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
echo ":: [OK] Ufw input rule set"
|
sed_pattern='/delete these required/i'
|
||||||
else
|
sed_pattern="${sed_pattern} *nat\n:POSTROUTING ACCEPT [0:0]\n"
|
||||||
ERR=1
|
sed_pattern="${sed_pattern} -I POSTROUTING"
|
||||||
read -r -p ":: [ERR] Ufw input rule is not set, attempt fix now? [Y/n] " REPLY
|
sed_pattern="${sed_pattern} -s ${pivpnNET}/${subnetClass}"
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
sed_pattern="${sed_pattern} -o ${IPv4dev}"
|
||||||
ufw insert 1 allow "${pivpnPORT}"/"${pivpnPROTO}"
|
sed_pattern="${sed_pattern} -j MASQUERADE"
|
||||||
ufw reload
|
sed_pattern="${sed_pattern} -m comment"
|
||||||
echo "Done"
|
sed_pattern="${sed_pattern} --comment ${VPN}-nat-rule\n"
|
||||||
fi
|
sed_pattern="${sed_pattern}COMMIT\n"
|
||||||
fi
|
|
||||||
|
|
||||||
if iptables -C ufw-user-forward -i "${pivpnDEV}" -o "${IPv4dev}" -s "${pivpnNET}/${subnetClass}" -j ACCEPT &> /dev/null; then
|
sed "${sed_pattern}" -i /etc/ufw/before.rules
|
||||||
echo ":: [OK] Ufw forwarding rule set"
|
ufw reload
|
||||||
else
|
echo "Done"
|
||||||
ERR=1
|
unset sed_pattern
|
||||||
read -r -p ":: [ERR] Ufw forwarding rule is not set, attempt fix now? [Y/n] " REPLY
|
fi
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
fi
|
||||||
ufw route insert 1 allow in on "${pivpnDEV}" from "${pivpnNET}/${subnetClass}" out on "${IPv4dev}" to any
|
|
||||||
ufw reload
|
|
||||||
echo "Done"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
if iptables \
|
||||||
|
-C ufw-user-input \
|
||||||
|
-p "${pivpnPROTO}" \
|
||||||
|
--dport "${pivpnPORT}" \
|
||||||
|
-j ACCEPT &> /dev/null; then
|
||||||
|
echo ":: [OK] Ufw input rule set"
|
||||||
|
else
|
||||||
|
ERR=1
|
||||||
|
read -r \
|
||||||
|
-p ":: [ERR] Ufw input rule is not set, attempt fix now? [Y/n] " \
|
||||||
|
REPLY
|
||||||
|
|
||||||
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
|
ufw insert 1 allow "${pivpnPORT}"/"${pivpnPROTO}"
|
||||||
|
ufw reload
|
||||||
|
echo "Done"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if iptables \
|
||||||
|
-C ufw-user-forward \
|
||||||
|
-i "${pivpnDEV}" \
|
||||||
|
-o "${IPv4dev}" \
|
||||||
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
|
-j ACCEPT &> /dev/null; then
|
||||||
|
echo ":: [OK] Ufw forwarding rule set"
|
||||||
|
else
|
||||||
|
ERR=1
|
||||||
|
read -r \
|
||||||
|
-p ":: [ERR] Ufw forwarding rule is not set, attempt fix now? [Y/n] " \
|
||||||
|
REPLY
|
||||||
|
|
||||||
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
|
ufw route insert 1 allow in on "${pivpnDEV}" \
|
||||||
|
from "${pivpnNET}/${subnetClass}" out on "${IPv4dev}" to any
|
||||||
|
ufw reload
|
||||||
|
echo "Done"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
if [ "$(rc-service "${VPN_SERVICE}" status | sed -E -e 's/.*status\: (.*)/\1/')" == 'started' ]; then
|
if [[ "$(rc-service "${VPN_SERVICE}" status \
|
||||||
echo ":: [OK] ${VPN_PRETTY_NAME} is running"
|
| sed -E -e 's/.*status\: (.*)/\1/')" == 'started' ]]; then
|
||||||
else
|
echo ":: [OK] ${VPN_PRETTY_NAME} is running"
|
||||||
ERR=1
|
else
|
||||||
read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not running, try to start now? [Y/n] " REPLY
|
ERR=1
|
||||||
|
echo -n ":: [ERR] ${VPN_PRETTY_NAME} is not running, "
|
||||||
|
echo -n "try to start now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
rc-service -s "${VPN_SERVICE}" restart
|
rc-service -s "${VPN_SERVICE}" restart
|
||||||
rc-service -N "${VPN_SERVICE}" start
|
rc-service -N "${VPN_SERVICE}" start
|
||||||
|
echo "Done"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Done"
|
if rc-update show default \
|
||||||
fi
|
| grep -sEe "\s*${VPN_SERVICE} .*" &> /dev/null; then
|
||||||
fi
|
echo -n ":: [OK] ${VPN_PRETTY_NAME} is enabled "
|
||||||
|
echo "(it will automatically start on reboot)"
|
||||||
|
else
|
||||||
|
ERR=1
|
||||||
|
echo -n ":: [ERR] ${VPN_PRETTY_NAME} is not enabled, "
|
||||||
|
echo -n "try to enable now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
if rc-update show default | grep -sEe "\s*${VPN_SERVICE} .*" &> /dev/null; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
echo ":: [OK] ${VPN_PRETTY_NAME} is enabled (it will automatically start on reboot)"
|
rc-update add "${VPN_SERVICE}" default
|
||||||
else
|
echo "Done"
|
||||||
ERR=1
|
fi
|
||||||
read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not enabled, try to enable now? [Y/n] " REPLY
|
fi
|
||||||
|
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
|
||||||
rc-update add "${VPN_SERVICE}" default
|
|
||||||
|
|
||||||
echo "Done"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
if systemctl is-active -q "${VPN_SERVICE}"; then
|
if systemctl is-active -q "${VPN_SERVICE}"; then
|
||||||
echo ":: [OK] ${VPN_PRETTY_NAME} is running"
|
echo ":: [OK] ${VPN_PRETTY_NAME} is running"
|
||||||
else
|
else
|
||||||
ERR=1
|
ERR=1
|
||||||
read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not running, try to start now? [Y/n] " REPLY
|
echo -n ":: [ERR] ${VPN_PRETTY_NAME} is not running, "
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
echo -n "try to start now? [Y/n] "
|
||||||
systemctl start "${VPN_SERVICE}"
|
read -r REPLY
|
||||||
echo "Done"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if systemctl is-enabled -q "${VPN_SERVICE}"; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
echo ":: [OK] ${VPN_PRETTY_NAME} is enabled (it will automatically start on reboot)"
|
systemctl start "${VPN_SERVICE}"
|
||||||
else
|
echo "Done"
|
||||||
ERR=1
|
fi
|
||||||
read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not enabled, try to enable now? [Y/n] " REPLY
|
fi
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
|
||||||
systemctl enable "${VPN_SERVICE}"
|
if systemctl is-enabled -q "${VPN_SERVICE}"; then
|
||||||
echo "Done"
|
echo ":: [OK] ${VPN_PRETTY_NAME} is enabled "
|
||||||
fi
|
echo "(it will automatically start on reboot)"
|
||||||
fi
|
else
|
||||||
|
ERR=1
|
||||||
|
echo -n ":: [ERR] ${VPN_PRETTY_NAME} is not enabled, "
|
||||||
|
echo -n "try to enable now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
|
systemctl enable "${VPN_SERVICE}"
|
||||||
|
echo "Done"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# grep -w (whole word) is used so port 11940 won't match when looking for 1194
|
# grep -w (whole word) is used so port 11940 won't match when looking for 1194
|
||||||
if netstat -antu | grep -wqE "${pivpnPROTO}.*${pivpnPORT}"; then
|
if netstat -antu | grep -wqE "${pivpnPROTO}.*${pivpnPORT}"; then
|
||||||
echo ":: [OK] ${VPN_PRETTY_NAME} is listening on port ${pivpnPORT}/${pivpnPROTO}"
|
echo -n ":: [OK] ${VPN_PRETTY_NAME} is listening "
|
||||||
|
echo "on port ${pivpnPORT}/${pivpnPROTO}"
|
||||||
else
|
else
|
||||||
ERR=1
|
ERR=1
|
||||||
read -r -p ":: [ERR] ${VPN_PRETTY_NAME} is not listening, try to restart now? [Y/n] " REPLY
|
echo -n ":: [ERR] ${VPN_PRETTY_NAME} is not listening, "
|
||||||
|
echo -n "try to restart now? [Y/n] "
|
||||||
|
read -r REPLY
|
||||||
|
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]] || [[ -z ${REPLY} ]]; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]] || [[ -z "${REPLY}" ]]; then
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
rc-service -s "${VPN_SERVICE}" restart
|
rc-service -s "${VPN_SERVICE}" restart
|
||||||
rc-service -N "${VPN_SERVICE}" start
|
rc-service -N "${VPN_SERVICE}" start
|
||||||
else
|
else
|
||||||
systemctl restart "${VPN_SERVICE}"
|
systemctl restart "${VPN_SERVICE}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Done"
|
echo "Done"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$ERR" -eq 1 ]; then
|
if [[ "${ERR}" -eq 1 ]]; then
|
||||||
echo -e "[INFO] Run \e[1mpivpn -d\e[0m again to see if we detect issues"
|
echo -e "[INFO] Run \e[1mpivpn -d\e[0m again to see if we detect issues"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
# PiVPN: Uninstall Script
|
# PiVPN: Uninstall Script
|
||||||
|
|
||||||
### FIXME: global: config storage, refactor all scripts to adhere to the storage
|
### FIXME:
|
||||||
### FIXME: use variables where appropriate, reduce magic numbers by 99.9%, at least.
|
### 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.
|
# 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)
|
screen_size="$(stty size 2> /dev/null || echo 24 80)"
|
||||||
rows=$(echo "$screen_size" | awk '{print $1}')
|
rows="$(echo "${screen_size}" | awk '{print $1}')"
|
||||||
columns=$(echo "$screen_size" | awk '{print $2}')
|
columns="$(echo "${screen_size}" | awk '{print $2}')"
|
||||||
|
|
||||||
# Divide by two so the dialogs take up half of the screen, which looks nice.
|
# Divide by two so the dialogs take up half of the screen, which looks nice.
|
||||||
r=$(( rows / 2 ))
|
r=$((rows / 2))
|
||||||
c=$(( columns / 2 ))
|
c=$((columns / 2))
|
||||||
# Unless the screen is tiny
|
# Unless the screen is tiny
|
||||||
r=$(( r < 20 ? 20 : r ))
|
r=$((r < 20 ? 20 : r))
|
||||||
c=$(( c < 70 ? 70 : c ))
|
c=$((c < 70 ? 70 : c))
|
||||||
|
|
||||||
PKG_MANAGER="apt-get"
|
PKG_MANAGER="apt-get"
|
||||||
PKG_REMOVE="${PKG_MANAGER} -y remove --purge"
|
PKG_REMOVE="${PKG_MANAGER} -y remove --purge"
|
||||||
|
@ -24,295 +26,391 @@ setupConfigDir="/etc/pivpn"
|
||||||
pivpnFilesDir="/usr/local/src/pivpn"
|
pivpnFilesDir="/usr/local/src/pivpn"
|
||||||
pivpnScriptDir="/opt/pivpn"
|
pivpnScriptDir="/opt/pivpn"
|
||||||
|
|
||||||
PLAT=$(grep -sEe '^NAME\=' /etc/os-release | sed -E -e "s/NAME\=[\'\"]?([^ ]*).*/\1/")
|
PLAT="$(grep -sEe '^NAME\=' /etc/os-release \
|
||||||
|
| sed -E -e "s/NAME\=[\'\"]?([^ ]*).*/\1/")"
|
||||||
|
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
PKG_MANAGER='apk'
|
PKG_MANAGER='apk'
|
||||||
PKG_REMOVE="${PKG_MANAGER} --no-cache --purge del -r"
|
PKG_REMOVE="${PKG_MANAGER} --no-cache --purge del -r"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
UPDATE_PKG_CACHE="${PKG_MANAGER} update"
|
UPDATE_PKG_CACHE="${PKG_MANAGER} update"
|
||||||
|
|
||||||
if [ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ] && [ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]; then
|
if [[ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]] \
|
||||||
vpnStillExists=1
|
&& [[ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]]; then
|
||||||
|
vpnStillExists=1
|
||||||
|
|
||||||
# Two protocols have been installed, check if the script has passed
|
# Two protocols have been installed, check if the script has passed
|
||||||
# an argument, otherwise ask the user which one he wants to remove
|
# an argument, otherwise ask the user which one he wants to remove
|
||||||
if [ $# -ge 1 ]; then
|
if [[ "$#" -ge 1 ]]; then
|
||||||
VPN="$1"
|
VPN="${1}"
|
||||||
echo "::: Uninstalling VPN: $VPN"
|
echo "::: Uninstalling VPN: ${VPN}"
|
||||||
else
|
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)
|
chooseVPNCmd=(whiptail
|
||||||
VPNChooseOptions=(WireGuard "" on
|
--backtitle "Setup PiVPN"
|
||||||
OpenVPN "" off)
|
--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
|
if VPN="$("${chooseVPNCmd[@]}" "${VPNChooseOptions[@]}" 2>&1 \
|
||||||
echo "::: Uninstalling VPN: $VPN"
|
> /dev/tty)"; then
|
||||||
VPN="${VPN,,}"
|
echo "::: Uninstalling VPN: ${VPN}"
|
||||||
else
|
VPN="${VPN,,}"
|
||||||
echo "::: Cancel selected, exiting...."
|
else
|
||||||
exit 1
|
err "::: Cancel selected, exiting...."
|
||||||
fi
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
setupVars="${setupConfigDir}/${VPN}/${setupVarsFile}"
|
setupVars="${setupConfigDir}/${VPN}/${setupVarsFile}"
|
||||||
else
|
else
|
||||||
vpnStillExists=0
|
vpnStillExists=0
|
||||||
|
|
||||||
if [ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]; then
|
if [[ -r "${setupConfigDir}/wireguard/${setupVarsFile}" ]]; then
|
||||||
setupVars="${setupConfigDir}/wireguard/${setupVarsFile}"
|
setupVars="${setupConfigDir}/wireguard/${setupVarsFile}"
|
||||||
elif [ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]; then
|
elif [[ -r "${setupConfigDir}/openvpn/${setupVarsFile}" ]]; then
|
||||||
setupVars="${setupConfigDir}/openvpn/${setupVarsFile}"
|
setupVars="${setupConfigDir}/openvpn/${setupVarsFile}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
|
err() {
|
||||||
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
### FIXME: introduce global lib
|
### FIXME: introduce global lib
|
||||||
spinner(){
|
spinner() {
|
||||||
local pid=$1
|
local pid="${1}"
|
||||||
local delay=0.50
|
local delay=0.50
|
||||||
local spinstr='/-\|'
|
local spinstr='/-\|'
|
||||||
while ps a | awk '{print $1}' | grep -q "$pid"; do
|
|
||||||
local temp=${spinstr#?}
|
while ps a | awk '{print $1}' | grep -q "${pid}"; do
|
||||||
printf " [%c] " "$spinstr"
|
local temp="${spinstr#?}"
|
||||||
local spinstr=$temp${spinstr%"$temp"}
|
printf " [%c] " "${spinstr}"
|
||||||
sleep $delay
|
local spinstr="${temp}${spinstr%"$temp"}"
|
||||||
printf "\\b\\b\\b\\b\\b\\b"
|
sleep "${delay}"
|
||||||
done
|
printf "\\b\\b\\b\\b\\b\\b"
|
||||||
printf " \\b\\b\\b\\b"
|
done
|
||||||
|
|
||||||
|
printf " \\b\\b\\b\\b"
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAll(){
|
removeAll() {
|
||||||
# Stopping and disabling services
|
# Stopping and disabling services
|
||||||
echo "::: Stopping and disabling services..."
|
echo "::: Stopping and disabling services..."
|
||||||
|
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
if [ "${VPN}" = "wireguard" ]; then
|
if [[ "${VPN}" == "wireguard" ]]; then
|
||||||
rc-service wg-quick stop
|
rc-service wg-quick stop
|
||||||
rc-update del wg-quick default &> /dev/null
|
rc-update del wg-quick default &> /dev/null
|
||||||
elif [ "${VPN}" = "openvpn" ]; then
|
elif [[ "${VPN}" == "openvpn" ]]; then
|
||||||
rc-service openvpn stop
|
rc-service openvpn stop
|
||||||
rc-update del openvpn default &> /dev/null
|
rc-update del openvpn default &> /dev/null
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ "${VPN}" = "wireguard" ]; then
|
if [[ "${VPN}" == "wireguard" ]]; then
|
||||||
systemctl stop wg-quick@wg0
|
systemctl stop wg-quick@wg0
|
||||||
systemctl disable wg-quick@wg0 &> /dev/null
|
systemctl disable wg-quick@wg0 &> /dev/null
|
||||||
elif [ "${VPN}" = "openvpn" ]; then
|
elif [[ "${VPN}" == "openvpn" ]]; then
|
||||||
systemctl stop openvpn
|
systemctl stop openvpn
|
||||||
systemctl disable openvpn &> /dev/null
|
systemctl disable openvpn &> /dev/null
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Removing firewall rules.
|
# Removing firewall rules.
|
||||||
echo "::: Removing firewall rules..."
|
echo "::: Removing firewall rules..."
|
||||||
|
|
||||||
if [ "$USING_UFW" -eq 1 ]; then
|
|
||||||
|
|
||||||
|
if [[ "${USING_UFW}" -eq 1 ]]; then
|
||||||
### Ignoring SC2154, value sourced from setupVars file
|
### Ignoring SC2154, value sourced from setupVars file
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
ufw delete allow "${pivpnPORT}"/"${pivpnPROTO}" > /dev/null
|
ufw delete allow "${pivpnPORT}/${pivpnPROTO}" > /dev/null
|
||||||
### Ignoring SC2154, value sourced from setupVars file
|
### Ignoring SC2154, value sourced from setupVars file
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
ufw route delete allow in on "${pivpnDEV}" from "${pivpnNET}/${subnetClass}" out on "${IPv4dev}" to any > /dev/null
|
ufw route delete allow in on "${pivpnDEV}" \
|
||||||
ufw delete allow in on "${pivpnDEV}" to any port 53 from "${pivpnNET}/${subnetClass}" >/dev/null
|
from "${pivpnNET}/${subnetClass}" out on "${IPv4dev}" to any > /dev/null
|
||||||
sed "/-I POSTROUTING -s ${pivpnNET}\\/${subnetClass} -o ${IPv4dev} -j MASQUERADE -m comment --comment ${VPN}-nat-rule/d" -i /etc/ufw/before.rules
|
ufw delete allow in on "${pivpnDEV}" to any port 53 \
|
||||||
iptables -t nat -D POSTROUTING -s "${pivpnNET}/${subnetClass}" -o "${IPv4dev}" -j MASQUERADE -m comment --comment "${VPN}-nat-rule"
|
from "${pivpnNET}/${subnetClass}" > /dev/null
|
||||||
ufw reload &> /dev/null
|
|
||||||
|
|
||||||
elif [ "$USING_UFW" -eq 0 ]; then
|
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
|
||||||
|
|
||||||
if [ "$INPUT_CHAIN_EDITED" -eq 1 ]; then
|
iptables \
|
||||||
iptables -D INPUT -i "${IPv4dev}" -p "${pivpnPROTO}" --dport "${pivpnPORT}" -j ACCEPT -m comment --comment "${VPN}-input-rule"
|
-t nat \
|
||||||
fi
|
-D POSTROUTING \
|
||||||
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
|
-o "${IPv4dev}" \
|
||||||
|
-j MASQUERADE \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-nat-rule"
|
||||||
|
|
||||||
if [ "$FORWARD_CHAIN_EDITED" -eq 1 ]; then
|
ufw reload &> /dev/null
|
||||||
iptables -D FORWARD -d "${pivpnNET}/${subnetClass}" -i "${IPv4dev}" -o "${pivpnDEV}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "${VPN}-forward-rule"
|
elif [[ "${USING_UFW}" -eq 0 ]]; then
|
||||||
iptables -D FORWARD -s "${pivpnNET}/${subnetClass}" -i "${pivpnDEV}" -o "${IPv4dev}" -j ACCEPT -m comment --comment "${VPN}-forward-rule"
|
if [[ "${INPUT_CHAIN_EDITED}" -eq 1 ]]; then
|
||||||
fi
|
iptables \
|
||||||
|
-D INPUT \
|
||||||
|
-i "${IPv4dev}" \
|
||||||
|
-p "${pivpnPROTO}" \
|
||||||
|
--dport "${pivpnPORT}" \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-input-rule"
|
||||||
|
fi
|
||||||
|
|
||||||
iptables -t nat -D POSTROUTING -s "${pivpnNET}/${subnetClass}" -o "${IPv4dev}" -j MASQUERADE -m comment --comment "${VPN}-nat-rule"
|
if [[ "${FORWARD_CHAIN_EDITED}" -eq 1 ]]; then
|
||||||
iptables-save > /etc/iptables/rules.v4
|
iptables \
|
||||||
|
-D FORWARD \
|
||||||
|
-d "${pivpnNET}/${subnetClass}" \
|
||||||
|
-i "${IPv4dev}" \
|
||||||
|
-o "${pivpnDEV}" \
|
||||||
|
-m conntrack \
|
||||||
|
--ctstate RELATED,ESTABLISHED \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-forward-rule"
|
||||||
|
|
||||||
fi
|
iptables \
|
||||||
|
-D FORWARD \
|
||||||
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
|
-i "${pivpnDEV}" \
|
||||||
|
-o "${IPv4dev}" \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-forward-rule"
|
||||||
|
fi
|
||||||
|
|
||||||
# Disable IPv4 forwarding
|
iptables \
|
||||||
if [ "${vpnStillExists}" -eq 0 ]; then
|
-t nat \
|
||||||
sed -i '/net.ipv4.ip_forward=1/c\#net.ipv4.ip_forward=1' /etc/sysctl.conf
|
-D POSTROUTING \
|
||||||
sysctl -p
|
-s "${pivpnNET}/${subnetClass}" \
|
||||||
fi
|
-o "${IPv4dev}" \
|
||||||
|
-j MASQUERADE \
|
||||||
|
-m comment \
|
||||||
|
--comment "${VPN}-nat-rule"
|
||||||
|
|
||||||
# Purge dependencies
|
iptables-save > /etc/iptables/rules.v4
|
||||||
echo "::: Purge dependencies..."
|
fi
|
||||||
|
|
||||||
for i in "${INSTALLED_PACKAGES[@]}"; do
|
# Disable IPv4 forwarding
|
||||||
while true; do
|
if [[ "${vpnStillExists}" -eq 0 ]]; then
|
||||||
read -rp "::: Do you wish to remove $i from your system? [Y/n]: " yn
|
sed -i '/net.ipv4.ip_forward=1/c\#net.ipv4.ip_forward=1' /etc/sysctl.conf
|
||||||
case $yn in
|
sysctl -p
|
||||||
[Yy]* )
|
fi
|
||||||
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
|
# Purge dependencies
|
||||||
rm -f /etc/apt/preferences.d/pivpn-limit-bullseye
|
echo "::: Purge dependencies..."
|
||||||
|
|
||||||
echo "::: Updating package cache..."
|
for i in "${INSTALLED_PACKAGES[@]}"; do
|
||||||
|
while true; do
|
||||||
|
read -rp "::: Do you wish to remove ${i} from your system? [Y/n]: " yn
|
||||||
|
|
||||||
${UPDATE_PKG_CACHE} &> /dev/null &
|
case "${yn}" in
|
||||||
spinner $!
|
[Yy]*)
|
||||||
fi
|
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 /etc/systemd/system/wg-quick@.service.d/override.conf ]; then
|
if [[ -f "${tmp_path}" ]]; then
|
||||||
rm -f /etc/systemd/system/wg-quick@.service.d/override.conf
|
echo "::: Removing Debian Bullseye repo..."
|
||||||
fi
|
|
||||||
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
|
rm -f "${tmp_path}"
|
||||||
|
rm -f /etc/apt/preferences.d/pivpn-limit-bullseye
|
||||||
|
|
||||||
echo "::: Updating package cache..."
|
echo "::: Updating package cache..."
|
||||||
|
|
||||||
${UPDATE_PKG_CACHE} &> /dev/null &
|
${UPDATE_PKG_CACHE} &> /dev/null &
|
||||||
spinner $!
|
spinner "$!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
deluser openvpn
|
tmp_path='/etc/systemd/system/wg-quick@.service.d/override.conf'
|
||||||
rm -f /etc/rsyslog.d/30-openvpn.conf /etc/logrotate.d/openvpn
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf ":::\\tRemoving %s..." "$i"
|
if [[ -f "${tmp_path}" ]]; then
|
||||||
|
rm -f "${tmp_path}"
|
||||||
|
fi
|
||||||
|
|
||||||
"${PKG_REMOVE}" "$i" &> /dev/null &
|
unset tmp_path
|
||||||
spinner $!
|
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..."
|
||||||
|
|
||||||
printf "done!\\n";
|
rm -f /etc/apt/sources.list.d/pivpn-openvpn-repo.list
|
||||||
break
|
|
||||||
;;
|
|
||||||
[Nn]* )
|
|
||||||
printf ":::\\tSkipping %s\\n" "$i";
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
printf "::: You must answer yes or no!\\n"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "${PLAT}" != 'Alpine' ]; then
|
echo "::: Updating package cache..."
|
||||||
# Take care of any additional package cleaning
|
|
||||||
printf "::: Auto removing remaining dependencies..."
|
|
||||||
|
|
||||||
"${PKG_MANAGER}" -y autoremove &> /dev/null &
|
${UPDATE_PKG_CACHE} &> /dev/null &
|
||||||
spinner $!
|
spinner "$!"
|
||||||
|
fi
|
||||||
|
|
||||||
printf "done!\\n";
|
deluser openvpn
|
||||||
printf "::: Auto cleaning remaining dependencies..."
|
rm -f /etc/rsyslog.d/30-openvpn.conf /etc/logrotate.d/openvpn
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
"${PKG_MANAGER}" -y autoclean &> /dev/null &
|
printf ":::\\tRemoving %s..." "${i}"
|
||||||
spinner $!
|
|
||||||
|
|
||||||
printf "done!\\n";
|
${PKG_REMOVE} "${i}" &> /dev/null &
|
||||||
fi
|
spinner "$!"
|
||||||
|
|
||||||
if [ -f "$dnsmasqConfig" ]; then
|
printf "done!\\n"
|
||||||
rm -f "$dnsmasqConfig"
|
break
|
||||||
pihole restartdns
|
;;
|
||||||
fi
|
[Nn]*)
|
||||||
|
printf ":::\\tSkipping %s\\n" "${i}"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
err "::: You must answer yes or no!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
echo ":::"
|
if [[ "${PLAT}" != 'Alpine' ]]; then
|
||||||
echo "::: Removing VPN configuration files..."
|
# Take care of any additional package cleaning
|
||||||
|
printf "::: Auto removing remaining dependencies..."
|
||||||
|
|
||||||
if [ "$VPN" = "wireguard" ]; then
|
"${PKG_MANAGER}" -y autoremove &> /dev/null &
|
||||||
rm -f /etc/wireguard/wg0.conf
|
spinner "$!"
|
||||||
rm -rf /etc/wireguard/configs
|
|
||||||
rm -rf /etc/wireguard/keys
|
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
|
### Ignoring SC2154, value sourced from setupVars file
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
rm -rf "$install_home/configs"
|
rm -rf "${install_home}/configs"
|
||||||
elif [ "$VPN" = "openvpn" ]; then
|
elif [[ "${VPN}" == "openvpn" ]]; then
|
||||||
rm -rf /var/log/*openvpn*
|
rm -rf /var/log/*openvpn*
|
||||||
rm -f /etc/openvpn/server.conf
|
rm -f /etc/openvpn/server.conf
|
||||||
rm -f /etc/openvpn/crl.pem
|
rm -f /etc/openvpn/crl.pem
|
||||||
rm -rf /etc/openvpn/easy-rsa
|
rm -rf /etc/openvpn/easy-rsa
|
||||||
rm -rf /etc/openvpn/ccd
|
rm -rf /etc/openvpn/ccd
|
||||||
rm -rf "$install_home/ovpns"
|
rm -rf "${install_home}/ovpns"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${vpnStillExists}" -eq 0 ]; then
|
if [[ "${vpnStillExists}" -eq 0 ]]; then
|
||||||
echo ":::"
|
echo ":::"
|
||||||
echo "::: Removing pivpn system files..."
|
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 ":::"
|
rm -rf "${setupConfigDir}"
|
||||||
echo "::: Other VPN ${othervpn} still present, so not"
|
rm -rf "${pivpnFilesDir}"
|
||||||
echo "::: removing pivpn system files"
|
rm -f /var/log/*pivpn*
|
||||||
rm -f "${setupConfigDir}/${VPN}/${setupVarsFile}"
|
rm -f /etc/bash_completion.d/pivpn
|
||||||
|
|
||||||
# Restore single pivpn script and bash completion for the remaining VPN
|
unlink "${pivpnScriptDir}"
|
||||||
$SUDO unlink /usr/local/bin/pivpn
|
unlink /usr/local/bin/pivpn
|
||||||
$SUDO ln -s -T "${pivpnFilesDir}/scripts/${othervpn}/pivpn.sh" /usr/local/bin/pivpn
|
else
|
||||||
$SUDO ln -s -T "${pivpnFilesDir}/scripts/${othervpn}/bash-completion" /etc/bash_completion.d/pivpn
|
if [[ "${VPN}" == 'wireguard' ]]; then
|
||||||
# shellcheck disable=SC1091
|
othervpn='openvpn'
|
||||||
. /etc/bash_completion.d/pivpn
|
else
|
||||||
fi
|
othervpn='wireguard'
|
||||||
|
fi
|
||||||
|
|
||||||
echo ":::"
|
echo ":::"
|
||||||
printf "::: Finished removing PiVPN from your system.\\n"
|
echo "::: Other VPN ${othervpn} still present, so not"
|
||||||
printf "::: Reinstall by simply running\\n:::\\n:::\\tcurl -L https://install.pivpn.io | bash\\n:::\\n::: at any time!\\n:::\\n"
|
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 \
|
||||||
|
-sT "${pivpnFilesDir}/scripts/${othervpn}/pivpn.sh" \
|
||||||
|
/usr/local/bin/pivpn
|
||||||
|
|
||||||
|
${SUDO} ln \
|
||||||
|
-sT "${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(){
|
askreboot() {
|
||||||
printf "It is \\e[1mstrongly\\e[0m recommended to reboot after un-installation.\\n"
|
printf "It is \\e[1mstrongly\\e[0m recommended to reboot "
|
||||||
read -p "Would you like to reboot now? [y/n]: " -n 1 -r
|
printf "after un-installation.\\n"
|
||||||
echo
|
|
||||||
if [[ ${REPLY} =~ ^[Yy]$ ]]; then
|
read -p "Would you like to reboot now? [y/n]: " -n 1 -r
|
||||||
printf "\\nRebooting system...\\n"
|
|
||||||
sleep 3
|
echo
|
||||||
reboot
|
|
||||||
fi
|
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
|
||||||
|
printf "\\nRebooting system...\\n"
|
||||||
|
sleep 3
|
||||||
|
reboot
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
######### SCRIPT ###########
|
######### SCRIPT ###########
|
||||||
echo "::: Preparing to remove packages, be sure that each may be safely removed depending on your operating system."
|
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)"
|
echo "::: (SAFE TO REMOVE ALL ON RASPBIAN)"
|
||||||
while true; do
|
|
||||||
read -rp "::: Do you wish to completely remove PiVPN configuration and installed packages from your system? (You will be prompted for each package) [y/n]: " yn
|
|
||||||
case $yn in
|
|
||||||
[Yy]* ) removeAll; askreboot; break;;
|
|
||||||
|
|
||||||
[Nn]* ) printf "::: Not removing anything, exiting...\\n"; break;;
|
while true; do
|
||||||
esac
|
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
|
done
|
||||||
|
|
|
@ -1,130 +1,145 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
###Updates pivpn scripts (Not PiVPN)
|
### Updates pivpn scripts (Not PiVPN)
|
||||||
###Main Vars
|
### Main Vars
|
||||||
pivpnrepo="https://github.com/pivpn/pivpn.git"
|
pivpnrepo="https://github.com/pivpn/pivpn.git"
|
||||||
pivpnlocalpath="/etc/.pivpn"
|
pivpnlocalpath="/etc/.pivpn"
|
||||||
pivpnscripts="/opt/pivpn/"
|
pivpnscripts="/opt/pivpn/"
|
||||||
bashcompletiondir="/etc/bash_completion.d/"
|
bashcompletiondir="/etc/bash_completion.d/"
|
||||||
|
|
||||||
# Find the rows and columns. Will default to 80x24 if it can not be detected.
|
# 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)
|
screen_size="$(stty size 2> /dev/null || echo 24 80)"
|
||||||
rows=$(echo "$screen_size" | awk '{print $1}')
|
rows="$(echo "${screen_size}" | awk '{print $1}')"
|
||||||
columns=$(echo "$screen_size" | awk '{print $2}')
|
columns="$(echo "${screen_size}" | awk '{print $2}')"
|
||||||
|
|
||||||
# Divide by two so the dialogs take up half of the screen, which looks nice.
|
# Divide by two so the dialogs take up half of the screen, which looks nice.
|
||||||
r=$(( rows / 2 ))
|
r=$((rows / 2))
|
||||||
c=$(( columns / 2 ))
|
c=$((columns / 2))
|
||||||
# Unless the screen is tiny
|
# Unless the screen is tiny
|
||||||
r=$(( r < 20 ? 20 : r ))
|
r=$((r < 20 ? 20 : r))
|
||||||
c=$(( c < 70 ? 70 : c ))
|
c=$((c < 70 ? 70 : c))
|
||||||
|
|
||||||
echo "::: The updating functionality for PiVPN scripts is temporarily disabled"
|
# TODO: Delete this section when the updating functionality will be re-enabled
|
||||||
echo "::: To keep the VPN (and the system) up to date, use 'apt update' and 'apt upgrade'"
|
###
|
||||||
|
err() {
|
||||||
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
err "::: The updating functionality for PiVPN scripts is temporarily disabled"
|
||||||
|
err "::: To keep the VPN (and the system) up to date, use:"
|
||||||
|
err " apt update; apt upgrade"
|
||||||
exit 0
|
exit 0
|
||||||
|
###
|
||||||
|
|
||||||
chooseVPNCmd=(whiptail --backtitle "Setup PiVPN" --title "Installation mode" --separate-output --radiolist "Choose a VPN to update (press space to select):" "${r}" "${c}" 2)
|
chooseVPNCmd=(whiptail
|
||||||
VPNChooseOptions=(WireGuard "" on
|
--backtitle "Setup PiVPN"
|
||||||
OpenVPN "" off)
|
--title "Installation mode"
|
||||||
|
--separate-output
|
||||||
|
--radiolist "Choose a VPN to update (press space to select):"
|
||||||
|
"${r}" "${c}" 2)
|
||||||
|
VPNChooseOptions=(WireGuard "" on
|
||||||
|
OpenVPN "" off)
|
||||||
|
|
||||||
if VPN=$("${chooseVPNCmd[@]}" "${VPNChooseOptions[@]}" 2>&1 >/dev/tty) ; then
|
if VPN="$("${chooseVPNCmd[@]}" "${VPNChooseOptions[@]}" 2>&1 > /dev/tty)"; then
|
||||||
echo "::: Using VPN: $VPN"
|
echo "::: Using VPN: ${VPN}"
|
||||||
VPN="${VPN,,}"
|
VPN="${VPN,,}"
|
||||||
else
|
else
|
||||||
echo "::: Cancel selected, exiting...."
|
err "::: Cancel selected, exiting...."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
setupVars="/etc/pivpn/${VPN}/setupVars.conf"
|
setupVars="/etc/pivpn/${VPN}/setupVars.conf"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
scriptusage(){
|
# TODO: Uncomment this function when the updating functionality
|
||||||
echo "::: Updates PiVPN scripts"
|
# will be re-enabled
|
||||||
echo ":::"
|
#err() {
|
||||||
echo "::: Usage: pivpn <-up|update> [-t|--test]"
|
# echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
#}
|
||||||
echo "::: Commands:"
|
|
||||||
echo "::: [none] Updates from master branch"
|
scriptusage() {
|
||||||
echo "::: -t, test Updates from test branch"
|
echo "::: Updates PiVPN scripts"
|
||||||
echo "::: -h, help Show this usage dialog"
|
echo ":::"
|
||||||
|
echo "::: Usage: pivpn <-up|update> [-t|--test]"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] Updates from master branch"
|
||||||
|
echo "::: -t, test Updates from test branch"
|
||||||
|
echo "::: -h, help Show this usage dialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
###Functions
|
### Functions
|
||||||
##Updates scripts
|
## Updates scripts
|
||||||
updatepivpnscripts(){
|
updatepivpnscripts() {
|
||||||
##We don't know what sort of changes users have made.
|
local branch
|
||||||
##Lets remove first /etc/.pivpn dir then clone it back again
|
branch="${1}"
|
||||||
echo "going do update PiVPN Scripts"
|
## We don't know what sort of changes users have made.
|
||||||
if [[ -d "$pivpnlocalpath" ]]; then
|
## Lets remove first /etc/.pivpn dir then clone it back again
|
||||||
if [[ -n "$pivpnlocalpath" ]]; then
|
echo -n "Going do update PiVPN Scripts"
|
||||||
rm -rf "${pivpnlocalpath}/../.pivpn"
|
|
||||||
cloneandupdate
|
if [[ -z "${branch}" ]]; then
|
||||||
fi
|
echo "from ${branch} branch"
|
||||||
else
|
else
|
||||||
cloneandupdate
|
echo
|
||||||
fi
|
fi
|
||||||
echo "PiVPN Scripts have been updated"
|
|
||||||
# Disabling warning for SC1090
|
if [[ -d "${pivpnlocalpath}" ]] \
|
||||||
|
&& [[ -n "${pivpnlocalpath}" ]]; then
|
||||||
|
rm -rf "${pivpnlocalpath}/../.pivpn"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cloneandupdate "${branch}"
|
||||||
|
echo -n "PiVPN Scripts have been updated"
|
||||||
|
|
||||||
|
if [[ -z "${branch}" ]]; then
|
||||||
|
echo "from ${branch} branch"
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
##Updates scripts using test branch
|
## Clone and copy pivpn scripts to /opt/pivpn
|
||||||
updatefromtest(){
|
cloneandupdate() {
|
||||||
##We don't know what sort of changes users have made.
|
local branch
|
||||||
##Lets remove first /etc/.pivpn dir then clone it back again
|
branch="${1}"
|
||||||
echo "PiVPN Scripts updating from test branch"
|
git clone "${pivpnrepo}" "${pivpnlocalpath}"
|
||||||
if [[ -d "$pivpnlocalpath" ]]; then
|
|
||||||
if [[ -n "$pivpnlocalpath" ]]; then
|
|
||||||
rm -rf "${pivpnlocalpath}/../.pivpn"
|
|
||||||
cloneupdttest
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
cloneupdttest
|
|
||||||
fi
|
|
||||||
echo "PiVPN Scripts updated have been updated from test branch"
|
|
||||||
}
|
|
||||||
|
|
||||||
##Clone and copy pivpn scripts to /opt/pivpn
|
if [[ -z "${branch}" ]]; then
|
||||||
cloneandupdate(){
|
git -C "${pivpnlocalpath}" checkout "${branch}"
|
||||||
git clone "$pivpnrepo" "$pivpnlocalpath"
|
git -C "${pivpnlocalpath}" pull origin "${branch}"
|
||||||
cp "${pivpnlocalpath}"/scripts/*.sh "$pivpnscripts"
|
fi
|
||||||
cp "${pivpnlocalpath}"/scripts/"$VPN"/*.sh "$pivpnscripts"
|
|
||||||
cp "${pivpnlocalpath}"/scripts/"$VPN"/bash-completion "$bashcompletiondir"
|
|
||||||
}
|
|
||||||
|
|
||||||
##same as cloneandupdate() but from test branch
|
cp "${pivpnlocalpath}"/scripts/*.sh "${pivpnscripts}"
|
||||||
##and falls back to master branch again after updating
|
cp "${pivpnlocalpath}"/scripts/"${VPN}"/*.sh "${pivpnscripts}"
|
||||||
cloneupdttest(){
|
cp "${pivpnlocalpath}"/scripts/"${VPN}"/bash-completion "${bashcompletiondir}"
|
||||||
git clone "$pivpnrepo" "$pivpnlocalpath"
|
|
||||||
git -C "$pivpnlocalpath" checkout test
|
if [[ -z "${branch}" ]]; then
|
||||||
git -C "$pivpnlocalpath" pull origin test
|
git -C "${pivpnlocalpath}" checkout master
|
||||||
cp "${pivpnlocalpath}"/scripts/*.sh "$pivpnscripts"
|
fi
|
||||||
cp "${pivpnlocalpath}"/scripts/"$VPN"/*.sh "$pivpnscripts"
|
|
||||||
cp "${pivpnlocalpath}"/scripts/"$VPN"/bash-completion "$bashcompletiondir"
|
|
||||||
git -C "$pivpnlocalpath" checkout master
|
|
||||||
}
|
}
|
||||||
|
|
||||||
## SCRIPT
|
## SCRIPT
|
||||||
|
|
||||||
if [[ $# -eq 0 ]]; then
|
if [[ "$#" -eq 0 ]]; then
|
||||||
updatepivpnscripts
|
updatepivpnscripts
|
||||||
else
|
else
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "${1}" in
|
||||||
-t|test)
|
-t | test)
|
||||||
updatefromtest
|
updatepivpnscripts 'test'
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
-h|help)
|
-h | help)
|
||||||
scriptusage
|
scriptusage
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
updatepivpnscripts
|
updatepivpnscripts
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
_pivpn()
|
|
||||||
{
|
_pivpn() {
|
||||||
local cur opts
|
local cur opts
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
dashopts="-a -c -d -l -qr -r -h -u -up -bk -off -on"
|
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"
|
opts="add clients debug list qrcode remove help uninstall update"
|
||||||
if [ "${#COMP_WORDS[@]}" -eq 2 ]; then
|
opts="${opts} backup (temp) off (temp) on"
|
||||||
if [[ ${cur} == -* ]] ; then
|
|
||||||
COMPREPLY=( "$(compgen -W "${dashopts}" -- "${cur}")" )
|
if [[ "${#COMP_WORDS[@]}" -eq 2 ]]; then
|
||||||
else
|
if [[ "${cur}" == -* ]]; then
|
||||||
COMPREPLY=( "$(compgen -W "${opts}" -- "${cur}")" )
|
COMPREPLY=("$(compgen -W "${dashopts}" -- "${cur}")")
|
||||||
fi
|
else
|
||||||
|
COMPREPLY=("$(compgen -W "${opts}" -- "${cur}")")
|
||||||
fi
|
fi
|
||||||
return 0
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
complete -F _pivpn pivpn
|
complete -F _pivpn pivpn
|
||||||
|
|
|
@ -1,94 +1,108 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
# PiVPN: client status script
|
# PiVPN: client status script
|
||||||
|
|
||||||
CLIENTS_FILE="/etc/wireguard/configs/clients.txt"
|
CLIENTS_FILE="/etc/wireguard/configs/clients.txt"
|
||||||
|
|
||||||
if [ ! -s "$CLIENTS_FILE" ]; then
|
if [[ ! -s "${CLIENTS_FILE}" ]]; then
|
||||||
echo "::: There are no clients to list"
|
err "::: There are no clients to list"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
scriptusage(){
|
err() {
|
||||||
echo "::: List any connected clients to the server"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
|
||||||
echo "::: Usage: pivpn <-c|clients> [-b|bytes]"
|
|
||||||
echo ":::"
|
|
||||||
echo "::: Commands:"
|
|
||||||
echo "::: [none] List clients with human readable format"
|
|
||||||
echo "::: -b, bytes List clients with dotted decimal notation"
|
|
||||||
echo "::: -h, help Show this usage dialog"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr(){
|
scriptusage() {
|
||||||
numfmt --to=iec-i --suffix=B "$1"
|
echo "::: List any connected clients to the server"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Usage: pivpn <-c|clients> [-b|bytes]"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] List clients with human readable format"
|
||||||
|
echo "::: -b, bytes List clients with dotted decimal notation"
|
||||||
|
echo "::: -h, help Show this usage dialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
listClients(){
|
hr() {
|
||||||
if DUMP="$(wg show wg0 dump)"; then
|
numfmt --to=iec-i --suffix=B "${1}"
|
||||||
DUMP="$(tail -n +2 <<< "$DUMP")"
|
}
|
||||||
else
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf "\e[1m::: Connected Clients List :::\e[0m\n"
|
listClients() {
|
||||||
|
if DUMP="$(wg show wg0 dump)"; then
|
||||||
|
DUMP="$(tail -n +2 <<< "${DUMP}")"
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
{
|
printf "\e[1m::: Connected Clients List :::\e[0m\n"
|
||||||
printf "\e[4mName\e[0m \t \e[4mRemote IP\e[0m \t \e[4mVirtual IP\e[0m \t \e[4mBytes Received\e[0m \t \e[4mBytes Sent\e[0m \t \e[4mLast Seen\e[0m\n"
|
|
||||||
|
{
|
||||||
|
printf "\e[4mName\e[0m \t \e[4mRemote IP\e[0m \t \e[4mVirtual IP\e[0m"
|
||||||
|
printf "\t \e[4mBytes Received\e[0m \t \e[4mBytes Sent\e[0m "
|
||||||
|
printf "\t \e[4mLast Seen\e[0m\n"
|
||||||
|
|
||||||
while IFS= read -r LINE; do
|
while IFS= read -r LINE; do
|
||||||
if [ -n "${LINE}" ]; then
|
if [[ -n "${LINE}" ]]; then
|
||||||
PUBLIC_KEY="$(awk '{ print $1 }' <<< "$LINE")"
|
PUBLIC_KEY="$(awk '{ print $1 }' <<< "${LINE}")"
|
||||||
REMOTE_IP="$(awk '{ print $3 }' <<< "$LINE")"
|
REMOTE_IP="$(awk '{ print $3 }' <<< "${LINE}")"
|
||||||
VIRTUAL_IP="$(awk '{ print $4 }' <<< "$LINE")"
|
VIRTUAL_IP="$(awk '{ print $4 }' <<< "${LINE}")"
|
||||||
BYTES_RECEIVED="$(awk '{ print $6 }' <<< "$LINE")"
|
BYTES_RECEIVED="$(awk '{ print $6 }' <<< "${LINE}")"
|
||||||
BYTES_SENT="$(awk '{ print $7 }' <<< "$LINE")"
|
BYTES_SENT="$(awk '{ print $7 }' <<< "${LINE}")"
|
||||||
LAST_SEEN="$(awk '{ print $5 }' <<< "$LINE")"
|
LAST_SEEN="$(awk '{ print $5 }' <<< "${LINE}")"
|
||||||
CLIENT_NAME="$(grep "$PUBLIC_KEY" "$CLIENTS_FILE" | awk '{ print $1 }')"
|
CLIENT_NAME="$(grep "${PUBLIC_KEY}" "${CLIENTS_FILE}" \
|
||||||
if [ "$HR" = 1 ]; then
|
| awk '{ print $1 }')"
|
||||||
if [ "$LAST_SEEN" -ne 0 ]; then
|
printf "%s \t %s \t %s \t " \
|
||||||
printf "%s \t %s \t %s \t %s \t %s \t %s\n" "$CLIENT_NAME" "$REMOTE_IP" "${VIRTUAL_IP/\/32/}" "$(hr "$BYTES_RECEIVED")" "$(hr "$BYTES_SENT")" "$(date -d @"$LAST_SEEN" '+%b %d %Y - %T')"
|
"${CLIENT_NAME}" \
|
||||||
else
|
"${REMOTE_IP}" \
|
||||||
printf "%s \t %s \t %s \t %s \t %s \t %s\n" "$CLIENT_NAME" "$REMOTE_IP" "${VIRTUAL_IP/\/32/}" "$(hr "$BYTES_RECEIVED")" "$(hr "$BYTES_SENT")" "(not yet)"
|
"${VIRTUAL_IP/\/32/}"
|
||||||
fi
|
|
||||||
else
|
if [[ "${HR}" == 1 ]]; then
|
||||||
if [ "$LAST_SEEN" -ne 0 ]; then
|
printf "%s \t %s \t " \
|
||||||
printf "%s \t %s \t %s \t %'d \t %'d \t %s\n" "$CLIENT_NAME" "$REMOTE_IP" "${VIRTUAL_IP/\/32/}" "$BYTES_RECEIVED" "$BYTES_SENT" "$(date -d @"$LAST_SEEN" '+%b %d %Y - %T')"
|
"$(hr "${BYTES_RECEIVED}")" \
|
||||||
else
|
"$(hr "${BYTES_SENT}")"
|
||||||
printf "%s \t %s \t %s \t %'d \t %'d \t %s\n" "$CLIENT_NAME" "$REMOTE_IP" "${VIRTUAL_IP/\/32/}" "$BYTES_RECEIVED" "$BYTES_SENT" "(not yet)"
|
else
|
||||||
fi
|
printf "%s \t %s \t " "${BYTES_RECEIVED}" "${BYTES_SENT}"
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
done <<< "$DUMP"
|
|
||||||
|
if [[ "${LAST_SEEN}" -ne 0 ]]; then
|
||||||
|
printf "%s" "$(date -d @"${LAST_SEEN}" '+%b %d %Y - %T')"
|
||||||
|
else
|
||||||
|
printf "(not yet)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "\n"
|
||||||
|
fi
|
||||||
|
done <<< "${DUMP}"
|
||||||
|
|
||||||
printf "\n"
|
printf "\n"
|
||||||
} | column -t -s $'\t'
|
} | column -ts $'\t'
|
||||||
|
|
||||||
cd /etc/wireguard || return
|
cd /etc/wireguard || return
|
||||||
echo "::: Disabled clients :::"
|
|
||||||
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
|
||||||
|
|
||||||
|
echo "::: Disabled clients :::"
|
||||||
|
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $# -eq 0 ]]; then
|
if [[ "$#" -eq 0 ]]; then
|
||||||
HR=1
|
HR=1
|
||||||
listClients
|
listClients
|
||||||
else
|
else
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "${1}" in
|
||||||
-b|bytes)
|
-b | bytes)
|
||||||
HR=0
|
HR=0
|
||||||
listClients
|
listClients
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
-h|help)
|
-h | help)
|
||||||
scriptusage
|
scriptusage
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
HR=0
|
HR=0
|
||||||
listClients
|
listClients
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -2,127 +2,137 @@
|
||||||
|
|
||||||
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
helpFunc(){
|
err() {
|
||||||
echo "::: Disable client conf profiles"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
}
|
||||||
echo "::: Usage: pivpn <-off|off> [-h|--help] [-v] [<client-1> ... [<client-2>] ...] "
|
|
||||||
echo ":::"
|
helpFunc() {
|
||||||
echo "::: Commands:"
|
echo "::: Disable client conf profiles"
|
||||||
echo "::: [none] Interactive mode"
|
echo ":::"
|
||||||
echo "::: <client> Client"
|
echo -n "::: Usage: pivpn <-off|off> [-h|--help] [-v] "
|
||||||
echo "::: -y,--yes Disable client(s) without confirmation"
|
echo "[<client-1> ... [<client-2>] ...]"
|
||||||
echo "::: -v Show disabled clients only"
|
echo ":::"
|
||||||
echo "::: -h,--help Show this help dialog"
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] Interactive mode"
|
||||||
|
echo "::: <client> 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
|
# Parse input arguments
|
||||||
while test $# -gt 0; do
|
while [[ "$#" -gt 0 ]]; do
|
||||||
_key="$1"
|
_key="${1}"
|
||||||
case "$_key" in
|
|
||||||
-h|--help)
|
case "${_key}" in
|
||||||
helpFunc
|
-h | --help)
|
||||||
exit 0
|
helpFunc
|
||||||
;;
|
exit 0
|
||||||
-y|--yes)
|
;;
|
||||||
CONFIRM=true
|
-y | --yes)
|
||||||
;;
|
CONFIRM=true
|
||||||
-v)
|
;;
|
||||||
DISPLAY_DISABLED=true
|
-v)
|
||||||
;;
|
DISPLAY_DISABLED=true
|
||||||
*)
|
;;
|
||||||
CLIENTS_TO_CHANGE+=("$1")
|
*)
|
||||||
;;
|
CLIENTS_TO_CHANGE+=("${1}")
|
||||||
esac
|
;;
|
||||||
shift
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
cd /etc/wireguard || exit
|
cd /etc/wireguard || exit
|
||||||
if [ ! -s configs/clients.txt ]; then
|
|
||||||
echo "::: There are no clients to change"
|
if [[ ! -s configs/clients.txt ]]; then
|
||||||
exit 1
|
err "::: There are no clients to change"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "${DISPLAY_DISABLED}" ]]; then
|
||||||
if [ "$DISPLAY_DISABLED" ]; then
|
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
||||||
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
exit 1
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
mapfile -t LIST < <(awk '{print $1}' configs/clients.txt)
|
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
|
|
||||||
|
|
||||||
read -r -p "Please enter the Index/Name of the Client to be removed from the list above: " CLIENTS_TO_CHANGE
|
if [[ "${#CLIENTS_TO_CHANGE[@]}" -eq 0 ]]; then
|
||||||
|
echo -e "::\e[4m Client list \e[0m::"
|
||||||
|
len="${#LIST[@]}"
|
||||||
|
COUNTER=1
|
||||||
|
|
||||||
if [ -z "${CLIENTS_TO_CHANGE}" ]; then
|
while [[ "${COUNTER}" -le "${len}" ]]; do
|
||||||
echo "::: You can not leave this blank!"
|
printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER - 1))]}"
|
||||||
exit 1
|
((COUNTER++))
|
||||||
fi
|
done
|
||||||
|
|
||||||
|
echo -n "Please enter the Index/Name of the Client to be removed "
|
||||||
|
echo -n "from the list above: "
|
||||||
|
read -r CLIENTS_TO_CHANGE
|
||||||
|
|
||||||
|
if [[ -z "${CLIENTS_TO_CHANGE}" ]]; then
|
||||||
|
err "::: You can not leave this blank!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CHANGED_COUNT=0
|
CHANGED_COUNT=0
|
||||||
|
|
||||||
for CLIENT_NAME in "${CLIENTS_TO_CHANGE[@]}"; do
|
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 ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then
|
||||||
if [[ ${CLIENT_NAME} =~ $re ]] ; then
|
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
||||||
CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]}
|
elif grep -q "#\[disabled\] ### begin ${CLIENT_NAME}" wg0.conf; then
|
||||||
fi
|
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
|
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
|
||||||
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
# Disable the peer section from the server config
|
||||||
elif grep -q "#\[disabled\] ### begin ${CLIENT_NAME}" wg0.conf; then
|
echo "${CLIENT_NAME}"
|
||||||
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
|
sed_pattern="/### begin ${CLIENT_NAME}/,"
|
||||||
|
sed_pattern="${sed_pattern}/end ${CLIENT_NAME}/ s/^/#\[disabled\] /"
|
||||||
# Disable the peer section from the server config
|
sed -e "${sed_pattern}" -i wg0.conf
|
||||||
echo "${CLIENT_NAME}"
|
unset sed_pattern
|
||||||
sed -e "/### begin ${CLIENT_NAME}/,/end ${CLIENT_NAME}/ s/^/#\[disabled\] /" -i wg0.conf
|
|
||||||
echo "::: Updated server config"
|
|
||||||
|
|
||||||
((CHANGED_COUNT++))
|
|
||||||
echo "::: Successfully disabled ${CLIENT_NAME}"
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
echo "::: Updated server config"
|
||||||
|
((CHANGED_COUNT++))
|
||||||
|
echo "::: Successfully disabled ${CLIENT_NAME}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Restart WireGuard only if some clients were actually deleted
|
# Restart WireGuard only if some clients were actually deleted
|
||||||
if [ "${CHANGED_COUNT}" -gt 0 ]; then
|
if [[ "${CHANGED_COUNT}" -gt 0 ]]; then
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
if rc-service wg-quick restart; then
|
if rc-service wg-quick restart; then
|
||||||
echo "::: WireGuard reloaded"
|
echo "::: WireGuard reloaded"
|
||||||
else
|
else
|
||||||
echo "::: Failed to reload WireGuard"
|
err "::: Failed to reload WireGuard"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if systemctl reload wg-quick@wg0; then
|
if systemctl reload wg-quick@wg0; then
|
||||||
echo "::: WireGuard reloaded"
|
echo "::: WireGuard reloaded"
|
||||||
else
|
else
|
||||||
echo "::: Failed to reload WireGuard"
|
err "::: Failed to reload WireGuard"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -2,123 +2,136 @@
|
||||||
|
|
||||||
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
helpFunc(){
|
err() {
|
||||||
echo "::: Enables client conf profiles"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
}
|
||||||
echo "::: Usage: pivpn <-on|on> [-h|--help] [-v] [<client-1> ... [<client-2>] ...] "
|
|
||||||
echo ":::"
|
helpFunc() {
|
||||||
echo "::: Commands:"
|
echo "::: Enables client conf profiles"
|
||||||
echo "::: [none] Interactive mode"
|
echo ":::"
|
||||||
echo "::: <client> Client"
|
echo -n "::: Usage: pivpn <-on|on> [-h|--help] [-v] "
|
||||||
echo "::: -y,--yes Enable client(s) without confirmation"
|
echo "[<client-1> ... [<client-2>] ...]"
|
||||||
echo "::: -v Show disabled clients only"
|
echo ":::"
|
||||||
echo "::: -h,--help Show this help dialog"
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] Interactive mode"
|
||||||
|
echo "::: <client> 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
|
# Parse input arguments
|
||||||
while test $# -gt 0; do
|
while [[ "$#" -gt 0 ]]; do
|
||||||
_key="$1"
|
_key="${1}"
|
||||||
case "$_key" in
|
|
||||||
-h|--help)
|
case "${_key}" in
|
||||||
helpFunc
|
-h | --help)
|
||||||
exit 0
|
helpFunc
|
||||||
;;
|
exit 0
|
||||||
-y|--yes)
|
;;
|
||||||
CONFIRM=true
|
-y | --yes)
|
||||||
;;
|
CONFIRM=true
|
||||||
-v)
|
;;
|
||||||
DISPLAY_DISABLED=true
|
-v)
|
||||||
;;
|
DISPLAY_DISABLED=true
|
||||||
*)
|
;;
|
||||||
CLIENTS_TO_CHANGE+=("$1")
|
*)
|
||||||
;;
|
CLIENTS_TO_CHANGE+=("${1}")
|
||||||
esac
|
;;
|
||||||
shift
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
cd /etc/wireguard || exit
|
cd /etc/wireguard || exit
|
||||||
if [ ! -s configs/clients.txt ]; then
|
|
||||||
echo "::: There are no clients to change"
|
if [[ ! -s configs/clients.txt ]]; then
|
||||||
exit 1
|
err "::: There are no clients to change"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$DISPLAY_DISABLED" ]; then
|
if [[ "${DISPLAY_DISABLED}" ]]; then
|
||||||
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mapfile -t LIST < <(awk '{print $1}' configs/clients.txt)
|
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
|
|
||||||
|
|
||||||
read -r -p "Please enter the Index/Name of the Client to be enabled from the list above: " CLIENTS_TO_CHANGE
|
if [[ "${#CLIENTS_TO_CHANGE[@]}" -eq 0 ]]; then
|
||||||
|
echo -e "::\e[4m Client list \e[0m::"
|
||||||
|
len="${#LIST[@]}"
|
||||||
|
COUNTER=1
|
||||||
|
|
||||||
if [ -z "${CLIENTS_TO_CHANGE}" ]; then
|
while [[ "${COUNTER}" -le "${len}" ]]; do
|
||||||
echo "::: You can not leave this blank!"
|
printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER - 1))]}"
|
||||||
exit 1
|
((COUNTER++))
|
||||||
fi
|
done
|
||||||
|
|
||||||
|
echo -n "Please enter the Index/Name of the Client to be enabled "
|
||||||
|
echo -n "from the list above: "
|
||||||
|
read -r CLIENTS_TO_CHANGE
|
||||||
|
|
||||||
|
if [[ -z "${CLIENTS_TO_CHANGE}" ]]; then
|
||||||
|
err "::: You can not leave this blank!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CHANGED_COUNT=0
|
CHANGED_COUNT=0
|
||||||
|
|
||||||
for CLIENT_NAME in "${CLIENTS_TO_CHANGE[@]}"; do
|
for CLIENT_NAME in "${CLIENTS_TO_CHANGE[@]}"; do
|
||||||
|
re='^[0-9]+$'
|
||||||
|
|
||||||
re='^[0-9]+$'
|
if [[ "${CLIENT_NAME}" =~ $re ]]; then
|
||||||
if [[ ${CLIENT_NAME} =~ $re ]] ; then
|
CLIENT_NAME="${LIST[$((CLIENT_NAME - 1))]}"
|
||||||
CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]}
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then
|
if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then
|
||||||
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
||||||
else
|
else
|
||||||
if [ -n "$CONFIRM" ]; then
|
if [[ -n "${CONFIRM}" ]]; then
|
||||||
REPLY="y"
|
REPLY="y"
|
||||||
else
|
else
|
||||||
read -r -p "Confirm you want to enable $CLIENT_NAME? [Y/n] "
|
read -r -p "Confirm you want to enable ${CLIENT_NAME}? [Y/n] "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
|
||||||
|
# Enable the peer section from the server config
|
||||||
|
echo "${CLIENT_NAME}"
|
||||||
|
|
||||||
# Enable the peer section from the server config
|
sed_pattern="/begin ${CLIENT_NAME}/,"
|
||||||
echo "${CLIENT_NAME}"
|
sed_pattern="${sed_pattern}/end ${CLIENT_NAME}/ s/#\[disabled\] //"
|
||||||
sed -e "/begin ${CLIENT_NAME}/,/end ${CLIENT_NAME}/ s/#\[disabled\] //" -i wg0.conf
|
sed -e "${sed_pattern}" -i wg0.conf
|
||||||
echo "::: Updated server config"
|
unset sed_pattern
|
||||||
|
|
||||||
((CHANGED_COUNT++))
|
|
||||||
echo "::: Successfully enabled ${CLIENT_NAME}"
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
echo "::: Updated server config"
|
||||||
|
((CHANGED_COUNT++))
|
||||||
|
echo "::: Successfully enabled ${CLIENT_NAME}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Restart WireGuard only if some clients were actually deleted
|
# Restart WireGuard only if some clients were actually deleted
|
||||||
if [ "${CHANGED_COUNT}" -gt 0 ]; then
|
if [[ "${CHANGED_COUNT}" -gt 0 ]]; then
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
if rc-service wg-quick restart; then
|
if rc-service wg-quick restart; then
|
||||||
echo "::: WireGuard reloaded"
|
echo "::: WireGuard reloaded"
|
||||||
else
|
else
|
||||||
echo "::: Failed to reload WireGuard"
|
err "::: Failed to reload WireGuard"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if systemctl reload wg-quick@wg0; then
|
if systemctl reload wg-quick@wg0; then
|
||||||
echo "::: WireGuard reloaded"
|
echo "::: WireGuard reloaded"
|
||||||
else
|
else
|
||||||
echo "::: Failed to reload WireGuard"
|
err "::: Failed to reload WireGuard"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,33 +1,34 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
err() {
|
||||||
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
cd /etc/wireguard/configs || exit
|
cd /etc/wireguard/configs || exit
|
||||||
if [ ! -s clients.txt ]; then
|
|
||||||
echo "::: There are no clients to list"
|
if [[ ! -s clients.txt ]]; then
|
||||||
exit 1
|
err "::: There are no clients to list"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "\e[1m::: Clients Summary :::\e[0m\n"
|
printf "\e[1m::: Clients Summary :::\e[0m\n"
|
||||||
|
|
||||||
# Present the user with a summary of the clients, fetching info from dates.
|
# Present the user with a summary of the clients, fetching info from dates.
|
||||||
{
|
{
|
||||||
echo -e "\e[4mClient\e[0m \t \e[4mPublic key\e[0m \t \e[4mCreation date\e[0m"
|
echo -ne "\e[4mClient\e[0m \t \e[4mPublic key\e[0m \t "
|
||||||
|
echo -e "\e[4mCreation date\e[0m"
|
||||||
while read -r LINE; do
|
|
||||||
CLIENT_NAME="$(awk '{print $1}' <<< "$LINE")"
|
|
||||||
|
|
||||||
PUBLIC_KEY="$(awk '{print $2}' <<< "$LINE")"
|
|
||||||
|
|
||||||
CREATION_DATE="$(awk '{print $3}' <<< "$LINE")"
|
|
||||||
|
|
||||||
|
while read -r LINE; do
|
||||||
|
CLIENT_NAME="$(awk '{print $1}' <<< "${LINE}")"
|
||||||
|
PUBLIC_KEY="$(awk '{print $2}' <<< "${LINE}")"
|
||||||
|
CREATION_DATE="$(awk '{print $3}' <<< "${LINE}")"
|
||||||
# Dates are converted from UNIX time to human readable.
|
# Dates are converted from UNIX time to human readable.
|
||||||
CD_FORMAT="$(date -d @"$CREATION_DATE" +'%d %b %Y, %H:%M, %Z')"
|
CD_FORMAT="$(date -d @"${CREATION_DATE}" +'%d %b %Y, %H:%M, %Z')"
|
||||||
|
echo -e "${CLIENT_NAME} \t ${PUBLIC_KEY} \t ${CD_FORMAT}"
|
||||||
echo -e "$CLIENT_NAME \t $PUBLIC_KEY \t $CD_FORMAT"
|
done < clients.txt
|
||||||
done < clients.txt
|
|
||||||
|
|
||||||
} | column -t -s $'\t'
|
} | column -t -s $'\t'
|
||||||
|
|
||||||
|
|
||||||
cd /etc/wireguard || return
|
cd /etc/wireguard || return
|
||||||
|
|
||||||
echo "::: Disabled clients :::"
|
echo "::: Disabled clients :::"
|
||||||
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
grep '\[disabled\] ### begin' wg0.conf | sed 's/#//g; s/begin//'
|
||||||
|
|
|
@ -1,108 +1,113 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
######## Some vars that might be empty
|
# Some vars that might be empty but need to be defined for checks
|
||||||
# but need to be defined for checks
|
|
||||||
pivpnPERSISTENTKEEPALIVE=""
|
pivpnPERSISTENTKEEPALIVE=""
|
||||||
pivpnDNS2=""
|
pivpnDNS2=""
|
||||||
|
|
||||||
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
userGroup="${install_user}:${install_user}"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
helpFunc(){
|
err() {
|
||||||
echo "::: Create a client conf profile"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
}
|
||||||
echo "::: Usage: pivpn <-a|add> [-n|--name <arg>] [-h|--help]"
|
|
||||||
echo ":::"
|
helpFunc() {
|
||||||
echo "::: Commands:"
|
echo "::: Create a client conf profile"
|
||||||
echo "::: [none] Interactive mode"
|
echo ":::"
|
||||||
echo "::: -n,--name Name for the Client (default: '$HOSTNAME')"
|
echo "::: Usage: pivpn <-a|add> [-n|--name <arg>] [-h|--help]"
|
||||||
echo "::: -h,--help Show this help dialog"
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] Interactive mode"
|
||||||
|
echo "::: -n,--name Name for the Client (default: '${HOSTNAME}')"
|
||||||
|
echo "::: -h,--help Show this help dialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse input arguments
|
# Parse input arguments
|
||||||
while test $# -gt 0; do
|
while [[ "$#" -gt 0 ]]; do
|
||||||
_key="$1"
|
_key="${1}"
|
||||||
case "$_key" in
|
|
||||||
-n|--name|--name=*)
|
case "${_key}" in
|
||||||
_val="${_key##--name=}"
|
-n | --name | --name=*)
|
||||||
if test "$_val" = "$_key"; then
|
_val="${_key##--name=}"
|
||||||
test $# -lt 2 && echo "::: Missing value for the optional argument '$_key'." && exit 1
|
|
||||||
_val="$2"
|
if [[ "${_val}" == "${_key}" ]]; then
|
||||||
shift
|
[[ "$#" -lt 2 ]] \
|
||||||
fi
|
&& err "::: Missing value for the optional argument '${_key}'." \
|
||||||
CLIENT_NAME="$_val"
|
&& exit 1
|
||||||
;;
|
|
||||||
-h|--help)
|
_val="${2}"
|
||||||
helpFunc
|
shift
|
||||||
exit 0
|
fi
|
||||||
;;
|
|
||||||
*)
|
CLIENT_NAME="${_val}"
|
||||||
echo "::: Error: Got an unexpected argument '$1'"
|
;;
|
||||||
helpFunc
|
-h | --help)
|
||||||
exit 1
|
helpFunc
|
||||||
;;
|
exit 0
|
||||||
esac
|
;;
|
||||||
shift
|
*)
|
||||||
|
err "::: Error: Got an unexpected argument '${1}'"
|
||||||
|
helpFunc
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
# Disabling SC2154, variables sourced externaly
|
# Disabling SC2154, variables sourced externaly
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
# The home folder variable was sourced from the settings file.
|
# The home folder variable was sourced from the settings file.
|
||||||
if [ ! -d "${install_home}/configs" ]; then
|
if [[ ! -d "${install_home}/configs" ]]; then
|
||||||
mkdir "${install_home}/configs"
|
mkdir "${install_home}/configs"
|
||||||
chown "${install_user}":"${install_user}" "${install_home}/configs"
|
chown "${userGroup}" "${install_home}/configs"
|
||||||
chmod 0750 "${install_home}/configs"
|
chmod 0750 "${install_home}/configs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd /etc/wireguard || exit
|
cd /etc/wireguard || exit
|
||||||
|
|
||||||
if [ -z "${CLIENT_NAME}" ]; then
|
if [[ -z "${CLIENT_NAME}" ]]; then
|
||||||
read -r -p "Enter a Name for the Client: " CLIENT_NAME
|
read -r -p "Enter a Name for the Client: " CLIENT_NAME
|
||||||
|
elif [[ "${CLIENT_NAME}" =~ [^a-zA-Z0-9.@_-] ]]; then
|
||||||
|
err "Name can only contain alphanumeric characters and these symbols (.-@_)."
|
||||||
|
exit 1
|
||||||
|
elif [[ "${CLIENT_NAME:0:1}" == "-" ]]; then
|
||||||
|
err "Name cannot start with -"
|
||||||
|
exit 1
|
||||||
|
elif [[ "${CLIENT_NAME}" =~ ^[0-9]+$ ]]; then
|
||||||
|
err "Names cannot be integers."
|
||||||
|
exit 1
|
||||||
|
elif [[ -z "${CLIENT_NAME}" ]]; then
|
||||||
|
err "::: You cannot leave the name blank."
|
||||||
|
exit 1
|
||||||
|
elif [[ -f "configs/${CLIENT_NAME}.conf" ]]; then
|
||||||
|
err "::: A client with this name already exists"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${CLIENT_NAME}" =~ [^a-zA-Z0-9.@_-] ]]; then
|
wg genkey \
|
||||||
echo "Name can only contain alphanumeric characters and these characters (.-@_)."
|
| tee "keys/${CLIENT_NAME}_priv" \
|
||||||
exit 1
|
| wg pubkey > "keys/${CLIENT_NAME}_pub"
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${CLIENT_NAME:0:1}" == "-" ]]; then
|
|
||||||
echo "Name cannot start with -"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${CLIENT_NAME}" =~ ^[0-9]+$ ]]; then
|
|
||||||
echo "Names cannot be integers."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${CLIENT_NAME}" ]; then
|
|
||||||
echo "::: You cannot leave the name blank."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "configs/${CLIENT_NAME}.conf" ]; then
|
|
||||||
echo "::: A client with this name already exists"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
wg genkey | tee "keys/${CLIENT_NAME}_priv" | wg pubkey > "keys/${CLIENT_NAME}_pub"
|
|
||||||
wg genpsk | tee "keys/${CLIENT_NAME}_psk" &> /dev/null
|
wg genpsk | tee "keys/${CLIENT_NAME}_psk" &> /dev/null
|
||||||
echo "::: Client Keys generated"
|
echo "::: Client Keys generated"
|
||||||
|
|
||||||
# Find an unused number for the last octet of the client IP
|
# Find an unused number for the last octet of the client IP
|
||||||
for i in {2..254}; do
|
for i in {2..254}; do
|
||||||
if ! grep -q " $i$" configs/clients.txt; then
|
if ! grep -q " ${i}$" configs/clients.txt; then
|
||||||
COUNT="$i"
|
COUNT="${i}"
|
||||||
echo "${CLIENT_NAME} $(<keys/"${CLIENT_NAME}"_pub) $(date +%s) ${COUNT}" >> configs/clients.txt
|
echo "${CLIENT_NAME} $(< keys/"${CLIENT_NAME}"_pub) $(date +%s) ${COUNT}" \
|
||||||
break
|
| tee -a configs/clients.txt > /dev/null
|
||||||
fi
|
break
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Disabling SC2154, variables sourced externaly
|
# Disabling SC2154, variables sourced externaly
|
||||||
|
@ -110,88 +115,95 @@ done
|
||||||
NET_REDUCED="${pivpnNET::-2}"
|
NET_REDUCED="${pivpnNET::-2}"
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
if [ "$pivpnenableipv6" == "1" ]; then
|
{
|
||||||
echo "[Interface]
|
echo '[Interface]'
|
||||||
PrivateKey = $(cat "keys/${CLIENT_NAME}_priv")
|
echo "PrivateKey = $(cat "keys/${CLIENT_NAME}_priv")"
|
||||||
Address = ${NET_REDUCED}.${COUNT}/${subnetClass},${pivpnNETv6}${COUNT}/${subnetClassv6}" > "configs/${CLIENT_NAME}.conf"
|
echo -n "Address = ${NET_REDUCED}.${COUNT}/${subnetClass}"
|
||||||
else
|
|
||||||
echo "[Interface]
|
|
||||||
PrivateKey = $(cat "keys/${CLIENT_NAME}_priv")
|
|
||||||
Address = ${NET_REDUCED}.${COUNT}/${subnetClass}" > "configs/${CLIENT_NAME}.conf"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
if [[ "${pivpnenableipv6}" == 1 ]]; then
|
||||||
echo -n "DNS = ${pivpnDNS1}" >> "configs/${CLIENT_NAME}.conf"
|
echo ",${pivpnNETv6}${COUNT}/${subnetClassv6}"
|
||||||
if [ -n "${pivpnDNS2}" ]; then
|
else
|
||||||
echo ", ${pivpnDNS2}" >> "configs/${CLIENT_NAME}.conf"
|
echo
|
||||||
else
|
fi
|
||||||
echo >> "configs/${CLIENT_NAME}.conf"
|
|
||||||
fi
|
|
||||||
echo >> "configs/${CLIENT_NAME}.conf"
|
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
echo -n "DNS = ${pivpnDNS1}"
|
||||||
echo "[Peer]
|
|
||||||
PublicKey = $(cat keys/server_pub)
|
if [[ -n "${pivpnDNS2}" ]]; then
|
||||||
PresharedKey = $(cat "keys/${CLIENT_NAME}_psk")
|
echo ", ${pivpnDNS2}"
|
||||||
Endpoint = ${pivpnHOST}:${pivpnPORT}
|
else
|
||||||
AllowedIPs = ${ALLOWED_IPS}" >> "configs/${CLIENT_NAME}.conf"
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo '[Peer]'
|
||||||
|
echo "PublicKey = $(cat keys/server_pub)"
|
||||||
|
echo "PresharedKey = $(cat "keys/${CLIENT_NAME}_psk")"
|
||||||
|
echo "Endpoint = ${pivpnHOST}:${pivpnPORT}"
|
||||||
|
echo "AllowedIPs = ${ALLOWED_IPS}"
|
||||||
|
|
||||||
|
if [[ -n "${pivpnPERSISTENTKEEPALIVE}" ]]; then
|
||||||
|
echo "PersistentKeepalive = ${pivpnPERSISTENTKEEPALIVE}"
|
||||||
|
fi
|
||||||
|
} > "configs/${CLIENT_NAME}.conf"
|
||||||
|
|
||||||
if [ -n "${pivpnPERSISTENTKEEPALIVE}" ]; then
|
|
||||||
echo "PersistentKeepalive = ${pivpnPERSISTENTKEEPALIVE}" >> "configs/${CLIENT_NAME}.conf"
|
|
||||||
fi
|
|
||||||
echo "::: Client config generated"
|
echo "::: Client config generated"
|
||||||
|
|
||||||
if [ "$pivpnenableipv6" == "1" ]; then
|
{
|
||||||
echo "### begin ${CLIENT_NAME} ###
|
echo "### begin ${CLIENT_NAME} ###"
|
||||||
[Peer]
|
echo '[Peer]'
|
||||||
PublicKey = $(cat "keys/${CLIENT_NAME}_pub")
|
echo "PublicKey = $(cat "keys/${CLIENT_NAME}_pub")"
|
||||||
PresharedKey = $(cat "keys/${CLIENT_NAME}_psk")
|
echo "PresharedKey = $(cat "keys/${CLIENT_NAME}_psk")"
|
||||||
AllowedIPs = ${NET_REDUCED}.${COUNT}/32,${pivpnNETv6}${COUNT}/128
|
echo -n "AllowedIPs = ${NET_REDUCED}.${COUNT}/32"
|
||||||
### end ${CLIENT_NAME} ###" >> wg0.conf
|
|
||||||
else
|
if [[ "${pivpnenableipv6}" == 1 ]]; then
|
||||||
echo "### begin ${CLIENT_NAME} ###
|
echo ",${pivpnNETv6}${COUNT}/128"
|
||||||
[Peer]
|
else
|
||||||
PublicKey = $(cat "keys/${CLIENT_NAME}_pub")
|
echo
|
||||||
PresharedKey = $(cat "keys/${CLIENT_NAME}_psk")
|
fi
|
||||||
AllowedIPs = ${NET_REDUCED}.${COUNT}/32
|
|
||||||
### end ${CLIENT_NAME} ###" >> wg0.conf
|
echo "### end ${CLIENT_NAME} ###"
|
||||||
fi
|
} >> wg0.conf
|
||||||
|
|
||||||
echo "::: Updated server config"
|
echo "::: Updated server config"
|
||||||
|
|
||||||
if [ -f /etc/pivpn/hosts.wireguard ]; then
|
if [[ -f /etc/pivpn/hosts.wireguard ]]; then
|
||||||
echo "${NET_REDUCED}.${COUNT} ${CLIENT_NAME}.pivpn" >> /etc/pivpn/hosts.wireguard
|
echo "${NET_REDUCED}.${COUNT} ${CLIENT_NAME}.pivpn" \
|
||||||
if [ "$pivpnenableipv6" == "1" ]; then
|
| tee -a /etc/pivpn/hosts.wireguard > /dev/null
|
||||||
echo "${pivpnNETv6}${COUNT} ${CLIENT_NAME}.pivpn" >> /etc/pivpn/hosts.wireguard
|
|
||||||
fi
|
if [[ "${pivpnenableipv6}" == 1 ]]; then
|
||||||
if killall -SIGHUP pihole-FTL; then
|
echo "${pivpnNETv6}${COUNT} ${CLIENT_NAME}.pivpn" \
|
||||||
echo "::: Updated hosts file for Pi-hole"
|
| tee -a /etc/pivpn/hosts.wireguard > /dev/null
|
||||||
else
|
fi
|
||||||
echo "::: Failed to reload pihole-FTL configuration"
|
|
||||||
fi
|
if killall -SIGHUP pihole-FTL; then
|
||||||
|
echo "::: Updated hosts file for Pi-hole"
|
||||||
|
else
|
||||||
|
err "::: Failed to reload pihole-FTL configuration"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
if rc-service wg-quick restart; then
|
if rc-service wg-quick restart; then
|
||||||
echo "::: WireGuard reloaded"
|
echo "::: WireGuard reloaded"
|
||||||
else
|
else
|
||||||
echo "::: Failed to reload WireGuard"
|
err "::: Failed to reload WireGuard"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if systemctl reload wg-quick@wg0; then
|
if systemctl reload wg-quick@wg0; then
|
||||||
echo "::: WireGuard reloaded"
|
echo "::: WireGuard reloaded"
|
||||||
else
|
else
|
||||||
echo "::: Failed to reload WireGuard"
|
err "::: Failed to reload WireGuard"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp "configs/${CLIENT_NAME}.conf" "${install_home}/configs/${CLIENT_NAME}.conf"
|
cp "configs/${CLIENT_NAME}.conf" "${install_home}/configs/${CLIENT_NAME}.conf"
|
||||||
chown "${install_user}":"${install_user}" "${install_home}/configs/${CLIENT_NAME}.conf"
|
chown "${userGroup}" "${install_home}/configs/${CLIENT_NAME}.conf"
|
||||||
chmod 640 "${install_home}/configs/${CLIENT_NAME}.conf"
|
chmod 640 "${install_home}/configs/${CLIENT_NAME}.conf"
|
||||||
|
|
||||||
echo "======================================================================"
|
echo "======================================================================"
|
||||||
echo -e "::: Done! \e[1m${CLIENT_NAME}.conf successfully created!\e[0m"
|
echo -e "::: Done! \e[1m${CLIENT_NAME}.conf successfully created!\e[0m"
|
||||||
echo "::: ${CLIENT_NAME}.conf was copied to ${install_home}/configs for easy transfer."
|
echo -n "::: ${CLIENT_NAME}.conf was copied to ${install_home}/configs for easy"
|
||||||
|
echo "transfer."
|
||||||
echo "::: Please use this profile only on one device and create additional"
|
echo "::: Please use this profile only on one device and create additional"
|
||||||
echo -e "::: profiles for other devices. You can also use \e[1mpivpn -qr\e[0m"
|
echo -e "::: profiles for other devices. You can also use \e[1mpivpn -qr\e[0m"
|
||||||
echo "::: to generate a QR Code you can scan with the mobile app."
|
echo "::: to generate a QR Code you can scan with the mobile app."
|
||||||
|
|
|
@ -3,127 +3,160 @@
|
||||||
CHECK_PKG_INSTALLED='dpkg-query -s'
|
CHECK_PKG_INSTALLED='dpkg-query -s'
|
||||||
|
|
||||||
if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then
|
if grep -qsEe "^NAME\=['\"]?Alpine[a-zA-Z ]*['\"]?$" /etc/os-release; then
|
||||||
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
CHECK_PKG_INSTALLED='apk --no-cache info -e'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Must be root to use this tool
|
# Must be root to use this tool
|
||||||
if [ $EUID -ne 0 ]; then
|
if [[ "${EUID}" -ne 0 ]]; then
|
||||||
if eval "${CHECK_PKG_INSTALLED} sudo" &> /dev/null; then
|
if ${CHECK_PKG_INSTALLED} sudo &> /dev/null; then
|
||||||
export SUDO="sudo"
|
export SUDO="sudo"
|
||||||
else
|
else
|
||||||
echo "::: Please install sudo or run this as root."
|
err "::: Please install sudo or run this as root."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
scriptdir="/opt/pivpn"
|
scriptdir="/opt/pivpn"
|
||||||
vpn="wireguard"
|
vpn="wireguard"
|
||||||
|
|
||||||
makeConf(){
|
err() {
|
||||||
shift
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
$SUDO ${scriptdir}/${vpn}/makeCONF.sh "$@"
|
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listConnected(){
|
makeConf() {
|
||||||
shift
|
shift
|
||||||
$SUDO ${scriptdir}/${vpn}/clientSTAT.sh "$@"
|
${SUDO} "${scriptdir}/${vpn}/makeCONF.sh" "$@"
|
||||||
exit "$?"
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(){
|
listConnected() {
|
||||||
echo "::: Generating Debug Output"
|
shift
|
||||||
$SUDO ${scriptdir}/${vpn}/pivpnDEBUG.sh | tee /tmp/debug.log
|
${SUDO} "${scriptdir}/${vpn}/clientSTAT.sh" "$@"
|
||||||
echo "::: "
|
exit "${?}"
|
||||||
echo "::: Debug output completed above."
|
|
||||||
echo "::: Copy saved to /tmp/debug.log"
|
|
||||||
echo "::: "
|
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listClients(){
|
debug() {
|
||||||
$SUDO ${scriptdir}/${vpn}/listCONF.sh
|
echo "::: Generating Debug Output"
|
||||||
exit "$?"
|
|
||||||
|
${SUDO} "${scriptdir}/${vpn}/pivpnDEBUG.sh" | tee /tmp/debug.log
|
||||||
|
|
||||||
|
echo "::: "
|
||||||
|
echo "::: Debug output completed above."
|
||||||
|
echo "::: Copy saved to /tmp/debug.log"
|
||||||
|
echo "::: "
|
||||||
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
showQrcode(){
|
listClients() {
|
||||||
shift
|
${SUDO} "${scriptdir}/${vpn}/listCONF.sh"
|
||||||
$SUDO ${scriptdir}/${vpn}/qrcodeCONF.sh "$@"
|
exit "${?}"
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeClient(){
|
showQrcode() {
|
||||||
shift
|
shift
|
||||||
$SUDO ${scriptdir}/${vpn}/removeCONF.sh "$@"
|
${SUDO} "${scriptdir}/${vpn}/qrcodeCONF.sh" "$@"
|
||||||
exit "$?"
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
disableClient(){
|
removeClient() {
|
||||||
shift
|
shift
|
||||||
$SUDO ${scriptdir}/${vpn}/disableCONF.sh "$@"
|
${SUDO} "${scriptdir}/${vpn}/removeCONF.sh" "$@"
|
||||||
exit "$?"
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
enableClient(){
|
disableClient() {
|
||||||
shift
|
shift
|
||||||
$SUDO ${scriptdir}/${vpn}/enableCONF.sh "$@"
|
${SUDO} "${scriptdir}/${vpn}/disableCONF.sh" "$@"
|
||||||
exit "$?"
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
uninstallServer(){
|
enableClient() {
|
||||||
$SUDO ${scriptdir}/uninstall.sh "${vpn}"
|
shift
|
||||||
exit "$?"
|
${SUDO} "${scriptdir}/${vpn}/enableCONF.sh" "$@"
|
||||||
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
updateScripts(){
|
uninstallServer() {
|
||||||
shift
|
${SUDO} "${scriptdir}/uninstall.sh" "${vpn}"
|
||||||
$SUDO ${scriptdir}/update.sh "$@"
|
exit "${?}"
|
||||||
exit "$?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backup(){
|
updateScripts() {
|
||||||
$SUDO ${scriptdir}/backup.sh "${vpn}"
|
shift
|
||||||
exit "$?"
|
${SUDO} "${scriptdir}/update.sh" "$@"
|
||||||
|
exit "${?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
showHelp(){
|
backup() {
|
||||||
echo "::: Control all PiVPN specific functions!"
|
${SUDO} "${scriptdir}/backup.sh" "${vpn}"
|
||||||
echo ":::"
|
exit "${?}"
|
||||||
echo "::: Usage: pivpn <command> [option]"
|
|
||||||
echo ":::"
|
|
||||||
echo "::: Commands:"
|
|
||||||
echo "::: -a, add Create a client conf profile"
|
|
||||||
echo "::: -c, clients List any connected clients to the server"
|
|
||||||
echo "::: -d, debug Start a debugging session if having trouble"
|
|
||||||
echo "::: -l, list List all clients"
|
|
||||||
echo "::: -qr, qrcode Show the qrcode of a client for use with the mobile app"
|
|
||||||
echo "::: -r, remove Remove a client"
|
|
||||||
echo "::: -off, off Disable a client"
|
|
||||||
echo "::: -on, on Enable a client"
|
|
||||||
echo "::: -h, help Show this help dialog"
|
|
||||||
echo "::: -u, uninstall Uninstall pivpn from your system!"
|
|
||||||
echo "::: -up, update Updates PiVPN Scripts"
|
|
||||||
echo "::: -bk, backup Backup VPN configs and user profiles"
|
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ $# = 0 ]; then
|
showHelp() {
|
||||||
showHelp
|
echo "::: Control all PiVPN specific functions!"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Usage: pivpn <command> [option]"
|
||||||
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: -a, add Create a client conf profile"
|
||||||
|
echo "::: -c, clients List any connected clients to the server"
|
||||||
|
echo "::: -d, debug Start a debugging session if having trouble"
|
||||||
|
echo "::: -l, list List all clients"
|
||||||
|
echo -n "::: -qr, qrcode Show the qrcode of a client for use "
|
||||||
|
echo "with the mobile app"
|
||||||
|
echo "::: -r, remove Remove a client"
|
||||||
|
echo "::: -off, off Disable a client"
|
||||||
|
echo "::: -on, on Enable a client"
|
||||||
|
echo "::: -h, help Show this help dialog"
|
||||||
|
echo "::: -u, uninstall Uninstall pivpn from your system!"
|
||||||
|
echo "::: -up, update Updates PiVPN Scripts"
|
||||||
|
echo "::: -bk, backup Backup VPN configs and user profiles"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$#" == 0 ]]; then
|
||||||
|
showHelp
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Handle redirecting to specific functions based on arguments
|
# Handle redirecting to specific functions based on arguments
|
||||||
case "$1" in
|
case "${1}" in
|
||||||
"-a" | "add" ) makeConf "$@";;
|
"-a" | "add")
|
||||||
"-c" | "clients" ) listConnected "$@";;
|
makeConf "$@"
|
||||||
"-d" | "debug" ) debug;;
|
;;
|
||||||
"-l" | "list" ) listClients;;
|
"-c" | "clients")
|
||||||
"-qr" | "qrcode" ) showQrcode "$@";;
|
listConnected "$@"
|
||||||
"-r" | "remove" ) removeClient "$@";;
|
;;
|
||||||
"-off" | "off" ) disableClient "$@";;
|
"-d" | "debug")
|
||||||
"-on" | "on" ) enableClient "$@";;
|
debug
|
||||||
"-h" | "help" ) showHelp;;
|
;;
|
||||||
"-u" | "uninstall" ) uninstallServer;;
|
"-l" | "list")
|
||||||
"-up" | "update" ) updateScripts "$@" ;;
|
listClients
|
||||||
"-bk" | "backup" ) backup ;;
|
;;
|
||||||
* ) showHelp;;
|
"-qr" | "qrcode")
|
||||||
|
showQrcode "$@"
|
||||||
|
;;
|
||||||
|
"-r" | "remove")
|
||||||
|
removeClient "$@"
|
||||||
|
;;
|
||||||
|
"-off" | "off")
|
||||||
|
disableClient "$@"
|
||||||
|
;;
|
||||||
|
"-on" | "on")
|
||||||
|
enableClient "$@"
|
||||||
|
;;
|
||||||
|
"-h" | "help")
|
||||||
|
showHelp
|
||||||
|
;;
|
||||||
|
"-u" | "uninstall")
|
||||||
|
uninstallServer
|
||||||
|
;;
|
||||||
|
"-up" | "update")
|
||||||
|
updateScripts "$@"
|
||||||
|
;;
|
||||||
|
"-bk" | "backup")
|
||||||
|
backup
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
showHelp
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
# This scripts runs as root
|
# This scripts runs as root
|
||||||
|
|
||||||
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
err() {
|
||||||
echo "::: Missing setup vars file!"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
exit 1
|
}
|
||||||
|
|
||||||
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
|
err "::: Missing setup vars file!"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
|
@ -15,51 +19,75 @@ echo -e "::::\t\t\e[4mPiVPN debug\e[0m\t\t ::::"
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e "::::\t\t\e[4mLatest commit\e[0m\t\t ::::"
|
echo -e "::::\t\t\e[4mLatest commit\e[0m\t\t ::::"
|
||||||
echo -n "Branch: "
|
echo -n "Branch: "
|
||||||
|
|
||||||
git --git-dir /usr/local/src/pivpn/.git rev-parse --abbrev-ref HEAD
|
git --git-dir /usr/local/src/pivpn/.git rev-parse --abbrev-ref HEAD
|
||||||
git --git-dir /usr/local/src/pivpn/.git log -n 1 --format='Commit: %H%nAuthor: %an%nDate: %ad%nSummary: %s'
|
git \
|
||||||
|
--git-dir /usr/local/src/pivpn/.git log -n 1 \
|
||||||
|
--format='Commit: %H%nAuthor: %an%nDate: %ad%nSummary: %s'
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e "::::\t \e[4mInstallation settings\e[0m \t ::::"
|
echo -e "::::\t \e[4mInstallation settings\e[0m \t ::::"
|
||||||
|
|
||||||
# Disabling SC2154 warning, variable is sourced externaly and may vary
|
# Disabling SC2154 warning, variable is sourced externaly and may vary
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
sed "s/$pivpnHOST/REDACTED/" < ${setupVars}
|
sed "s/${pivpnHOST}/REDACTED/" < "${setupVars}"
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: \e[4mServer configuration shown below\e[0m ::::"
|
echo -e ":::: \e[4mServer configuration shown below\e[0m ::::"
|
||||||
|
|
||||||
cd /etc/wireguard/keys || exit
|
cd /etc/wireguard/keys || exit
|
||||||
cp ../wg0.conf ../wg0.tmp
|
cp ../wg0.conf ../wg0.tmp
|
||||||
|
|
||||||
# Replace every key in the server configuration with just its file name
|
# Replace every key in the server configuration with just its file name
|
||||||
for k in *; do
|
for k in *; do
|
||||||
sed "s#$(<"$k")#$k#" -i ../wg0.tmp
|
sed "s#$(< "${k}")#${k}#" -i ../wg0.tmp
|
||||||
done
|
done
|
||||||
|
|
||||||
cat ../wg0.tmp
|
cat ../wg0.tmp
|
||||||
rm ../wg0.tmp
|
rm ../wg0.tmp
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: \e[4mClient configuration shown below\e[0m ::::"
|
echo -e ":::: \e[4mClient configuration shown below\e[0m ::::"
|
||||||
|
|
||||||
EXAMPLE="$(head -1 /etc/wireguard/configs/clients.txt | awk '{print $1}')"
|
EXAMPLE="$(head -1 /etc/wireguard/configs/clients.txt | awk '{print $1}')"
|
||||||
if [ -n "$EXAMPLE" ]; then
|
|
||||||
cp ../configs/"$EXAMPLE".conf ../configs/"$EXAMPLE".tmp
|
if [[ -n "${EXAMPLE}" ]]; then
|
||||||
for k in *; do
|
cp ../configs/"${EXAMPLE}".conf ../configs/"${EXAMPLE}".tmp
|
||||||
sed "s#$(<"$k")#$k#" -i ../configs/"$EXAMPLE".tmp
|
|
||||||
done
|
for k in *; do
|
||||||
sed "s/$pivpnHOST/REDACTED/" < ../configs/"$EXAMPLE".tmp
|
sed "s#$(< "${k}")#${k}#" -i ../configs/"${EXAMPLE}".tmp
|
||||||
rm ../configs/"$EXAMPLE".tmp
|
done
|
||||||
|
|
||||||
|
sed "s/${pivpnHOST}/REDACTED/" < ../configs/"${EXAMPLE}".tmp
|
||||||
|
rm ../configs/"${EXAMPLE}".tmp
|
||||||
else
|
else
|
||||||
echo "::: There are no clients yet"
|
echo "::: There are no clients yet"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: \t\e[4mRecursive list of files in\e[0m\t ::::\n::::\t\e[4m/etc/wireguard shown below\e[0m\t ::::"
|
echo -e ":::: \t\e[4mRecursive list of files in\e[0m\t ::::"
|
||||||
|
echo -e "::::\t\e[4m/etc/wireguard shown below\e[0m\t ::::"
|
||||||
|
|
||||||
ls -LR /etc/wireguard
|
ls -LR /etc/wireguard
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e "::::\t\t\e[4mSelf check\e[0m\t\t ::::"
|
echo -e "::::\t\t\e[4mSelf check\e[0m\t\t ::::"
|
||||||
|
|
||||||
/opt/pivpn/self_check.sh "${VPN}"
|
/opt/pivpn/self_check.sh "${VPN}"
|
||||||
|
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: Having trouble connecting? Take a look at the FAQ:"
|
echo -e ":::: Having trouble connecting? Take a look at the FAQ:"
|
||||||
echo -e ":::: \e[1mhttps://docs.pivpn.io/faq\e[0m"
|
echo -e ":::: \e[1mhttps://docs.pivpn.io/faq\e[0m"
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e ":::: \e[1mWARNING\e[0m: This script should have automatically masked sensitive ::::"
|
echo -ne ":::: \e[1mWARNING\e[0m: This script should have "
|
||||||
echo -e ":::: information, however, still make sure that \e[4mPrivateKey\e[0m, \e[4mPublicKey\e[0m ::::"
|
echo -e "automatically masked sensitive ::::"
|
||||||
echo -e ":::: and \e[4mPresharedKey\e[0m are masked before reporting an issue. An example key ::::"
|
echo -ne ":::: information, however, still make sure that "
|
||||||
echo ":::: that you should NOT see in this log looks like this: ::::"
|
echo -e "\e[4mPrivateKey\e[0m, \e[4mPublicKey\e[0m ::::"
|
||||||
echo ":::: YIAoJVsdIeyvXfGGDDadHh6AxsMRymZTnnzZoAb9cxRe ::::"
|
echo -ne ":::: and \e[4mPresharedKey\e[0m are masked before "
|
||||||
|
echo -e "reporting an issue. An example key ::::"
|
||||||
|
echo -n ":::: that you should NOT see in this log looks like this:"
|
||||||
|
echo " ::::"
|
||||||
|
echo -n ":::: YIAoJVsdIeyvXfGGDDadHh6AxsMRymZTnnzZoAb9cxRe"
|
||||||
|
echo " ::::"
|
||||||
printf "=============================================\n"
|
printf "=============================================\n"
|
||||||
echo -e "::::\t\t\e[4mDebug complete\e[0m\t\t ::::"
|
echo -e "::::\t\t\e[4mDebug complete\e[0m\t\t ::::"
|
||||||
|
|
|
@ -1,76 +1,91 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
helpFunc(){
|
err() {
|
||||||
echo "::: Show the qrcode of a client for use with the mobile app"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
}
|
||||||
echo "::: Usage: pivpn <-qr|qrcode> [-h|--help] [Options] [<client-1>] ... [<client-n>] ..."
|
|
||||||
echo ":::"
|
helpFunc() {
|
||||||
echo "::: Options:"
|
echo "::: Show the qrcode of a client for use with the mobile app"
|
||||||
echo "::: -a256|ansi256 Shows QR Code in ansi256 characters"
|
echo ":::"
|
||||||
echo "::: Commands:"
|
echo -n "::: Usage: pivpn <-qr|qrcode> [-h|--help] [Options] "
|
||||||
echo "::: [none] Interactive mode"
|
echo "[<client-1> ... [<client-2>] ...]"
|
||||||
echo "::: <client> Client(s) to show"
|
echo ":::"
|
||||||
echo "::: -h,--help Show this help dialog"
|
echo "::: Options:"
|
||||||
|
echo "::: -a256|ansi256 Shows QR Code in ansi256 characters"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] Interactive mode"
|
||||||
|
echo "::: <client> Client(s) to show"
|
||||||
|
echo "::: -h,--help Show this help dialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse input arguments
|
# Parse input arguments
|
||||||
encoding="ansiutf8"
|
encoding="ansiutf8"
|
||||||
while test $# -gt 0; do
|
|
||||||
_key="$1"
|
while [[ "$#" -gt 0 ]]; do
|
||||||
case "$_key" in
|
_key="${1}"
|
||||||
-h|--help)
|
|
||||||
helpFunc
|
case "${_key}" in
|
||||||
exit 0
|
-h | --help)
|
||||||
;;
|
helpFunc
|
||||||
-a256|--ansi256)
|
exit 0
|
||||||
encoding="ansi256"
|
;;
|
||||||
;;
|
-a256 | --ansi256)
|
||||||
*)
|
encoding="ansi256"
|
||||||
CLIENTS_TO_SHOW+=("$1")
|
;;
|
||||||
;;
|
*)
|
||||||
esac
|
CLIENTS_TO_SHOW+=("${1}")
|
||||||
shift
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
cd /etc/wireguard/configs || exit
|
cd /etc/wireguard/configs || exit
|
||||||
if [ ! -s clients.txt ]; then
|
|
||||||
echo "::: There are no clients to show"
|
if [[ ! -s clients.txt ]]; then
|
||||||
exit 1
|
err "::: There are no clients to show"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mapfile -t LIST < <(awk '{print $1}' clients.txt)
|
mapfile -t LIST < <(awk '{print $1}' clients.txt)
|
||||||
if [ "${#CLIENTS_TO_SHOW[@]}" -eq 0 ]; then
|
|
||||||
|
|
||||||
echo -e "::\e[4m Client list \e[0m::"
|
if [[ "${#CLIENTS_TO_SHOW[@]}" -eq 0 ]]; then
|
||||||
len=${#LIST[@]}
|
echo -e "::\e[4m Client list \e[0m::"
|
||||||
COUNTER=1
|
len="${#LIST[@]}"
|
||||||
while [ $COUNTER -le "${len}" ]; do
|
COUNTER=1
|
||||||
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 show: " CLIENTS_TO_SHOW
|
while [[ "${COUNTER}" -le "${len}" ]]; do
|
||||||
|
printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER - 1))]}"
|
||||||
|
((COUNTER++))
|
||||||
|
done
|
||||||
|
|
||||||
if [ -z "${CLIENTS_TO_SHOW}" ]; then
|
echo -n "Please enter the Index/Name of the Client to show: "
|
||||||
echo "::: You can not leave this blank!"
|
read -r CLIENTS_TO_SHOW
|
||||||
exit 1
|
|
||||||
fi
|
if [[ -z "${CLIENTS_TO_SHOW}" ]]; then
|
||||||
|
err "::: You can not leave this blank!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for CLIENT_NAME in "${CLIENTS_TO_SHOW[@]}"; do
|
for CLIENT_NAME in "${CLIENTS_TO_SHOW[@]}"; do
|
||||||
re='^[0-9]+$'
|
re='^[0-9]+$'
|
||||||
if [[ ${CLIENT_NAME:0:1} == "-" ]]; then
|
|
||||||
echo "${CLIENT_NAME} is not a valid client name or option"
|
if [[ "${CLIENT_NAME:0:1}" == "-" ]]; then
|
||||||
exit 1
|
err "${CLIENT_NAME} is not a valid client name or option"
|
||||||
elif [[ ${CLIENT_NAME} =~ $re ]] ; then
|
exit 1
|
||||||
CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]}
|
elif [[ "${CLIENT_NAME}" =~ $re ]]; then
|
||||||
fi
|
CLIENT_NAME="${LIST[$((CLIENT_NAME - 1))]}"
|
||||||
if grep -qw "${CLIENT_NAME}" clients.txt; then
|
fi
|
||||||
echo -e "::: Showing client \e[1m${CLIENT_NAME}\e[0m below"
|
|
||||||
echo "====================================================================="
|
if grep -qw "${CLIENT_NAME}" clients.txt; then
|
||||||
qrencode -t "${encoding}" < "${CLIENT_NAME}.conf"
|
echo -e "::: Showing client \e[1m${CLIENT_NAME}\e[0m below"
|
||||||
echo "====================================================================="
|
echo "====================================================================="
|
||||||
else
|
|
||||||
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
qrencode -t "${encoding}" < "${CLIENT_NAME}.conf"
|
||||||
fi
|
|
||||||
|
echo "====================================================================="
|
||||||
|
else
|
||||||
|
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
@ -2,159 +2,182 @@
|
||||||
|
|
||||||
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
setupVars="/etc/pivpn/wireguard/setupVars.conf"
|
||||||
|
|
||||||
if [ ! -f "${setupVars}" ]; then
|
if [[ ! -f "${setupVars}" ]]; then
|
||||||
echo "::: Missing setup vars file!"
|
err "::: Missing setup vars file!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
helpFunc(){
|
err() {
|
||||||
echo "::: Remove a client conf profile"
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
echo ":::"
|
}
|
||||||
echo "::: Usage: pivpn <-r|remove> [-y|--yes] [-h|--help] [<client-1>] ... [<client-n>] ..."
|
|
||||||
echo ":::"
|
helpFunc() {
|
||||||
echo "::: Commands:"
|
echo "::: Remove a client conf profile"
|
||||||
echo "::: [none] Interactive mode"
|
echo ":::"
|
||||||
echo "::: <client> Client(s) to remove"
|
echo -n "::: Usage: pivpn <-r|remove> [-y|--yes] [-h|--help] "
|
||||||
echo "::: -y,--yes Remove Client(s) without confirmation"
|
echo "[<client-1> ... [<client-2>] ...]"
|
||||||
echo "::: -h,--help Show this help dialog"
|
echo ":::"
|
||||||
|
echo "::: Commands:"
|
||||||
|
echo "::: [none] Interactive mode"
|
||||||
|
echo "::: <client> Client(s) to remove"
|
||||||
|
echo "::: -y,--yes Remove Client(s) without confirmation"
|
||||||
|
echo "::: -h,--help Show this help dialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse input arguments
|
# Parse input arguments
|
||||||
while test $# -gt 0
|
while [[ "$#" -gt 0 ]]; do
|
||||||
do
|
_key="${1}"
|
||||||
_key="$1"
|
|
||||||
case "$_key" in
|
case "${_key}" in
|
||||||
-h|--help)
|
-h | --help)
|
||||||
helpFunc
|
helpFunc
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
-y|--yes)
|
-y | --yes)
|
||||||
CONFIRM=true
|
CONFIRM=true
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
CLIENTS_TO_REMOVE+=("$1")
|
CLIENTS_TO_REMOVE+=("${1}")
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
|
||||||
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
cd /etc/wireguard || exit
|
cd /etc/wireguard || exit
|
||||||
if [ ! -s configs/clients.txt ]; then
|
|
||||||
echo "::: There are no clients to remove"
|
if [[ ! -s configs/clients.txt ]]; then
|
||||||
exit 1
|
err "::: There are no clients to remove"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mapfile -t LIST < <(awk '{print $1}' configs/clients.txt)
|
mapfile -t LIST < <(awk '{print $1}' configs/clients.txt)
|
||||||
if [ "${#CLIENTS_TO_REMOVE[@]}" -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
|
|
||||||
|
|
||||||
read -r -p "Please enter the Index/Name of the Client to be removed from the list above: " CLIENTS_TO_REMOVE
|
if [[ "${#CLIENTS_TO_REMOVE[@]}" -eq 0 ]]; then
|
||||||
|
echo -e "::\e[4m Client list \e[0m::"
|
||||||
|
len="${#LIST[@]}"
|
||||||
|
COUNTER=1
|
||||||
|
|
||||||
if [ -z "${CLIENTS_TO_REMOVE}" ]; then
|
while [[ "${COUNTER}" -le "${len}" ]]; do
|
||||||
echo "::: You can not leave this blank!"
|
printf "%0${#len}s) %s\r\n" "${COUNTER}" "${LIST[(($COUNTER - 1))]}"
|
||||||
exit 1
|
((COUNTER++))
|
||||||
fi
|
done
|
||||||
|
|
||||||
|
echo -n "Please enter the Index/Name of the Client to be removed "
|
||||||
|
echo -n "from the list above: "
|
||||||
|
read -r CLIENTS_TO_REMOVE
|
||||||
|
|
||||||
|
if [[ -z "${CLIENTS_TO_REMOVE}" ]]; then
|
||||||
|
err "::: You can not leave this blank!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DELETED_COUNT=0
|
DELETED_COUNT=0
|
||||||
|
|
||||||
for CLIENT_NAME in "${CLIENTS_TO_REMOVE[@]}"; do
|
for CLIENT_NAME in "${CLIENTS_TO_REMOVE[@]}"; do
|
||||||
|
re='^[0-9]+$'
|
||||||
|
|
||||||
re='^[0-9]+$'
|
if [[ "${CLIENT_NAME}" =~ $re ]]; then
|
||||||
if [[ ${CLIENT_NAME} =~ $re ]] ; then
|
CLIENT_NAME="${LIST[$((CLIENT_NAME - 1))]}"
|
||||||
CLIENT_NAME=${LIST[$((CLIENT_NAME -1))]}
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then
|
if ! grep -q "^${CLIENT_NAME} " configs/clients.txt; then
|
||||||
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
echo -e "::: \e[1m${CLIENT_NAME}\e[0m does not exist"
|
||||||
|
else
|
||||||
|
REQUESTED="$(sha256sum "configs/${CLIENT_NAME}.conf" | cut -c 1-64)"
|
||||||
|
|
||||||
|
if [[ -n "${CONFIRM}" ]]; then
|
||||||
|
REPLY="y"
|
||||||
else
|
else
|
||||||
REQUESTED="$(sha256sum "configs/${CLIENT_NAME}.conf" | cut -c 1-64)"
|
read -r -p "Do you really want to delete ${CLIENT_NAME}? [y/N] "
|
||||||
if [ -n "$CONFIRM" ]; then
|
|
||||||
REPLY="y"
|
|
||||||
else
|
|
||||||
read -r -p "Do you really want to delete $CLIENT_NAME? [y/N] "
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
|
|
||||||
# Grab the least significant octed of the client IP address
|
|
||||||
COUNT=$(grep "^${CLIENT_NAME} " configs/clients.txt | awk '{print $4}')
|
|
||||||
# The creation date of the client
|
|
||||||
CREATION_DATE="$(grep "^${CLIENT_NAME} " configs/clients.txt | awk '{print $3}')"
|
|
||||||
# And its public key
|
|
||||||
PUBLIC_KEY="$(grep "^${CLIENT_NAME} " configs/clients.txt | awk '{print $2}')"
|
|
||||||
|
|
||||||
# Then remove the client matching the variables above
|
|
||||||
sed "\#${CLIENT_NAME} ${PUBLIC_KEY} ${CREATION_DATE} ${COUNT}#d" -i configs/clients.txt
|
|
||||||
|
|
||||||
# Remove the peer section from the server config
|
|
||||||
sed "/### begin ${CLIENT_NAME} ###/,/### end ${CLIENT_NAME} ###/d" -i wg0.conf
|
|
||||||
echo "::: Updated server config"
|
|
||||||
|
|
||||||
rm "configs/${CLIENT_NAME}.conf"
|
|
||||||
echo "::: Client config for ${CLIENT_NAME} removed"
|
|
||||||
|
|
||||||
rm "keys/${CLIENT_NAME}_priv"
|
|
||||||
rm "keys/${CLIENT_NAME}_pub"
|
|
||||||
rm "keys/${CLIENT_NAME}_psk"
|
|
||||||
echo "::: Client Keys for ${CLIENT_NAME} removed"
|
|
||||||
|
|
||||||
# Find all .conf files in the home folder of the user matching the checksum of the
|
|
||||||
# config and delete them. '-maxdepth 3' is used to avoid traversing too many folders.
|
|
||||||
# Disabling SC2154, variable sourced externaly and may vary
|
|
||||||
# shellcheck disable=SC2154
|
|
||||||
find "${install_home}" -maxdepth 3 -type f -name '*.conf' -print0 | while IFS= read -r -d '' CONFIG; do
|
|
||||||
if sha256sum -c <<< "${REQUESTED} ${CONFIG}" &> /dev/null; then
|
|
||||||
rm "${CONFIG}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
((DELETED_COUNT++))
|
|
||||||
echo "::: Successfully deleted ${CLIENT_NAME}"
|
|
||||||
|
|
||||||
# If using Pi-hole, remove the client from the hosts file
|
|
||||||
# Disabling SC2154, variable sourced externaly and may vary
|
|
||||||
# shellcheck disable=SC2154
|
|
||||||
if [ -f /etc/pivpn/hosts.wireguard ]; then
|
|
||||||
NET_REDUCED="${pivpnNET::-2}"
|
|
||||||
sed -e "\#${NET_REDUCED}.${COUNT} ${CLIENT_NAME}.pivpn#d" -e "\#${pivpnNETv6}${COUNT} ${CLIENT_NAME}.pivpn#d" -i /etc/pivpn/hosts.wireguard
|
|
||||||
if killall -SIGHUP pihole-FTL; then
|
|
||||||
echo "::: Updated hosts file for Pi-hole"
|
|
||||||
else
|
|
||||||
echo "::: Failed to reload pihole-FTL configuration"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
else
|
|
||||||
echo "Aborting operation"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
|
||||||
|
# Grab the least significant octed of the client IP address
|
||||||
|
COUNT="$(grep "^${CLIENT_NAME} " configs/clients.txt | awk '{print $4}')"
|
||||||
|
# The creation date of the client
|
||||||
|
CREATION_DATE="$(grep "^${CLIENT_NAME} " configs/clients.txt \
|
||||||
|
| awk '{print $3}')"
|
||||||
|
# And its public key
|
||||||
|
PUBLIC_KEY="$(grep "^${CLIENT_NAME} " configs/clients.txt \
|
||||||
|
| awk '{print $2}')"
|
||||||
|
|
||||||
|
# Then remove the client matching the variables above
|
||||||
|
sed \
|
||||||
|
-e "\#${CLIENT_NAME} ${PUBLIC_KEY} ${CREATION_DATE} ${COUNT}#d" \
|
||||||
|
-i configs/clients.txt
|
||||||
|
|
||||||
|
# Remove the peer section from the server config
|
||||||
|
sed_pattern="/### begin ${CLIENT_NAME} ###/,"
|
||||||
|
sed_pattern="${sed_pattern}/### end ${CLIENT_NAME} ###/d"
|
||||||
|
sed -e "${sed_pattern}" -i wg0.conf
|
||||||
|
echo "::: Updated server config"
|
||||||
|
|
||||||
|
rm "configs/${CLIENT_NAME}.conf"
|
||||||
|
echo "::: Client config for ${CLIENT_NAME} removed"
|
||||||
|
|
||||||
|
rm "keys/${CLIENT_NAME}_priv"
|
||||||
|
rm "keys/${CLIENT_NAME}_pub"
|
||||||
|
rm "keys/${CLIENT_NAME}_psk"
|
||||||
|
echo "::: Client Keys for ${CLIENT_NAME} removed"
|
||||||
|
|
||||||
|
# Find all .conf files in the home folder of the user matching the
|
||||||
|
# checksum of the config and delete them. '-maxdepth 3' is used to
|
||||||
|
# avoid traversing too many folders.
|
||||||
|
# Disabling SC2154, variable sourced externaly and may vary
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
while IFS= read -r -d '' CONFIG; do
|
||||||
|
if sha256sum -c <<< "${REQUESTED} ${CONFIG}" &> /dev/null; then
|
||||||
|
rm "${CONFIG}"
|
||||||
|
fi
|
||||||
|
done < <(find "${install_home}" \
|
||||||
|
-maxdepth 3 -type f -name '*.conf' -print0)
|
||||||
|
|
||||||
|
((DELETED_COUNT++))
|
||||||
|
echo "::: Successfully deleted ${CLIENT_NAME}"
|
||||||
|
|
||||||
|
# If using Pi-hole, remove the client from the hosts file
|
||||||
|
# Disabling SC2154, variable sourced externaly and may vary
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
if [[ -f /etc/pivpn/hosts.wireguard ]]; then
|
||||||
|
NET_REDUCED="${pivpnNET::-2}"
|
||||||
|
sed \
|
||||||
|
-e "\#${NET_REDUCED}.${COUNT} ${CLIENT_NAME}.pivpn#d" \
|
||||||
|
-e "\#${pivpnNETv6}${COUNT} ${CLIENT_NAME}.pivpn#d" \
|
||||||
|
-i /etc/pivpn/hosts.wireguard
|
||||||
|
|
||||||
|
if killall -SIGHUP pihole-FTL; then
|
||||||
|
echo "::: Updated hosts file for Pi-hole"
|
||||||
|
else
|
||||||
|
err "::: Failed to reload pihole-FTL configuration"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset sed_pattern
|
||||||
|
else
|
||||||
|
err "Aborting operation"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Restart WireGuard only if some clients were actually deleted
|
# Restart WireGuard only if some clients were actually deleted
|
||||||
if [ "${DELETED_COUNT}" -gt 0 ]; then
|
if [[ "${DELETED_COUNT}" -gt 0 ]]; then
|
||||||
if [ "${PLAT}" == 'Alpine' ]; then
|
if [[ "${PLAT}" == 'Alpine' ]]; then
|
||||||
if rc-service wg-quick restart; then
|
if rc-service wg-quick restart; then
|
||||||
echo "::: WireGuard reloaded"
|
echo "::: WireGuard reloaded"
|
||||||
else
|
|
||||||
echo "::: Failed to reload WireGuard"
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
if systemctl reload wg-quick@wg0; then
|
err "::: Failed to reload WireGuard"
|
||||||
echo "::: WireGuard reloaded"
|
|
||||||
else
|
|
||||||
echo "::: Failed to reload WireGuard"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
if systemctl reload wg-quick@wg0; then
|
||||||
|
echo "::: WireGuard reloaded"
|
||||||
|
else
|
||||||
|
err "::: Failed to reload WireGuard"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in a new issue