#!/usr/bin/env bash # DESCRIPTION: # creating or deleting client config for wireguard # and # sending config and info to email # # DEPENDENCIES: # - privileged rights # - wireguard # - qrencode # - grepcidr # - Python 3 # - existing /usr/local/bin/sendmail.py # # PARAMETERS: # 1: interface - define wireguard interface # 2: "add|del" - add or delete client config # 3: username - client username # 4: address - client ip address # 5: additional - client description # -f|--force - service will restart after username add|del # # FUNCTIONS: # ####################################### # Print message and add to log. # Globals: # logs # Arguments: # 1: message to print and logging ####################################### addtologs() { printf "%s\n" "$(date +'%Y.%m.%d-%H:%M:%S') $1" | tee -a "${logs}" } ####################################### # Exit procedure. # Globals: # show # Arguments: # None ####################################### execquite() { addtologs "execution time is $(($(date +%s)-time)) seconds, exit" exit "${1}" } ####################################### # Error exit procedure. # Globals: # None # Arguments: # 1: message to print and logging ####################################### execerror() { addtologs "error: $1" execquite 1 } ####################################### # Parsing config file and creating global vars. # Globals: # None # Arguments: # None ####################################### getconfig() { logs=/var/log/wireguard/$(basename -s .sh "$(realpath "$0")").log conf="$(dirname "$(realpath "$0")")/$(basename -s .sh "$(realpath "$0")").conf" # wireguard configuration serverpublkey=$(cat /etc/wireguard/pki/server-public.key) servercfgname="/etc/wireguard/${iface_name}.conf" clientpublkey='' clientprivkey='' clientconfdef="/etc/wireguard/client.conf.default" # mail configuration from="$(grep "from=" "${conf}" | cut -d= -f2)" pass="$(grep "pass=" "${conf}" | cut -d= -f2)" dest="$(grep "dest=" "${conf}" | cut -d= -f2)" smtp="$(grep "smtp=" "${conf}" | cut -d= -f2)" port="$(grep "port=" "${conf}" | cut -d= -f2)" # telegram configuration API_KEY=$(grep "API_KEY=" "${conf}" | cut -d= -f2) CHAT_ID=$(grep "CHAT_ID=" "${conf}" | cut -d= -f2) THRD_ID=$(grep "THRD_ID=" "${conf}" | cut -d= -f2) } ####################################### # Checking user rights. # Globals: # None # Arguments: # None # return: # 0 - if privileged rights, 1 - if not privileged rights ####################################### checkroot() { if [ "${EUID}" -ne 0 ]; then return 1 # false else return 0 # true fi } ####################################### # Send email notification about client config. # Globals: # clientname # faqprofile # Arguments: # None ####################################### startsendmail() { subj="[WG Settings] $(cat /etc/hostname): ${clientname} client profile" ( python3 /usr/local/bin/sendmail.py \ -u "${from}" \ -p "${pass}" \ -d "${dest}" \ --smtp "${smtp}" \ --port "${port}" \ --stls "True" \ --subj "${subj}" \ --text "$(printf "%s\n" "${faqprofile}" | sed 's|`||g')" \ --file "/etc/wireguard/${clientname}.png,/etc/wireguard/${clientname}.conf" ) > /dev/null 2>&1 addtologs "sent mail with subject '${subj}' to ${dest}" } ####################################### # Create wireguard client certificates. # Globals: # clientname # clientaddr # servercfgname # Arguments: # None ####################################### createcert() { wg genkey | tee "/etc/wireguard/pki/${clientname}-private.key" | wg pubkey > "/etc/wireguard/pki/${clientname}-public.key" clientpublkey=$(cat "/etc/wireguard/pki/${clientname}-public.key") clientprivkey=$(cat "/etc/wireguard/pki/${clientname}-private.key") wg set "${iface_name}" peer "${clientpublkey}" \ allowed-ips "${clientaddr}/32" \ persistent-keepalive 5 { printf "%s\n" "[Peer]" printf "%s\n" " PublicKey = ${clientpublkey}" printf "%s\n" " AllowedIPs = ${clientaddr}/32" printf "%s\n" " PersistentKeepalive = 5" } >> "${servercfgname}" addtologs "created ${clientname} wireguard certificate" ip -4 route add "${clientaddr}/32" dev "${iface_name}" addtologs "created route to ${clientname} peer" } ####################################### # Create wireguard client configuration. # Globals: # clientname # clientaddr # clientconfdef # clientprivkey # serverpublkey # Arguments: # None ####################################### createconf() { clientconf=$(cat "${clientconfdef}") clientconf=${clientconf//clientaddr/${clientaddr}} clientconf=${clientconf//clientprivkey/${clientprivkey}} clientconf=${clientconf//serverpublkey/${serverpublkey}} clientconf=${clientconf//clientaddrs/${clientaddr}} printf "%s\n" "${clientconf}" > "/etc/wireguard/${clientname}.conf" addtologs "created ${clientname} wireguard config file" } ####################################### # Create wireguard client info, qr-code. # Globals: # clientname # Arguments: # None ####################################### createinfo() { faqprofile=$(printf "%s\n" \ "WireGuard client:" \ "https://www.wireguard.com/install/" \ "" \ "${additional}" \ "" \ "Peer Address: \`${clientaddr}\`" \ ) qrencode -o "/etc/wireguard/${clientname}.png" -t png -s 6 < "/etc/wireguard/${clientname}.conf" addtologs "created ${clientname} qr code" } ####################################### # Delete wireguard client certificates. # Globals: # clientname # clientpublkey # servercfgname # Arguments: # None ####################################### deletecert() { clientpublkey=$(cat "/etc/wireguard/pki/${clientname}-public.key") clientprivkey=$(cat "/etc/wireguard/pki/${clientname}-private.key") wg set "${iface_name}" peer "${clientpublkey}" remove rm -f "/etc/wireguard/pki/${clientname}-public.key" rm -f "/etc/wireguard/pki/${clientname}-private.key" addtologs "deleted ${clientname} wireguard certificate" # PublicKey = s2=$(grep -n "${clientpublkey}" "${servercfgname}" | cut -d":" -f1) # [Peer] s1=$(( s2 - 1 )) # AllowedIPs = s3=$(( s2 + 1 )) # PersistentKeepalive = s4=$(( s2 + 2 )) sed -i "${s1}d;${s2}d;${s3}d;${s4}d" "${servercfgname}" ip -4 route del "${clientaddr}/32" dev "${iface_name}" addtologs "deleted route to ${clientname} peer" } ####################################### # Delete wireguard client configuration. # Globals: # clientname # Arguments: # None ####################################### deleteconf() { rm -f "/etc/wireguard/${clientname}.conf" addtologs "deleted ${clientname} wireguard config file" } ####################################### # Delete wireguard client qr-code. # Globals: # clientname # Arguments: # None ####################################### deleteinfo() { rm -f "/etc/wireguard/${clientname}.png" addtologs "deleted ${clientname} qr code" } # # VARIABLES: # iface_name=$1 clienttodo=$2 clientname=$3 clientaddr=$4 additional=$5 resetforce=0 for argument in "${@}"; do case $argument in -f | --force ) resetforce=1 ;; -* ) ;; esac done time=$(date +%s) logs=/dev/null if ! command -v qrencode &> /dev/null || \ ! command -v /usr/local/bin/sendmail.py &> /dev/null || \ ! command -v python3 &> /dev/null; then execerror "Not found dependencies" fi # # MAIN: # if checkroot; then getconfig if [ "${clienttodo}" == "add" ] && \ [ -n "${clientname}" ] && \ grepcidr "0.0.0.0/0" <(echo "${clientaddr}") >/dev/null; then if [ -f "/etc/wireguard/${clientname}.conf" ] || \ grep -q -w "${clientaddr}/32" "${servercfgname}"; then execerror "wireguard config exist or address used, exit" else createcert createconf createinfo startsendmail fi if [ "${resetforce}" -eq 1 ];then addtologs "restarting wg-quick@${iface_name}..." systemctl restart "wg-quick@${iface_name}" fi elif [ "${clienttodo}" == "del" ] && \ [ -n "${clientname}" ] && \ grepcidr "0.0.0.0/0" <(echo "${clientaddr}") >/dev/null; then if [ -f "/etc/wireguard/${clientname}.conf" ]; then deleteconf fi if [ -f "/etc/wireguard/${clientname}.png" ]; then deleteinfo fi if grep -q -w "${clientaddr}/32" "${servercfgname}"; then deletecert fi if [ "${resetforce}" -eq 1 ];then addtologs "restarting wg-quick@${iface_name}..." systemctl "restart wg-quick@${iface_name}" fi else printf "%s\n" "Usage example: $0 'wg0' 'add' 'username(surname)' 'address(ww.xx.yy.zz)'" printf "%s\n" "Usage example: $0 'wg0' 'add' 'username(surname)' 'address(ww.xx.yy.zz) 'additional client description'" printf "%s\n" "Usage example: $0 'wg0' 'del' 'username(surname)' 'address(ww.xx.yy.zz)'" printf "%s\n" "Usage example: $0 'wg0' 'del' 'username(surname)' 'address(ww.xx.yy.zz)' -f" fi else execerror "Restart this as root!" fi execquite 0