From 5d2761b94be19f34cdbcf64c309944ea061e24eb Mon Sep 17 00:00:00 2001 From: Douglas Orend <43975081+xptsp@users.noreply.github.com> Date: Tue, 20 Oct 2020 10:57:28 -0500 Subject: [PATCH 01/12] Update listOVPN.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit allows PiVPN scripts to display certificates with common names like "José" better. Prior to this commit, names like "José" would be shown as "Jos\xC3\xA9". --- scripts/openvpn/listOVPN.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/openvpn/listOVPN.sh b/scripts/openvpn/listOVPN.sh index cd02790..6fba929 100755 --- a/scripts/openvpn/listOVPN.sh +++ b/scripts/openvpn/listOVPN.sh @@ -28,13 +28,13 @@ while read -r line || [ -n "$line" ]; do EXPD=$(echo "$line" | awk '{if (length($2) == 15) print $2; else print "20"$2}' | cut -b 1-8 | date +"%b %d %Y" -f -) if [ "${STATUS}" == "V" ]; then - printf "Valid \t %s \t %s\\n" "$NAME" "$EXPD" + printf "Valid \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD" elif [ "${STATUS}" == "R" ]; then - printf "Revoked \t %s \t %s\\n" "$NAME" "$EXPD" + printf "Revoked \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD" elif [ "${STATUS}" == "E" ]; then - printf "Expired \t %s \t %s\\n" "$NAME" "$EXPD" + printf "Expired \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD" else - printf "Unknown \t %s \t %s\\n" "$NAME" "$EXPD" + printf "Unknown \t %s \t %s\\n" "$(echo -e "$NAME")" "$EXPD" fi done <${INDEX} From 22cb5ee0ef704c2ca5f068a0a0dd096cd4848fcc Mon Sep 17 00:00:00 2001 From: Douglas Orend <43975081+xptsp@users.noreply.github.com> Date: Tue, 20 Oct 2020 11:00:35 -0500 Subject: [PATCH 02/12] Update removeOVPN.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit allows PiVPN scripts to revoke certificates with common names like "José" better. Prior to this commit, names like "José" could not be revoked using PiVPN tools. --- scripts/openvpn/removeOVPN.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/openvpn/removeOVPN.sh b/scripts/openvpn/removeOVPN.sh index 30bfac7..a77333b 100755 --- a/scripts/openvpn/removeOVPN.sh +++ b/scripts/openvpn/removeOVPN.sh @@ -58,7 +58,7 @@ if [[ -z "${CERTS_TO_REVOKE}" ]]; then NAME=$(echo "$line" | sed -e 's:.*/CN=::') if [ "$i" != 0 ]; then # Prevent printing "server" certificate - CERTS[$i]=${NAME} + CERTS[$i]=$(echo -e "${NAME}") fi let i=i+1 fi @@ -102,7 +102,7 @@ else while read -r line || [ -n "$line" ]; do STATUS=$(echo "$line" | awk '{print $1}') if [[ "${STATUS}" = "V" ]]; then - NAME=$(echo "$line" | sed -e 's:.*/CN=::') + NAME=$(echo -e "$line" | sed -e 's:.*/CN=::') CERTS[$i]=${NAME} let i=i+1 fi From 9955f1fc024bcd5fb3ef76ee39af53ea16935cd7 Mon Sep 17 00:00:00 2001 From: Orazio Date: Sat, 24 Oct 2020 13:16:56 +0200 Subject: [PATCH 03/12] Updated WireGuard module detection to accommodate different paths --- auto_install/install.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/auto_install/install.sh b/auto_install/install.sh index e37ef3e..1e2d083 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -77,6 +77,9 @@ c=$(( c < 70 ? 70 : c )) # Override localization settings so the output is in English language. export LC_ALL=C +# Enable recursive globbing to find wireguard.ko in /lib/modules. +shopt -s globstar + main(){ ######## FIRST CHECK ######## @@ -488,7 +491,7 @@ preconfigurePackages(){ # make the module part of the package since the module itself is built at install time # and not part of the .deb). # Source: https://github.com/MichaIng/DietPi/blob/7bf5e1041f3b2972d7827c48215069d1c90eee07/dietpi/dietpi-software#L1807-L1815 - for i in /lib/modules/*/kernel/net/wireguard/wireguard.ko; do + for i in /lib/modules/**/wireguard.ko; do [[ -f $i ]] || continue dpkg-query -S "$i" &> /dev/null || continue WIREGUARD_BUILTIN=1 From d860f1d40247a30556f819a06cbf87cda43c938e Mon Sep 17 00:00:00 2001 From: Orazio Date: Sat, 24 Oct 2020 13:41:07 +0200 Subject: [PATCH 04/12] Add systemd override for wg-quick units that don't yet implement reload - Discussed on pull request 1164 --- auto_install/install.sh | 7 +++++++ files/etc/systemd/system/wg-quick@.service.d/override.conf | 2 ++ scripts/uninstall.sh | 4 ++++ 3 files changed, 13 insertions(+) create mode 100644 files/etc/systemd/system/wg-quick@.service.d/override.conf diff --git a/auto_install/install.sh b/auto_install/install.sh index 1e2d083..7ed1c33 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -2037,6 +2037,13 @@ confOVPN(){ } confWireGuard(){ + # Reload job type is not yet available in wireguard-tools shipped with Ubuntu 20.04 + if ! grep -q 'ExecReload' /usr/lib/systemd/system/wg-quick@.service; then + echo "::: Adding additional reload job type for wg-quick unit" + $SUDOE install -m 644 "${pivpnFilesDir}"/files/etc/systemd/system/wg-quick@.service.d/override.conf /etc/systemd/system/wg-quick@.service.d/override.conf + $SUDO systemctl daemon-reload + fi + if [ -d /etc/wireguard ]; then # Backup the wireguard folder WIREGUARD_BACKUP="wireguard_$(date +%Y-%m-%d-%H%M%S).tar.gz" diff --git a/files/etc/systemd/system/wg-quick@.service.d/override.conf b/files/etc/systemd/system/wg-quick@.service.d/override.conf new file mode 100644 index 0000000..54e6bb8 --- /dev/null +++ b/files/etc/systemd/system/wg-quick@.service.d/override.conf @@ -0,0 +1,2 @@ +[Service] +ExecReload=/bin/bash -c 'exec /usr/bin/wg syncconf %i <(exec /usr/bin/wg-quick strip %i)' diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh index 7b00b78..4e04f05 100755 --- a/scripts/uninstall.sh +++ b/scripts/uninstall.sh @@ -146,6 +146,10 @@ removeAll(){ ${UPDATE_PKG_CACHE} &> /dev/null & spinner $! fi + if [ -f /etc/systemd/system/wg-quick@.service.d/override.conf ]; then + rm -f /etc/systemd/system/wg-quick@.service.d/override.conf + fi + elif [ "${i}" = "unattended-upgrades" ]; then rm -rf /var/log/unattended-upgrades From 43057b3f3b66225358b23362803fcb2782ab5f7f Mon Sep 17 00:00:00 2001 From: Orazio Date: Sat, 24 Oct 2020 16:00:26 +0200 Subject: [PATCH 05/12] Fixed typos, clarified 'pivpn -l' text. --- auto_install/install.sh | 2 +- scripts/openvpn/listOVPN.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/auto_install/install.sh b/auto_install/install.sh index 7ed1c33..0cabb26 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -2040,7 +2040,7 @@ confWireGuard(){ # Reload job type is not yet available in wireguard-tools shipped with Ubuntu 20.04 if ! grep -q 'ExecReload' /usr/lib/systemd/system/wg-quick@.service; then echo "::: Adding additional reload job type for wg-quick unit" - $SUDOE install -m 644 "${pivpnFilesDir}"/files/etc/systemd/system/wg-quick@.service.d/override.conf /etc/systemd/system/wg-quick@.service.d/override.conf + $SUDO install -m 644 "${pivpnFilesDir}"/files/etc/systemd/system/wg-quick@.service.d/override.conf /etc/systemd/system/wg-quick@.service.d/override.conf $SUDO systemctl daemon-reload fi diff --git a/scripts/openvpn/listOVPN.sh b/scripts/openvpn/listOVPN.sh index 6fba929..4718f60 100755 --- a/scripts/openvpn/listOVPN.sh +++ b/scripts/openvpn/listOVPN.sh @@ -14,9 +14,9 @@ if [ ! -f "${EASYRSA}" ]; then exit 1 fi -$EASYRSA update-db >> /dev/null 2>1 +$EASYRSA update-db >> /dev/null 2>&1 -printf ": NOTE : The first entry should always be your valid server!\n" +printf ": NOTE : The first entry is your server, which should always be valid!\n" printf "\\n" printf "\\e[1m::: Certificate Status List :::\\e[0m\\n" { From 915563610d5af47ec751824d5d4ca1a341e2afc0 Mon Sep 17 00:00:00 2001 From: Jeffry Suryadharma <41689493+jeffrysurya@users.noreply.github.com> Date: Sun, 25 Oct 2020 17:37:59 +0700 Subject: [PATCH 06/12] Update install.sh add -D option because wg-quick@.service.d folder is not yet created --- auto_install/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_install/install.sh b/auto_install/install.sh index 0cabb26..0db151f 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -2040,7 +2040,7 @@ confWireGuard(){ # Reload job type is not yet available in wireguard-tools shipped with Ubuntu 20.04 if ! grep -q 'ExecReload' /usr/lib/systemd/system/wg-quick@.service; then echo "::: Adding additional reload job type for wg-quick unit" - $SUDO install -m 644 "${pivpnFilesDir}"/files/etc/systemd/system/wg-quick@.service.d/override.conf /etc/systemd/system/wg-quick@.service.d/override.conf + $SUDO install -D -m 644 "${pivpnFilesDir}"/files/etc/systemd/system/wg-quick@.service.d/override.conf /etc/systemd/system/wg-quick@.service.d/override.conf $SUDO systemctl daemon-reload fi From f1553985a65001f784be892c44d117863a9a26c3 Mon Sep 17 00:00:00 2001 From: Jeffry Suryadharma <41689493+jeffrysurya@users.noreply.github.com> Date: Sun, 25 Oct 2020 17:46:27 +0700 Subject: [PATCH 07/12] Update install.sh --- auto_install/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_install/install.sh b/auto_install/install.sh index 0db151f..c2c331b 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -13,7 +13,7 @@ # timestamp 2020/5/24 15:53BST ######## VARIABLES ######### -pivpnGitUrl="https://github.com/pivpn/pivpn.git" +pivpnGitUrl="https://github.com/jeffrysurya/pivpn.git" #pivpnGitUrl="/home/pi/repos/pivpn" setupVarsFile="setupVars.conf" setupConfigDir="/etc/pivpn" From 1ce55658aa31e511c727046d4256a64316a4de61 Mon Sep 17 00:00:00 2001 From: Jeffry Suryadharma <41689493+jeffrysurya@users.noreply.github.com> Date: Sun, 25 Oct 2020 17:54:14 +0700 Subject: [PATCH 08/12] Update install.sh --- auto_install/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_install/install.sh b/auto_install/install.sh index c2c331b..0db151f 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -13,7 +13,7 @@ # timestamp 2020/5/24 15:53BST ######## VARIABLES ######### -pivpnGitUrl="https://github.com/jeffrysurya/pivpn.git" +pivpnGitUrl="https://github.com/pivpn/pivpn.git" #pivpnGitUrl="/home/pi/repos/pivpn" setupVarsFile="setupVars.conf" setupConfigDir="/etc/pivpn" From 4f9349b576166cca1c3906ecfce9331bed822133 Mon Sep 17 00:00:00 2001 From: Orazio Date: Tue, 27 Oct 2020 08:52:51 +0100 Subject: [PATCH 09/12] Log debconf-apt-progress output to show errors in case of failed package install --- auto_install/install.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/auto_install/install.sh b/auto_install/install.sh index 0db151f..c3a1e7d 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -552,9 +552,11 @@ installDependentPackages(){ fi done + local APTLOGFILE="$(mktemp)" + if command -v debconf-apt-progress > /dev/null; then # shellcheck disable=SC2086 - $SUDO debconf-apt-progress -- ${PKG_INSTALL} "${TO_INSTALL[@]}" + $SUDO debconf-apt-progress --logfile "${APTLOGFILE}" -- ${PKG_INSTALL} "${TO_INSTALL[@]}" else # shellcheck disable=SC2086 $SUDO ${PKG_INSTALL} "${TO_INSTALL[@]}" @@ -574,6 +576,7 @@ installDependentPackages(){ done if [ "$FAILED" -gt 0 ]; then + cat "${APTLOGFILE}" exit 1 fi } From 8b69904b69994ed79914a881d3bfa4677cc73a92 Mon Sep 17 00:00:00 2001 From: Orazio Date: Tue, 27 Oct 2020 09:03:34 +0100 Subject: [PATCH 10/12] Moved Telekom Hybrid help to the wiki: - https://github.com/pivpn/pivpn/wiki/OpenVPN#trouble-with-telekom-hybrid --- scripts/openvpn/pivpnDebug.sh | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/scripts/openvpn/pivpnDebug.sh b/scripts/openvpn/pivpnDebug.sh index a3e86cf..38a8d7e 100755 --- a/scripts/openvpn/pivpnDebug.sh +++ b/scripts/openvpn/pivpnDebug.sh @@ -47,16 +47,3 @@ cat /tmp/snippet rm /tmp/snippet printf "=============================================\n" echo -e "::::\t\t\e[4mDebug complete\e[0m\t\t ::::" - -# Telekom Hybrid Check -wget -O /tmp/hybcheck http://speedport.ip &>/dev/null -if grep -Fq "Speedport Pro" /tmp/hybcheck || grep -Fq "Speedport Hybrid" /tmp/hybcheck -then - printf ":::\t\t\t\t\t:::\n::\tTelekom Hybrid Check\t\t ::\n:::\t\t\t\t\t:::\n" - echo "Are you using Telekom Hybrid (found a hybrid compatible router)?" - echo "If yes and you have problems with the connections you can test the following:" - echo "Add 'tun-mtu 1316' in /etc/openvpn/easy-rsa/pki/Default.txt to set a hybrid compatible MTU size (new .ovpn files)." - echo "For already existing .ovpn files 'tun-mtu 1316' can also be inserted there manually." - echo "With Telekom hybrid connections, you may have to experiment a little with MTU (tun-mtu, link-mtu and mssfix)." -fi -rm /tmp/hybcheck From 7f1c5ba33cc3c1eee18e381532365e63108d5a33 Mon Sep 17 00:00:00 2001 From: Orazio Date: Tue, 27 Oct 2020 12:19:46 +0100 Subject: [PATCH 11/12] Save debug to /tmp/debug.log for WireGuard too, do not use temporary file to redact IPs in the OpenVPN log. --- scripts/openvpn/pivpn.sh | 4 ++-- scripts/openvpn/pivpnDebug.sh | 9 ++++----- scripts/wireguard/pivpn.sh | 7 ++++++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/scripts/openvpn/pivpn.sh b/scripts/openvpn/pivpn.sh index 0b7feb7..59ca5c1 100755 --- a/scripts/openvpn/pivpn.sh +++ b/scripts/openvpn/pivpn.sh @@ -32,10 +32,10 @@ function listOVPNFunc { function debugFunc { echo "::: Generating Debug Output" - $SUDO ${scriptDir}/${vpn}/pivpnDebug.sh | tee /tmp/debug.txt + $SUDO ${scriptDir}/${vpn}/pivpnDebug.sh | tee /tmp/debug.log echo "::: " echo "::: Debug output completed above." - echo "::: Copy saved to /tmp/debug.txt" + echo "::: Copy saved to /tmp/debug.log" echo "::: " exit 0 } diff --git a/scripts/openvpn/pivpnDebug.sh b/scripts/openvpn/pivpnDebug.sh index 38a8d7e..46d5edd 100755 --- a/scripts/openvpn/pivpnDebug.sh +++ b/scripts/openvpn/pivpnDebug.sh @@ -34,16 +34,15 @@ echo -e ":::: Having trouble connecting? Take a look at the FAQ:" echo -e ":::: \e[1mhttps://github.com/pivpn/pivpn/wiki/FAQ\e[0m" printf "=============================================\n" echo -e ":::: \e[4mSnippet of the server log\e[0m ::::" -tail -20 /var/log/openvpn.log > /tmp/snippet +OVPNLOG="$(tail -n 20 /var/log/openvpn.log)" # Regular expession taken from https://superuser.com/a/202835, it will match invalid IPs # like 123.456.789.012 but it's fine since the log only contains valid ones. -declare -a IPS_TO_HIDE=($(grepcidr -v 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 /tmp/snippet | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | uniq)) +declare -a IPS_TO_HIDE=($(grepcidr -v 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 <<< "$OVPNLOG" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | uniq)) for IP in "${IPS_TO_HIDE[@]}"; do - sed -i "s/$IP/REDACTED/g" /tmp/snippet + OVPNLOG="${OVPNLOG//"$IP"/REDACTED}" done -cat /tmp/snippet -rm /tmp/snippet +echo "$OVPNLOG" printf "=============================================\n" echo -e "::::\t\t\e[4mDebug complete\e[0m\t\t ::::" diff --git a/scripts/wireguard/pivpn.sh b/scripts/wireguard/pivpn.sh index 61db6d9..ad4b0e7 100755 --- a/scripts/wireguard/pivpn.sh +++ b/scripts/wireguard/pivpn.sh @@ -26,7 +26,12 @@ listConnected(){ } debug(){ - $SUDO ${scriptdir}/${vpn}/pivpnDEBUG.sh + echo "::: Generating Debug Output" + $SUDO ${scriptdir}/${vpn}/pivpnDEBUG.sh | tee /tmp/debug.log + echo "::: " + echo "::: Debug output completed above." + echo "::: Copy saved to /tmp/debug.log" + echo "::: " exit 0 } From 18007bb01e8c52653c07573364dc87f42fe6af5d Mon Sep 17 00:00:00 2001 From: Orazio Date: Tue, 27 Oct 2020 18:40:16 +0100 Subject: [PATCH 12/12] OpenVPN GPG key is static, so we might as well include the key in the PiVPN repo. --- auto_install/install.sh | 46 +--------- files/etc/apt/repo-public.gpg | 162 ++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 42 deletions(-) create mode 100644 files/etc/apt/repo-public.gpg diff --git a/auto_install/install.sh b/auto_install/install.sh index c3a1e7d..ed54931 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -28,9 +28,6 @@ dhcpcdFile="/etc/dhcpcd.conf" subnetClass="24" debianOvpnUserGroup="openvpn:openvpn" -# OpenVPN GPG fingerprint, you can look it up at https://keyserver.ubuntu.com (prepend '0x' before it) -OPENVPN_KEY_ID="30EBF4E73CCE63EEE124DD278E6DA8B4E158C569" - ######## PKG Vars ######## PKG_MANAGER="apt-get" PKG_CACHE="/var/lib/apt/lists/" @@ -51,9 +48,6 @@ INSTALLED_PACKAGES=() easyrsaVer="3.0.7" easyrsaRel="https://github.com/OpenVPN/easy-rsa/releases/download/v${easyrsaVer}/EasyRSA-${easyrsaVer}.tgz" -# Fallback url for the OpenVPN key -OPENVPN_KEY_URL="https://swupdate.openvpn.net/repos/repo-public.gpg" - ######## Undocumented Flags. Shhh ######## runUnattended=false skipSpaceCheck=false @@ -1184,32 +1178,6 @@ askAboutCustomizing(){ fi } -downloadVerifyKey(){ - local KEY_URL="$1" - local EXPECTED_KEY_ID="$2" - - local KEY_CONTENT - local KEY_INFO - local DOWNLOADED_KEY_ID - - if ! KEY_CONTENT="$(wget -qO- "$KEY_URL")"; then - return 1 - fi - - if ! KEY_INFO="$(gpg --show-key --with-colons <<< "$KEY_CONTENT")"; then - return 1 - fi - - DOWNLOADED_KEY_ID="$(sed -n '/^pub:/,/^fpr:/p' <<< "$KEY_INFO" | grep '^fpr' | cut -d ':' -f 10)" - - if [ "$DOWNLOADED_KEY_ID" != "$EXPECTED_KEY_ID" ]; then - return 1 - fi - - echo "$KEY_CONTENT" - return 0 -} - installOpenVPN(){ local PIVPN_DEPS @@ -1221,17 +1189,11 @@ installOpenVPN(){ PIVPN_DEPS=(gnupg) installDependentPackages PIVPN_DEPS[@] - # We will download the repository key for the official repository from a - # keyserver. If we fail, we will attempt to download the key via HTTPS + # OpenVPN repo's public GPG key (fingerprint 0x30EBF4E73CCE63EEE124DD278E6DA8B4E158C569) echo "::: Adding repository key..." - if ! $SUDO apt-key adv --keyserver keyserver.ubuntu.com --recv-keys "$OPENVPN_KEY_ID"; then - echo "::: Import via keyserver failed, now trying wget" - if ! downloadVerifyKey "$OPENVPN_KEY_URL" "$OPENVPN_KEY_ID" | $SUDO apt-key add -; then - echo "::: Can't import OpenVPN GPG key" - exit 1 - else - echo "::: Acquired key $OPENVPN_KEY_ID" - fi + if ! $SUDO apt-key add "${pivpnFilesDir}"/files/etc/apt/repo-public.gpg; then + echo "::: Can't import OpenVPN GPG key" + exit 1 fi echo "::: Adding OpenVPN repository... " diff --git a/files/etc/apt/repo-public.gpg b/files/etc/apt/repo-public.gpg new file mode 100644 index 0000000..eaae384 --- /dev/null +++ b/files/etc/apt/repo-public.gpg @@ -0,0 +1,162 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +VHxVxJNKrv1//EX/ +=qIrL +-----END PGP PUBLIC KEY BLOCK-----