From 850e6656421c1c234794ee0dc649ad35f54c8621 Mon Sep 17 00:00:00 2001 From: Orazio <22700499+orazioedoardo@users.noreply.github.com> Date: Thu, 23 Nov 2023 11:54:07 +0100 Subject: [PATCH] Updates to subnet generation and client creation (#1782) * refactor(core): allow any subnet and netmask * fix(scripts): prevent adding more clients than the subnet allows * fix(scripts): correctly remove leading zeros from ipv6 quartets * refactor(core): new probabilistic subnet generation with fallback to other RFC1918 subnets --- auto_install/install.sh | 227 ++++++++++++++++++++++++++------ scripts/ipaddr_utils.sh | 54 ++++++++ scripts/openvpn/makeOVPN.sh | 77 ++++++----- scripts/openvpn/removeOVPN.sh | 11 +- scripts/wireguard/makeCONF.sh | 57 +++++--- scripts/wireguard/removeCONF.sh | 19 ++- 6 files changed, 339 insertions(+), 106 deletions(-) create mode 100755 scripts/ipaddr_utils.sh diff --git a/auto_install/install.sh b/auto_install/install.sh index 3b19348..7b764ac 100755 --- a/auto_install/install.sh +++ b/auto_install/install.sh @@ -1713,6 +1713,59 @@ installPiVPN() { writeVPNTempVarsFile } +decIPv4ToDot() { + local a b c d + a=$((($1 & 4278190080) >> 24)) + b=$((($1 & 16711680) >> 16)) + c=$((($1 & 65280) >> 8)) + d=$(($1 & 255)) + printf "%s.%s.%s.%s\n" $a $b $c $d +} + +dotIPv4ToDec() { + local original_ifs=$IFS + IFS='.' + read -r -a array_ip <<< "$1" + IFS=$original_ifs + printf "%s\n" $((array_ip[0] * 16777216 + array_ip[1] * 65536 + array_ip[2] * 256 + array_ip[3])) +} + +dotIPv4FirstDec() { + local decimal_ip decimal_mask + decimal_ip=$(dotIPv4ToDec "$1") + decimal_mask=$((2 ** 32 - 1 ^ (2 ** (32 - $2) - 1))) + printf "%s\n" "$((decimal_ip & decimal_mask))" +} + +dotIPv4LastDec() { + local decimal_ip decimal_mask_inv + decimal_ip=$(dotIPv4ToDec "$1") + decimal_mask_inv=$((2 ** (32 - $2) - 1)) + printf "%s\n" "$((decimal_ip | decimal_mask_inv))" +} + +decIPv4ToHex() { + local hex + hex="$(printf "%08x\n" "$1")" + quartet_hi=${hex:0:4} + quartet_lo=${hex:4:4} + # Removes leading zeros from quartets, purely for aesthetic reasons + # Source: https://stackoverflow.com/a/19861690 + leading_zeros_hi="${quartet_hi%%[!0]*}" + leading_zeros_lo="${quartet_lo%%[!0]*}" + printf "%s:%s\n" "${quartet_hi#"${leading_zeros_hi}"}" "${quartet_lo#"${leading_zeros_lo}"}" +} + +cidrToMask() { + # Source: https://stackoverflow.com/a/20767392 + set -- $((5 - (${1} / 8))) \ + 255 255 255 255 \ + $(((255 << (8 - (${1} % 8))) & 255)) \ + 0 0 0 + shift "${1}" + echo "${1-0}.${2-0}.${3-0}.${4-0}" +} + setVPNDefaultVars() { # Allow custom subnetClass via unattend setupVARs file. # Use default if not provided. @@ -1726,43 +1779,99 @@ setVPNDefaultVars() { } generateRandomSubnet() { - local MATCHES # Source: https://community.openvpn.net/openvpn/wiki/AvoidRoutingConflicts - declare -a SUBNET_EXCLUDE_LIST + declare -a excluded_subnets_dec=( + 167772160 167772415 # 10.0.0.0/24 + 167772416 167772671 # 10.0.1.0/24 + 167837952 167838207 # 10.1.1.0/24 + 167840256 167840511 # 10.1.10.0/24 + 167903232 167903487 # 10.2.0.0/24 + 168296448 168296703 # 10.8.0.0/24 + 168427776 168428031 # 10.10.1.0/24 + 173693440 173693695 # 10.90.90.0/24 + 174326016 174326271 # 10.100.1.0/24 + 184549120 184549375 # 10.255.255.0/24 + 3232235520 3232235775 # 192.168.0.0/24 + 3232235776 3232236031 # 192.168.1.0/24 + ) - SUBNET_EXCLUDE_LIST=(10.0.0.0/24) - SUBNET_EXCLUDE_LIST+=(10.0.1.0/24) - SUBNET_EXCLUDE_LIST+=(10.1.1.0/24) - SUBNET_EXCLUDE_LIST+=(10.1.10.0/24) - SUBNET_EXCLUDE_LIST+=(10.2.0.0/24) - SUBNET_EXCLUDE_LIST+=(10.8.0.0/24) - SUBNET_EXCLUDE_LIST+=(10.10.1.0/24) - SUBNET_EXCLUDE_LIST+=(10.90.90.0/24) - SUBNET_EXCLUDE_LIST+=(10.100.1.0/24) - SUBNET_EXCLUDE_LIST+=(10.255.255.0/24) - - readarray -t CURRENTLY_USED_SUBNETS <<< "$(ip route show \ + # Add numeric ranges to the previous array + readarray -t currently_used_subnets <<< "$(ip route show \ | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}')" - SUBNET_EXCLUDE_LIST=("${SUBNET_EXCLUDE_LIST[@]}" - "${CURRENTLY_USED_SUBNETS[@]}") - while true; do - MATCHES=0 - pivpnNET="10.$((RANDOM % 256)).$((RANDOM % 256)).0" + local used used_ip used_mask + for used in "${currently_used_subnets[@]}"; do + used_ip="${used%/*}" + used_mask="${used##*/}" - for SUB in "${SUBNET_EXCLUDE_LIST[@]}"; do - if grepcidr "${SUB}" <<< "${pivpnNET}/${subnetClass}" \ - 2>&1 > /dev/null; then - ((MATCHES++)) + excluded_subnets_dec+=("$(dotIPv4FirstDec "$used_ip" "$used_mask")") + excluded_subnets_dec+=("$(dotIPv4LastDec "$used_ip" "$used_mask")") + done + + # Note: excluded_subnets_count array length is twice the number of subnets + local excluded_subnets_count="${#excluded_subnets_dec[@]}" + + local source_subnet="$1" + local source_ip="${source_subnet%/*}" + # shellcheck disable=SC2155 + local source_ip_dec="$(dotIPv4ToDec "$source_ip")" + local source_netmask="${source_subnet##*/}" + local source_netmask_dec="$((2 ** 32 - 1 ^ (2 ** (32 - source_netmask) - 1)))" + + local target_netmask="$2" + + local first_ip_target_subnet_dec="$((source_ip_dec & source_netmask_dec))" + local total_ips_target_subnet="$((2 ** (32 - target_netmask)))" + + # Picking a random subnet would cause the same subnets to be checked multiple + # times shall the number of subnets were small, so instead a random permutation + # is scanned to check a subnet only once. + local subnets_count="$((2 ** (target_netmask - source_netmask)))" + readarray -t random_perm <<< "$(shuf -i 0-"$((subnets_count - 1))")" + # random_perm=( 3221 9 8 431 7 [...] ) + + # Due to bash performance limitations, it's not pratical to check all subnets. + # Taking into account that the install script should not hang for too long even + # on a Pi Zero, we avoid doing more than about 5000 iteration. + local max_tries="$subnets_count" + if [ $((subnets_count * excluded_subnets_count)) -ge 5000 ]; then + max_tries="$((5000 / (excluded_subnets_count / 2)))" + fi + + local first_ip_subnet_dec last_ip_subnet_dec + local first_ip_excluded_subnet_dec last_ip_excluded_subnet_dec + local overlap + for ((i = 0; i < max_tries; i++)); do + + first_ip_subnet_dec="$((first_ip_target_subnet_dec + total_ips_target_subnet * random_perm[i]))" + last_ip_subnet_dec="$((first_ip_subnet_dec + total_ips_target_subnet - 1))" + + overlap=false + + for ((j = 0; j < excluded_subnets_count; j += 2)); do + + first_ip_excluded_subnet_dec="${excluded_subnets_dec[$j]}" + last_ip_excluded_subnet_dec="${excluded_subnets_dec[$j + 1]}" + + # |-------------subnet2------------| + # |----------subnet1-----------| | + # | | | | + # first_ip_excluded_subnet_dec | last_ip_excluded_subnet_dec | + # | | + # first_ip_subnet_dec last_ip_subnet_dec + if ((last_ip_excluded_subnet_dec >= first_ip_subnet_dec)) \ + && ((first_ip_excluded_subnet_dec <= last_ip_subnet_dec)); then + overlap=true + break fi + done - if [[ "${MATCHES}" -eq 0 ]]; then + if ! "$overlap"; then + decIPv4ToDot "$first_ip_subnet_dec" break fi done - - echo "${pivpnNET}" } setOpenVPNDefaultVars() { @@ -1771,10 +1880,31 @@ setOpenVPNDefaultVars() { # Allow custom NET via unattend setupVARs file. # Use default if not provided. if [[ -z "${pivpnNET}" ]]; then - pivpnNET="$(generateRandomSubnet)" + echo "::: Generating random subnet in network 10.0.0.0/8..." + pivpnNET="$(generateRandomSubnet "10.0.0.0/8" "$subnetClass")" fi - vpnGw="$(cut -d '.' -f 1-3 <<< "${pivpnNET}").1" + if [[ -z "${pivpnNET}" ]]; then + echo "::: Network 10.0.0.0/8 is unavailable, trying 172.16.0.0/12 next..." + pivpnNET="$(generateRandomSubnet "172.16.0.0/12" "$subnetClass")" + fi + + if [[ -z "${pivpnNET}" ]]; then + echo "::: Network 172.16.0.0/12 is unavailable, trying 192.168.0.0/16 next..." + pivpnNET="$(generateRandomSubnet "192.168.0.0/16" "$subnetClass")" + fi + + if [[ -z "${pivpnNET}" ]]; then + # This should not happen in practice + echo "::: Unable to generate a random subnet for PiVPN. Looks like all private networks are in use." + exit 1 + fi + + pivpnNETdec="$(dotIPv4ToDec "${pivpnNET}")" + + vpnGwdec="$((pivpnNETdec + 1))" + vpnGw="$(decIPv4ToDot "${vpnGwdec}")" + vpnGwhex="$(decIPv4ToHex "${vpnGwdec}")" if [[ "${pivpnenableipv6}" -eq 1 ]] \ && [[ -z "${pivpnNETv6}" ]]; then @@ -1782,7 +1912,7 @@ setOpenVPNDefaultVars() { fi if [[ "${pivpnenableipv6}" -eq 1 ]]; then - vpnGwv6="${pivpnNETv6}1" + vpnGwv6="${pivpnNETv6}${vpnGwhex}" fi } @@ -1795,18 +1925,39 @@ setWireguardDefaultVars() { # Allow custom NET via unattend setupVARs file. # Use default if not provided. if [[ -z "${pivpnNET}" ]]; then - pivpnNET="$(generateRandomSubnet)" + echo "::: Generating random subnet in network 10.0.0.0/8..." + pivpnNET="$(generateRandomSubnet "10.0.0.0/8" "$subnetClass")" fi + if [[ -z "${pivpnNET}" ]]; then + echo "::: Network 10.0.0.0/8 is unavailable, trying 172.16.0.0/12 next..." + pivpnNET="$(generateRandomSubnet "172.16.0.0/12" "$subnetClass")" + fi + + if [[ -z "${pivpnNET}" ]]; then + echo "::: Network 172.16.0.0/12 is unavailable, trying 192.168.0.0/16 next..." + pivpnNET="$(generateRandomSubnet "192.168.0.0/16" "$subnetClass")" + fi + + if [[ -z "${pivpnNET}" ]]; then + # This should not happen in practice + echo "::: Unable to generate a random subnet for PiVPN. Looks like all private networks are in use." + exit 1 + fi + + pivpnNETdec="$(dotIPv4ToDec "${pivpnNET}")" + + vpnGwdec="$((pivpnNETdec + 1))" + vpnGw="$(decIPv4ToDot "${vpnGwdec}")" + vpnGwhex="$(decIPv4ToHex "${vpnGwdec}")" + if [[ "${pivpnenableipv6}" -eq 1 ]] \ && [[ -z "${pivpnNETv6}" ]]; then pivpnNETv6="fd11:5ee:bad:c0de::" fi - vpnGw="$(cut -d '.' -f 1-3 <<< "${pivpnNET}").1" - if [[ "${pivpnenableipv6}" -eq 1 ]]; then - vpnGwv6="${pivpnNETv6}1" + vpnGwv6="${pivpnNETv6}${vpnGwhex}" fi # Allow custom allowed IPs via unattend setupVARs file. @@ -2715,16 +2866,6 @@ parameters will be generated on your device." "${r}" "${c}"; then } >> "${tempsetupVarsFile}" } -cidrToMask() { - # Source: https://stackoverflow.com/a/20767392 - set -- $((5 - ($1 / 8))) \ - 255 255 255 255 \ - $(((255 << (8 - ($1 % 8))) & 255)) \ - 0 0 0 - shift "${1}" - echo "${1-0}.${2-0}.${3-0}.${4-0}" -} - confOpenVPN() { local sed_pattern file_pattern diff --git a/scripts/ipaddr_utils.sh b/scripts/ipaddr_utils.sh new file mode 100755 index 0000000..a0f2e3e --- /dev/null +++ b/scripts/ipaddr_utils.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +decIPv4ToDot() { + local a b c d + a=$((($1 & 4278190080) >> 24)) + b=$((($1 & 16711680) >> 16)) + c=$((($1 & 65280) >> 8)) + d=$(($1 & 255)) + printf "%s.%s.%s.%s\n" $a $b $c $d +} + +dotIPv4ToDec() { + local original_ifs=$IFS + IFS='.' + read -r -a array_ip <<< "$1" + IFS=$original_ifs + printf "%s\n" $((array_ip[0] * 16777216 + array_ip[1] * 65536 + array_ip[2] * 256 + array_ip[3])) +} + +dotIPv4FirstDec() { + local decimal_ip decimal_mask + decimal_ip=$(dotIPv4ToDec "$1") + decimal_mask=$((2 ** 32 - 1 ^ (2 ** (32 - $2) - 1))) + printf "%s\n" "$((decimal_ip & decimal_mask))" +} + +dotIPv4LastDec() { + local decimal_ip decimal_mask_inv + decimal_ip=$(dotIPv4ToDec "$1") + decimal_mask_inv=$((2 ** (32 - $2) - 1)) + printf "%s\n" "$((decimal_ip | decimal_mask_inv))" +} + +decIPv4ToHex() { + local hex + hex="$(printf "%08x\n" "$1")" + quartet_hi=${hex:0:4} + quartet_lo=${hex:4:4} + # Removes leading zeros from quartets, purely for aesthetic reasons + # Source: https://stackoverflow.com/a/19861690 + leading_zeros_hi="${quartet_hi%%[!0]*}" + leading_zeros_lo="${quartet_lo%%[!0]*}" + printf "%s:%s\n" "${quartet_hi#"${leading_zeros_hi}"}" "${quartet_lo#"${leading_zeros_lo}"}" +} + +cidrToMask() { + # Source: https://stackoverflow.com/a/20767392 + set -- $((5 - (${1} / 8))) \ + 255 255 255 255 \ + $(((255 << (8 - (${1} % 8))) & 255)) \ + 0 0 0 + shift "${1}" + echo "${1-0}.${2-0}.${3-0}.${4-0}" +} diff --git a/scripts/openvpn/makeOVPN.sh b/scripts/openvpn/makeOVPN.sh index f0cd765..b07b76f 100755 --- a/scripts/openvpn/makeOVPN.sh +++ b/scripts/openvpn/makeOVPN.sh @@ -14,6 +14,12 @@ INDEX="/etc/openvpn/easy-rsa/pki/index.txt" # shellcheck disable=SC1090 source "${setupVars}" +if [ ! -r /opt/pivpn/ipaddr_utils.sh ]; then + exit 1 +fi +# shellcheck disable=SC1091 +source /opt/pivpn/ipaddr_utils.sh + # shellcheck disable=SC2154 userGroup="${install_user}:${install_user}" @@ -162,16 +168,6 @@ keyPASS() { cd pki || exit } -cidrToMask() { - # Source: https://stackoverflow.com/a/20767392 - set -- $((5 - (${1} / 8))) \ - 255 255 255 255 \ - $(((255 << (8 - (${1} % 8))) & 255)) \ - 0 0 0 - shift "${1}" - echo "${1-0}.${2-0}.${3-0}.${4-0}" -} - ### Script if [[ ! -f "${setupVars}" ]]; then err "::: Missing setup vars file!" @@ -293,6 +289,35 @@ if [[ ! -d "${install_home}/ovpns" ]]; then chmod 0750 "${install_home}/ovpns" fi +# Exclude first, last and server addresses +# shellcheck disable=SC2154 +MAX_CLIENTS="$((2 ** (32 - subnetClass) - 3))" + +# shellcheck disable=SC2154 +FIRST_IPV4_DEC="$(dotIPv4FirstDec "${pivpnNET}" "${subnetClass}")" +LAST_IPV4_DEC="$(dotIPv4LastDec "${pivpnNET}" "${subnetClass}")" + +if [ "$(find /etc/openvpn/ccd -type f | wc -l)" -ge "${MAX_CLIENTS}" ]; then + echo "::: Can't add any more clients (max. ${MAX_CLIENTS})!" + exit 1 +fi + +# Find an unused address for the client IP +for ((ip = FIRST_IPV4_DEC + 2; ip <= LAST_IPV4_DEC - 1; ip++)); do + # 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 + # cycle to the end without finding and available octet. + # disabling SC2514, variable sourced externaly + ip_dot="$(decIPv4ToDot "${ip}")" + + if [[ -z "$(ls -A /etc/openvpn/ccd)" ]] \ + || ! find /etc/openvpn/ccd -type f \ + -exec grep -q "${ip_dot}" {} +; then + UNUSED_IPV4_DOT="${ip_dot}" + break + fi +done + #bitWarden if [[ "${BITWARDEN}" =~ "2" ]]; then useBitwarden @@ -469,33 +494,15 @@ if [[ "${iOS}" == 1 ]]; then printf "========================================================\n\n" fi -#disabling SC2514, variable sourced externaly -# shellcheck disable=SC2154 -NET_REDUCED="${pivpnNET::-2}" - -# Find an unused number for the last octet of the client IP -for i in {2..254}; do - # 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 - # cycle to the end without finding and available octet. - # disabling SC2514, variable sourced externaly - # shellcheck disable=SC2154 - if [[ -z "$(ls -A /etc/openvpn/ccd)" ]] \ - || ! find /etc/openvpn/ccd -type f \ - -exec grep -q "${NET_REDUCED}.${i}" {} +; then - COUNT="${i}" - echo -n "ifconfig-push ${NET_REDUCED}.${i} " >> /etc/openvpn/ccd/"${NAME}" - # The space after ${i} is important ------^! - cidrToMask "${subnetClass}" >> /etc/openvpn/ccd/"${NAME}" - # the end resuld should be a line like: - # ifconfig-push ${NET_REDUCED}.${i} ${subnetClass} - # ifconfig-push 10.205.45.8 255.255.255.0 - break - fi -done +echo -n "ifconfig-push ${UNUSED_IPV4_DOT} " >> /etc/openvpn/ccd/"${NAME}" +# The space after ${UNUSED_IPV4_DOT} is important! +cidrToMask "${subnetClass}" >> /etc/openvpn/ccd/"${NAME}" +# the end resuld should be a line like: +# ifconfig-push ${UNUSED_IPV4_DOT} ${subnetClass} +# ifconfig-push 10.205.45.8 255.255.255.0 if [[ -f /etc/pivpn/hosts.openvpn ]]; then - echo "${NET_REDUCED}.${COUNT} ${NAME}.pivpn" >> /etc/pivpn/hosts.openvpn + echo "${UNUSED_IPV4_DOT} ${NAME}.pivpn" >> /etc/pivpn/hosts.openvpn if killall -SIGHUP pihole-FTL; then echo "::: Updated hosts file for Pi-hole" diff --git a/scripts/openvpn/removeOVPN.sh b/scripts/openvpn/removeOVPN.sh index f6ce765..851b608 100755 --- a/scripts/openvpn/removeOVPN.sh +++ b/scripts/openvpn/removeOVPN.sh @@ -4,9 +4,16 @@ ### Constants setupVars="/etc/pivpn/openvpn/setupVars.conf" INDEX="/etc/openvpn/easy-rsa/pki/index.txt" + # shellcheck disable=SC1090 source "${setupVars}" +if [ ! -r /opt/pivpn/ipaddr_utils.sh ]; then + exit 1 +fi +# shellcheck disable=SC1091 +source /opt/pivpn/ipaddr_utils.sh + ### Functions err() { echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2 @@ -167,10 +174,8 @@ for ((ii = 0; ii < ${#CERTS_TO_REVOKE[@]}; ii++)); do # Disabling SC2154 $pivpnNET sourced externally # shellcheck disable=SC2154 # Grab the client IP address - 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}")" + | grep -w ifconfig-push | awk '{print $2}')" rm -rf /etc/openvpn/ccd/"${CERTS_TO_REVOKE[ii]}" # disablung warning SC2154, $install_home sourced externally diff --git a/scripts/wireguard/makeCONF.sh b/scripts/wireguard/makeCONF.sh index 67fd527..23d04ef 100755 --- a/scripts/wireguard/makeCONF.sh +++ b/scripts/wireguard/makeCONF.sh @@ -10,6 +10,12 @@ setupVars="/etc/pivpn/wireguard/setupVars.conf" # shellcheck disable=SC1090 source "${setupVars}" +if [ ! -r /opt/pivpn/ipaddr_utils.sh ]; then + exit 1 +fi +# shellcheck disable=SC1091 +source /opt/pivpn/ipaddr_utils.sh + # shellcheck disable=SC2154 userGroup="${install_user}:${install_user}" @@ -109,6 +115,27 @@ fi cd /etc/wireguard || exit +# Exclude first, last and server addresses +# shellcheck disable=SC2154 +MAX_CLIENTS="$((2 ** (32 - subnetClass) - 3))" + +if [ "$(wc -l configs/clients.txt | awk '{print $1}')" -ge "${MAX_CLIENTS}" ]; then + echo "::: Can't add any more clients (max. ${MAX_CLIENTS})!" + exit 1 +fi + +# shellcheck disable=SC2154 +FIRST_IPV4_DEC="$(dotIPv4FirstDec "${pivpnNET}" "${subnetClass}")" +LAST_IPV4_DEC="$(dotIPv4LastDec "${pivpnNET}" "${subnetClass}")" + +# Find an unused address for the client IP +for ((ip = FIRST_IPV4_DEC + 2; ip <= LAST_IPV4_DEC - 1; ip++)); do + if ! grep -q " ${ip}$" configs/clients.txt; then + UNUSED_IPV4_DEC="${ip}" + break + fi +done + if [[ -z "${CLIENT_NAME}" ]]; then read -r -p "Enter a Name for the Client: " CLIENT_NAME checkName @@ -122,28 +149,17 @@ wg genkey \ wg genpsk | tee "keys/${CLIENT_NAME}_psk" &> /dev/null echo "::: Client Keys generated" -# Find an unused number for the last octet of the client IP -for i in {2..254}; do - if ! grep -q " ${i}$" configs/clients.txt; then - COUNT="${i}" - echo "${CLIENT_NAME} $(< keys/"${CLIENT_NAME}"_pub) $(date +%s) ${COUNT}" \ - | tee -a configs/clients.txt > /dev/null - break - fi -done - -# Disabling SC2154, variables sourced externaly -# shellcheck disable=SC2154 -NET_REDUCED="${pivpnNET::-2}" +UNUSED_IPV4_DOT="$(decIPv4ToDot "${UNUSED_IPV4_DEC}")" +UNUSED_IPV4_HEX="$(decIPv4ToHex "${UNUSED_IPV4_DEC}")" # shellcheck disable=SC2154 { echo '[Interface]' echo "PrivateKey = $(cat "keys/${CLIENT_NAME}_priv")" - echo -n "Address = ${NET_REDUCED}.${COUNT}/${subnetClass}" + echo -n "Address = ${UNUSED_IPV4_DOT}/${subnetClass}" if [[ "${pivpnenableipv6}" == 1 ]]; then - echo ",${pivpnNETv6}${COUNT}/${subnetClassv6}" + echo ",${pivpnNETv6}${UNUSED_IPV4_HEX}/${subnetClassv6}" else echo fi @@ -175,10 +191,10 @@ echo "::: Client config generated" echo '[Peer]' echo "PublicKey = $(cat "keys/${CLIENT_NAME}_pub")" echo "PresharedKey = $(cat "keys/${CLIENT_NAME}_psk")" - echo -n "AllowedIPs = ${NET_REDUCED}.${COUNT}/32" + echo -n "AllowedIPs = ${UNUSED_IPV4_DOT}/32" if [[ "${pivpnenableipv6}" == 1 ]]; then - echo ",${pivpnNETv6}${COUNT}/128" + echo ",${pivpnNETv6}${UNUSED_IPV4_HEX}/128" else echo fi @@ -188,12 +204,15 @@ echo "::: Client config generated" echo "::: Updated server config" +echo "${CLIENT_NAME} $(< keys/"${CLIENT_NAME}"_pub) $(date +%s) ${UNUSED_IPV4_DEC}" \ + | tee -a configs/clients.txt > /dev/null + if [[ -f /etc/pivpn/hosts.wireguard ]]; then - echo "${NET_REDUCED}.${COUNT} ${CLIENT_NAME}.pivpn" \ + echo "${UNUSED_IPV4_DOT} ${CLIENT_NAME}.pivpn" \ | tee -a /etc/pivpn/hosts.wireguard > /dev/null if [[ "${pivpnenableipv6}" == 1 ]]; then - echo "${pivpnNETv6}${COUNT} ${CLIENT_NAME}.pivpn" \ + echo "${pivpnNETv6}${UNUSED_IPV4_HEX} ${CLIENT_NAME}.pivpn" \ | tee -a /etc/pivpn/hosts.wireguard > /dev/null fi diff --git a/scripts/wireguard/removeCONF.sh b/scripts/wireguard/removeCONF.sh index fd7e66f..0baac9b 100755 --- a/scripts/wireguard/removeCONF.sh +++ b/scripts/wireguard/removeCONF.sh @@ -6,6 +6,12 @@ setupVars="/etc/pivpn/wireguard/setupVars.conf" # shellcheck disable=SC1090 source "${setupVars}" +if [ ! -r /opt/pivpn/ipaddr_utils.sh ]; then + exit 1 +fi +# shellcheck disable=SC1091 +source /opt/pivpn/ipaddr_utils.sh + ### Functions err() { echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2 @@ -100,8 +106,8 @@ for CLIENT_NAME in "${CLIENTS_TO_REMOVE[@]}"; do 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}')" + # Grab the decimal representation of the client IP address + IPV4_DEC="$(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}')" @@ -111,7 +117,7 @@ for CLIENT_NAME in "${CLIENTS_TO_REMOVE[@]}"; do # Then remove the client matching the variables above sed \ - -e "\#${CLIENT_NAME} ${PUBLIC_KEY} ${CREATION_DATE} ${COUNT}#d" \ + -e "\#${CLIENT_NAME} ${PUBLIC_KEY} ${CREATION_DATE} ${IPV4_DEC}#d" \ -i configs/clients.txt # Remove the peer section from the server config @@ -147,10 +153,11 @@ for CLIENT_NAME in "${CLIENTS_TO_REMOVE[@]}"; do # Disabling SC2154, variable sourced externaly and may vary # shellcheck disable=SC2154 if [[ -f /etc/pivpn/hosts.wireguard ]]; then - NET_REDUCED="${pivpnNET::-2}" + IPV4_DOT="$(decIPv4ToDot "${IPV4_DEC}")" + IPV4_HEX="$(decIPv4ToHex "${IPV4_DEC}")" sed \ - -e "\#${NET_REDUCED}.${COUNT} ${CLIENT_NAME}.pivpn#d" \ - -e "\#${pivpnNETv6}${COUNT} ${CLIENT_NAME}.pivpn#d" \ + -e "\#${IPV4_DOT} ${CLIENT_NAME}.pivpn#d" \ + -e "\#${pivpnNETv6}${IPV4_HEX} ${CLIENT_NAME}.pivpn#d" \ -i /etc/pivpn/hosts.wireguard if killall -SIGHUP pihole-FTL; then