From 1923aa17e6b27d94876411ea73ebb65647324547 Mon Sep 17 00:00:00 2001 From: randomshell Date: Mon, 3 Aug 2020 14:24:43 +0000 Subject: [PATCH] Add clientRevoke() and improve addClient() (#94) Added `clientRevoke()` based on openvpn-install repo, fixes #4 Some other changes were required for this to work: - client names aren't random anymore - client names are saved above the `[Peer]` block of the server configuration file to keep track of them - checks added for existing IPv4, IPv6 and client name. I used `until` to ask the user again if this is the case to not make him loose its work if, for example, the client name and IPv4 inserted are unique but not the IPv6. - using `until` instead of `exit` isn't idempotent but it's more user friendly. This will be a future goal. - default options should be safe to use so the suggestion for the client IP is automatically incremented. The subnet of `SERVER_WG_IPV` is hard-coded inside `CLIENT_WG_IPV` for obvious reasons --- wireguard-install.sh | 141 +++++++++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 37 deletions(-) diff --git a/wireguard-install.sh b/wireguard-install.sh index 55f24df..1eb4263 100644 --- a/wireguard-install.sh +++ b/wireguard-install.sh @@ -33,9 +33,9 @@ function checkOS() { source /etc/os-release OS="${ID}" # debian or ubuntu if [[ -e /etc/debian_version ]]; then - if [[ $ID == "debian" || $ID == "raspbian" ]]; then - if [[ $VERSION_ID -ne 10 ]]; then - echo "Your version of Debian ($VERSION_ID) is not supported. Please use Debian 10 Buster" + if [[ ${ID} == "debian" || ${ID} == "raspbian" ]]; then + if [[ ${VERSION_ID} -ne 10 ]]; then + echo "Your version of Debian (${VERSION_ID}) is not supported. Please use Debian 10 Buster" exit 1 fi fi @@ -215,25 +215,59 @@ net.ipv6.conf.all.forwarding = 1" >/etc/sysctl.d/wg.conf } function newClient() { - # Load params - # shellcheck disable=SC1091 - source /etc/wireguard/params - ENDPOINT="${SERVER_PUB_IP}:${SERVER_PORT}" - printf "\n" - until [[ ${CLIENT_WG_IPV4} =~ ^([0-9]{1,3}\.?){4}$ ]]; do - read -rp "Client's WireGuard IPv4: " -e -i "${SERVER_WG_IPV4::-1}"2 CLIENT_WG_IPV4 + echo "" + echo "Tell me a name for the client." + echo "Use one word only, no special characters." + + until [[ "${CLIENT_NAME}" =~ ^[a-zA-Z0-9_]+$ && "${CLIENT_EXISTS}" == '0' ]]; do + read -rp "Client name: " -e CLIENT_NAME + CLIENT_EXISTS=$(grep -c -E "^### Client ${CLIENT_NAME}\$" "/etc/wireguard/${SERVER_WG_NIC}.conf") + + if [[ ${CLIENT_EXISTS} == '1' ]]; then + echo "" + echo "A client with the specified name was already created, please choose another name." + echo "" + fi done - until [[ ${CLIENT_WG_IPV6} =~ ^([a-f0-9]{1,4}:?:?){3,5} ]]; do - read -rp "Client's WireGuard IPv6 : " -e -i "${SERVER_WG_IPV6::-1}"2 CLIENT_WG_IPV6 + for DOT_IP in {2..254}; do + DOT_EXISTS=$(grep -c "${SERVER_WG_IPV4::-1}${DOT_IP}" "/etc/wireguard/${SERVER_WG_NIC}.conf") + if [[ ${DOT_EXISTS} == '0' ]]; then + break + fi done - CLIENT_NAME=$( - head /dev/urandom | tr -dc A-Za-z0-9 | head -c 10 - echo '' - ) + if [[ ${DOT_EXISTS} == '1' ]]; then + echo "" + echo "The subnet configured supports only 253 clients." + exit 1 + fi + + until [[ "${IPV4_EXISTS}" == '0' ]]; do + read -rp "Client's WireGuard IPv4: ${SERVER_WG_IPV4::-1}" -e -i "${DOT_IP}" DOT_IP + CLIENT_WG_IPV4="${SERVER_WG_IPV4::-1}${DOT_IP}" + IPV4_EXISTS=$(grep -c "$CLIENT_WG_IPV4" "/etc/wireguard/${SERVER_WG_NIC}.conf") + + if [[ ${IPV4_EXISTS} == '1' ]]; then + echo "" + echo "A client with the specified IPv4 was already created, please choose another IPv4." + echo "" + fi + done + + until [[ "${IPV6_EXISTS}" == '0' ]]; do + read -rp "Client's WireGuard IPv6: ${SERVER_WG_IPV6::-1}" -e -i "${DOT_IP}" DOT_IP + CLIENT_WG_IPV6="${SERVER_WG_IPV6::-1}${DOT_IP}" + IPV6_EXISTS=$(grep -c "${CLIENT_WG_IPV6}" "/etc/wireguard/${SERVER_WG_NIC}.conf") + + if [[ ${IPV6_EXISTS} == '1' ]]; then + echo "" + echo "A client with the specified IPv6 was already created, please choose another IPv6." + echo "" + fi + done # Generate key pair for the client CLIENT_PRIV_KEY=$(wg genkey) @@ -262,7 +296,8 @@ Endpoint = ${ENDPOINT} AllowedIPs = 0.0.0.0/0,::/0" >>"${HOME_DIR}/${SERVER_WG_NIC}-client-${CLIENT_NAME}.conf" # Add the client as a peer to the server - echo -e "\n[Peer] + echo -e "\n### Client ${CLIENT_NAME} +[Peer] PublicKey = ${CLIENT_PUB_KEY} PresharedKey = ${CLIENT_PRE_SHARED_KEY} AllowedIPs = ${CLIENT_WG_IPV4}/32,${CLIENT_WG_IPV6}/128" >>"/etc/wireguard/${SERVER_WG_NIC}.conf" @@ -276,35 +311,61 @@ AllowedIPs = ${CLIENT_WG_IPV4}/32,${CLIENT_WG_IPV6}/128" >>"/etc/wireguard/${SER echo "It is also available in ${HOME_DIR}/${SERVER_WG_NIC}-client-${CLIENT_NAME}.conf" } -function uninstallWg() { - if [[ ! -e /etc/wireguard/params ]]; then - echo "WireGuard is not installed." +function revokeClient() { + NUMBER_OF_CLIENTS=$(grep -c -E "^### Client" "/etc/wireguard/${SERVER_WG_NIC}.conf") + if [[ ${NUMBER_OF_CLIENTS} == '0' ]]; then + echo "" + echo "You have no existing clients!" exit 1 fi + echo "" + echo "Select the existing client you want to revoke" + grep -E "^### Client" "/etc/wireguard/${SERVER_WG_NIC}.conf" | cut -d ' ' -f 3 | nl -s ') ' + until [[ ${CLIENT_NUMBER} -ge 1 && ${CLIENT_NUMBER} -le ${NUMBER_OF_CLIENTS} ]]; do + if [[ ${CLIENT_NUMBER} == '1' ]]; then + read -rp "Select one client [1]: " CLIENT_NUMBER + else + read -rp "Select one client [1-${NUMBER_OF_CLIENTS}]: " CLIENT_NUMBER + fi + done + + # match the selected number to a client name + CLIENT_NAME=$(grep -E "^### Client" "/etc/wireguard/${SERVER_WG_NIC}.conf" | cut -d ' ' -f 3 | sed -n "${CLIENT_NUMBER}"p) + + # remove [Peer] block matching $CLIENT_NAME + sed -i "/^### Client ${CLIENT_NAME}\$/,/^$/d" "/etc/wireguard/${SERVER_WG_NIC}.conf" + + # remove generated client file + rm -f "${HOME}/${SERVER_WG_NIC}-client-${CLIENT_NAME}.conf" + + # restart wireguard to apply changes + systemctl restart "wg-quick@${SERVER_WG_NIC}" +} + +function uninstallWg() { checkOS - source /etc/wireguard/params - systemctl stop "wg-quick@$SERVER_WG_NIC" - systemctl disable "wg-quick@$SERVER_WG_NIC" + systemctl stop "wg-quick@${SERVER_WG_NIC}" + systemctl disable "wg-quick@${SERVER_WG_NIC}" - if [[ $OS == 'ubuntu' ]]; then + if [[ ${OS} == 'ubuntu' ]]; then apt-get autoremove --purge -y wireguard qrencode add-apt-repository -y -r ppa:wireguard/wireguard - elif [[ $OS == 'debian' ]]; then + elif [[ ${OS} == 'debian' ]]; then apt-get autoremove --purge -y wireguard qrencode - elif [[ $OS == 'fedora' ]]; then + elif [[ ${OS} == 'fedora' ]]; then dnf remove -y wireguard-tools qrencode - if [[ $VERSION_ID -lt 32 ]]; then + if [[ ${VERSION_ID} -lt 32 ]]; then dnf remove -y wireguard-dkms dnf copr disable -y jdoss/wireguard fi dnf autoremove -y - elif [[ $OS == 'centos' ]]; then + elif [[ ${OS} == 'centos' ]]; then yum -y remove wireguard-dkms wireguard-tools qrencode rm -f "/etc/yum.repos.d/wireguard.repo" yum -y autoremove - elif [[ $OS == 'arch' ]]; then + elif [[ ${OS} == 'arch' ]]; then pacman -Rs --noconfirm wireguard-tools qrencode fi @@ -315,10 +376,10 @@ function uninstallWg() { sysctl --system # Check if WireGuard is running - systemctl is-active --quiet "wg-quick@$SERVER_WG_NIC" + systemctl is-active --quiet "wg-quick@${SERVER_WG_NIC}" WG_RUNNING=$? - if [[ $WG_RUNNING -eq 0 ]]; then + if [[ ${WG_RUNNING} -eq 0 ]]; then echo "WireGuard failed to uninstall properly." exit 1 else @@ -335,19 +396,23 @@ function manageMenu() { echo "" echo "What do you want to do?" echo " 1) Add a new user" - echo " 2) Uninstall WireGuard" - echo " 3) Exit" - until [[ ${MENU_OPTION} =~ ^[1-3]$ ]]; do - read -rp "Select an option [1-3]: " MENU_OPTION + echo " 2) Revoke existing user" + echo " 3) Uninstall WireGuard" + echo " 4) Exit" + until [[ ${MENU_OPTION} =~ ^[1-4]$ ]]; do + read -rp "Select an option [1-4]: " MENU_OPTION done case "${MENU_OPTION}" in 1) newClient ;; 2) - uninstallWg + revokeClient ;; 3) + uninstallWg + ;; + 4) exit 0 ;; esac @@ -356,8 +421,10 @@ function manageMenu() { # Check for root, virt, OS... initialCheck -# Check if WireGuard is already installed +# Check if WireGuard is already installed and load params if [[ -e /etc/wireguard/params ]]; then + # shellcheck disable=SC1091 + source /etc/wireguard/params manageMenu else installWireGuard