From f5a8f84155e049a6b433255b60df90c92046ef5a Mon Sep 17 00:00:00 2001 From: "Arnaud G. GIBERT" Date: Mon, 21 Jul 2025 12:32:57 +0200 Subject: [PATCH] - Major VPN management debug and fixing. --- usr/local/lib/default.bash | 65 +++-- usr/local/lib/network.bash | 2 +- usr/local/lib/vpn.bash | 475 +++++++++++++++++++++++++++++++------ usr/local/sbin/rx3_vpn_adm | 19 +- 4 files changed, 463 insertions(+), 98 deletions(-) diff --git a/usr/local/lib/default.bash b/usr/local/lib/default.bash index 30c0279..7aa4240 100644 --- a/usr/local/lib/default.bash +++ b/usr/local/lib/default.bash @@ -188,18 +188,20 @@ var_assign() file_dir_init() { - locale File="$1" - locale Owner="$2" - locale Group="$3" + local File="$1" + local Owner="$2" + local Group="$3" + + local dir - if [[ "'$id -u" != "0" ]] + if [[ "$( id -u)" != "0" ]] then - ${LOG} "Can't perform file: [${File}] init as non root user!" + ${LOG} "Can't perform file init of: [${File}] as non root user!" else if [ ! -f ${File} ] then - dir="$( dirname ${file})" + dir="$( dirname ${File})" if [ ! -d ${dir} ] then @@ -215,6 +217,7 @@ file_dir_init() >${File} chmod ug+rw ${File} chown ${Owner}:${Group} ${File} + fi fi } @@ -228,27 +231,27 @@ file_dir_init() file_lock() { - fl_file="$1" - fl_mode="$2" - fl_desc="$3" + local file="$1" + local mode="$2" + local desc="$3" - if [[ ( "${fl_mode}" == "EXCLUSIVE" ) || ( "${fl_mode}" == "WRITE" ) ]] + if [[ ( "${mode}" == "EXCLUSIVE" ) || ( "${mode}" == "WRITE" ) ]] then - fl_flag="-x" + flag="-x" else - fl_flag="-s" + flag="-s" fi - if [[ "${fl_desc}" == "" ]] + if [[ "${desc}" == "" ]] then - fl_desc="9" + desc="9" fi - eval "exec ${fl_desc}<>\"\${fl_file}\"" + eval "exec ${desc}<>\"\${file}\"" - if ! flock ${fl_flag} -w 5 ${fl_desc} + if ! flock ${flag} -w 5 ${desc} then err_echo "Failed to acquire read lock on: [${file}]" exit 1 @@ -265,15 +268,35 @@ file_lock() file_unlock() { - fu_desc="$1" + local desc="$1" - if [[ "${fu_desc}" == "" ]] + if [[ "${desc}" == "" ]] then - fu_desc="9" + desc="9" fi - eval "exec ${fl_desc}<&-" - eval "exec ${fl_desc}>&-" + eval "exec ${desc}<&-" + eval "exec ${desc}>&-" +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# log_print +#-------------------------------------------------------------------------------------------------------------------------- + +log_print() +{ + local log_file="$1" + local echo_function="$2" + + + shift; shift + + ${echo_function} "($BASHPID):" "$*" + echo >> ${VPN_LOG_FILE} $(date) "($BASHPID):" "$*" } diff --git a/usr/local/lib/network.bash b/usr/local/lib/network.bash index 9aaf239..7131f04 100644 --- a/usr/local/lib/network.bash +++ b/usr/local/lib/network.bash @@ -1072,7 +1072,7 @@ network_init() file_dir_init ${NETWORK_CONFIG_LOCK} root apache - network_table_load + network_tab_load } diff --git a/usr/local/lib/vpn.bash b/usr/local/lib/vpn.bash index 98d8d82..c72d380 100644 --- a/usr/local/lib/vpn.bash +++ b/usr/local/lib/vpn.bash @@ -1,4 +1,4 @@ -<#!/bin/bash +#!/bin/bash if [[ "${VPN_BASH}" != "" ]] then @@ -12,7 +12,7 @@ fi # Includes #----------------------------------------------------------------------------------------------------------------------------------- -. /usr/global/lib/network.bash +. /usr/local/lib/network.bash @@ -22,7 +22,15 @@ fi #----------------------------------------------------------------------------------------------------------------------------------- declare -Ag VPN_JOB_TAB -declare -g VPN_STATUS_FILE="/var/lib/rx3-vpn.status" +declare -Ag VPN_JOB_ID_LIST + +declare -g VPN_LOG_FILE="/var/log/network/rx3-vpn.log" +declare -g VPN_PID_FILE="/var/lib/network/rx3-vpn.pid" +declare -g VPN_STATUS_FILE="/var/lib/network/rx3-vpn.status" +declare -g VPN_STATUS_LOCK="/var/lock/network/rx3-vpn.status" + +declare -g VPN_TEMPLATE_FILE="/etc/openvpn/template/ext-client-tunx.conf" +declare -g VPN_CONFIG_FILE="/etc/openvpn/ext-client-DEVICE.conf" @@ -37,6 +45,296 @@ fi +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_config_make +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_config_make() +{ + local Config_File="$1" + local Device="$2" + local Target_Config="$3" + + local mng_port=$(( 2330 + ${Device/tun/})) + + ${LOG} "Creating config File: [${Config_File}] Device: [${Device}] Mng_Port: (${mng_port}) Target_Config: [${Target_Config}]" + + ${DEBUG} cp -f ${VPN_TEMPLATE_FILE} ${Config_File} + ${DEBUG} sed -e "s/TARGET-CFG/${Target_Config}-client.conf/" -e "s/VPN-DEVICE/${Device}/" -e "s/MNG-PORT/${mng_port}/" -i ${Config_File} +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_job_tab_load +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_job_tab_load() +{ + local job_id=0 + local job_pid + local job_date + local job_cmd + + + ${LOG} 1>&2 "Loading Job tab..." + + while IFS= read -r line + do + line=${line%%#*} + if [[ ! -z "$line" ]] + then + set ${line} + + job_name="$1" + job_pid="$2" + job_date="$4 $4" + shift; shift; shift; shift + job_cmd="$*" + + var_assign VPN_JOB_ID_LIST "${job_id}" INC + + tab_assign VPN_JOB_TAB "${job_id},Name" "${job_name}" + tab_assign VPN_JOB_TAB "${job_id},PId" "${job_pid}" + tab_assign VPN_JOB_TAB "${job_id},Date" "${job_date}" + tab_assign VPN_JOB_TAB "${job_id},Cmd" "${job_cmd}" + + job_id=$(( ${job_id} + 1)) + fi + done <<< ${VPN_STATUS} +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_job_tab_get +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_job_tab_get() +{ + job_id="$1" + + + job_name="${VPN_JOB_TAB["${job_id},Name"]}" + job_pid="${VPN_JOB_TAB["${job_id},PId"]}" + job_date="${VPN_JOB_TAB["${job_id},Date"]}" + job_cmd="${VPN_JOB_TAB["${job_id},Cmd"]}" +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_job_tab_save +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_job_tab_save() +{ + local job_id=0 + local dst_id + local config_file + + + file_lock ${VPN_STATUS_LOCK} WRITE 9 + + >${VPN_STATUS_FILE} + echo >>${VPN_STATUS_FILE} '#------------------------------------------------------------------------------- +# VPN Status +#------------------------------------------------------------------------------- + +VPN_STATUS=" +#------------------------------------------------------------------------------- +# Name PId Date Cmd +#-------------------------------------------------------------------------------' + + for job_id in ${VPN_JOB_ID_LIST} + do + vpn_job_tab_get "${job_id}" + + echo -e >>${VPN_STATUS_FILE} "${job_name}\t${job_pid}\t${job_date}\t${job_cmd}" + done + + echo >>${VPN_STATUS_FILE} '"' + + file_unlock 9 +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_job_tab_init +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_job_tab_init() +{ + local job_id=0 + local dst_id + local config_file + + + for dst_id in ${NETWORK_DST_ID_LIST} + do + network_dst_tab_get ${dst_id} + + if [[ "${dst_type}" == "1" ]] && [[ "${dst_config}" != "" ]] + then + config_file="${VPN_CONFIG_FILE/DEVICE/${dst_device}}" + + var_assign VPN_JOB_ID_LIST "${job_id}" INC + + tab_assign VPN_JOB_TAB "${job_id},Name" "${dst_name}" + tab_assign VPN_JOB_TAB "${job_id},PId" "0" + tab_assign VPN_JOB_TAB "${job_id},Cmd" "/usr/sbin/openvpn --config ${config_file} --dev ${dst_device} --daemon" + tab_assign VPN_JOB_TAB "${job_id},Date" "" + + vpn_config_make "${config_file}" "${dst_device}" "${dst_config}" + + log_print "${VPN_LOG_FILE}" "${LOG}" "Loading config: Id: [${job_id}] Name: [${dst_name}] Cmd: [${VPN_JOB_TAB["${job_id},Cmd"]}]" + +# ${LOG} "Loading config: Id: [${job_id}] Name: [${dst_name}] Cmd: [${VPN_JOB_TAB["${job_id},Cmd"]}]" +# echo >>${VPN_LOG_FILE} $(date) "Loading config: Id: [${job_id}] Name: [${dst_name}] Cmd: [${VPN_JOB_TAB["${job_id},Cmd"]}]" + + job_id=$(( ${job_id} + 1)) + fi + done +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_job_tab_deinit +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_job_tab_deinit() +{ + local job_id + + + for job_id in ${VPN_JOB_ID_LIST} + do + vpn_job_tab_get "${job_id}" + + if [[ "${job_PId}" -gt 0 ]] + then + log_print "${VPN_LOG_FILE}" "${LOG}" "Killing : Id: [${job_id}] Name: [${job_name}] PId: [${job_pid}]..." + +# ${LOG} $(date) "Killing : Id: [${job_id}] Name: [${job_name}] PId: [${job_pid}]..." +# echo >> ${VPN_LOG_FILE} $(date) "Killing : Id: [${job_id}] Name: [${job_name}] PId: [${job_pid}]..." + + kill -15 ${job_pid} + fi + done + + ${LOG} "Flushing status file..." + + file_lock ${VPN_STATUS_LOCK} WRITE 9 + + >${VPN_STATUS_FILE} + + file_unlock 9 +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_job_tab_dump +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_job_tab_dump() +{ + echo "VPN_JOB_ID_LIST: [${VPN_JOB_ID_LIST}]" + echo + + echo "VPN_JOB_TAB:" + + for key in "${!VPN_JOB_TAB[@]}" + do + echo "[${key}]: [${VPN_JOB_TAB[${key}]}]" + done | sort -n + + echo +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# vpn_supervisor +#-------------------------------------------------------------------------------------------------------------------------- + +vpn_supervisor() +{ + local job_id + local job_pid + + + log_print "${VPN_LOG_FILE}" "${LOG}" "Starting Supervisor..." + +# ${LOG} "Starting Superviosr, PId: [$$]..." +# echo >> ${VPN_LOG_FILE} $(date) "($$):" "Starting Supervisor..." + + + # Main Loop + + while true + do + for job_id in ${VPN_JOB_ID_LIST} + do + vpn_job_tab_get "${job_id}" + + ${DEBUG} kill -0 "${job_pid}" 2>/dev/null + rc=$? + + if [[ ${job_pid} == 0 ]] || [[ $rc != 0 ]] + then + log_print "${VPN_LOG_FILE}" "${LOG}" "Restarting Cmd: [${job_cmd}]..." + +# ${LOG} "Restarting Cmd: [${job_cmd}]..." +# echo >> ${VPN_LOG_FILE} $(date) "($$):" "Restarting Cmd: [${job_cmd}]..." + + eval ${DEBUG} ${job_cmd} + + job_pid="$( ps aux | grep "${job_cmd}" | grep -v grep | head -1 | awk '{print $2}')" + + if [[ "${job_pid}" == "" ]] + then + job_pid=0 + fi + + tab_assign VPN_JOB_TAB "${job_id},PId" "${job_pid}" + tab_assign VPN_JOB_TAB "${job_id},Date" "$(date --rfc-3339=seconds -u)" + + log_print "${VPN_LOG_FILE}" "${LOG}" "PId: [${VPN_JOB_TAB["${job_id},PId"]}]!" + +# ${LOG} "PId: [${VPN_JOB_TAB["${job_id},PId"]}]!" +# echo >> ${VPN_LOG_FILE} $(date) "($$):" "PId: [${VPN_JOB_TAB["${job_id},PId"]}]!" + fi + done + + vpn_job_tab_save + + sleep 30 + + network_dst_address_refresh_all + done +} + + + + + #-------------------------------------------------------------------------------------------------------------------------- # vpn_init #-------------------------------------------------------------------------------------------------------------------------- @@ -45,7 +343,26 @@ vpn_init() { network_init - file_dir_init ${VPN_STATUS_FILE} root apache + file_dir_init ${VPN_STATUS_LOCK} root apache + + file_lock ${VPN_STATUS_LOCK} READ 9 + file_dir_init ${VPN_STATUS_FILE} root apache + file_unlock 9 + + file_dir_init ${VPN_LOG_FILE} root apache + + if [[ -s "${VPN_STATUS_FILE}" ]] + then + file_lock ${VPN_STATUS_LOCK} READ 9 + + . "${VPN_STATUS_FILE}" + + file_unlock 9 + + vpn_job_tab_load + else + vpn_job_tab_init + fi } @@ -71,75 +388,36 @@ vpn_deinit() vpn_start() { - local job_id=0 - local job_nb - local dst_id - local config_file - local mng_port + local daemon_pid - for dst_id in ${NETWORK_DST_ID_LIST} - do - network_dst_tab_get ${dst_id} - - if [[ "${dst_type}" == "1" ]] - then - config_file="${VPN_CONFIG_FILE/DEVICE/${dst_device}}" - mng_port=$((2330+$(echo ${dev} | sed -e "s/tun//"))) - - tab_assign VPN_JOB_TAB "${dst_id},PId" "0" - tab_assign VPN_JOB_TAB "${dst_id},Cmd" "/usr/sbin/openvpn --config ${config_file} --dev ${dst_device} --daemon" - - ${DEBUG} \rm -f ${config_file} 2>/dev/null - ${DEBUG} sed -e "s/TARGET-CFG/${dst_config}-client.conf/" -e "s/VPN-DEVICE/${dst_device}/" -e "s/MNG-PORT/${mng_port}/" <${template_file} >${config_file} - - echo >>${LOG_FILE} $(date) "Loading config: VPN[${dst_id}] Name: [${dst_name}] Cmd: [${VPN_JOB_TAB["${job_id},Cmd"]}]" - job_id=$(( ${job_id} + 1)) - fi - done + if [[ -s ${VPN_PID_FILE} ]] + then + daemon_pid=$( cat ${VPN_PID_FILE}) + else + daemon_pid=0 + fi - job_nb=${job_id} + ${DEBUG} kill -0 "${daemon_pid}" 2>/dev/null + rc=$? - - # Main Loop - - while true - do - while [[ "${job_id}" -lt "${job_nb}" ]] - do - ${DEBUG} kill -0 ${VPN_JOB_TAB["${job_id},PId"]} 2>/dev/null - rc=$? + if [[ "${daemon_pid}" == "0" ]] || [[ $rc != 0 ]] + then + vpn_supervisor & + daemon_pid=$! - if [[ ${VPN_JOB_TAB["${job_id},PId]"]} == 0 ]] || [[ $rc != 0 ]] - then - echo >> ${LOG_FILE} $(date) "Restarting Cmd: [${VPN_JOB_TAB["${job_id}",Cmd]}]..." + log_print "${VPN_LOG_FILE}" "${LOG}" "Daemon started, PId: [${daemon_pid}]" - eval ${DEBUG} ${VPN_JOB_TAB["${job_id},Cmd"]} - - VPN_JOB_TAB["${job_id},PId"]="$( ps aux | grep "${VPN_JOB_TAB["Cmd,${job_id}"]}" | grep -v grep | head -1 | awk '{print $2}')" - VPN_JOB_TAB["${job_id},Date"]="$(date)" - - echo >> ${LOG_FILE} $(date) "PId: [${VPN_JOB_TAB["${job_id},PId"]}]!" - fi - - job_id=$(( ${job_id} + 1)) - done - - job_id=0 - >${VPN_STATUS_FILE} - - while [[ ${job_id} -lt ${job_nb} ]] - do - echo >>${VPN_STATUS_FILE} "PId: [${VPN_JOB_TAB["${job_id},PId"]}] Date: [${VPN_JOB_TAB["${job_id},Date"]}] Cmd: [${VPN_JOB_TAB["${job_id},Date"]}]" - job_id=$(( ${job_id} + 1)) - done - - job_id=0 - - sleep 30 - - network_dst_address_refresh_all - done +# ${LOG} "($$):" "Daemon started, PId: [${daemon_pid}]" +# echo >> ${VPN_LOG_FILE} $(date) "($$):" "Daemon started, PId: [${daemon_pid}]" + + echo >${VPN_PID_FILE} "${daemon_pid}" + else + log_print "${VPN_LOG_FILE}" "${LOG}" "Daemon already running PId: [${daemon_pid}]" + +# echo 1>&2 "($$):" "Daemon already running PId: [${daemon_pid}]" +# echo >> ${VPN_LOG_FILE} $(date) "($$):" "Daemon already running PId: [${daemon_pid}]" + fi } @@ -152,15 +430,37 @@ vpn_start() vpn_stop() { - echo >> ${LOG_FILE} $(date) "Killing daemon: [$(cat ${PID_FILE})]..." - - kill -15 $(cat ${PID_FILE}) + local daemon_pid - while read stat - do - echo >> ${LOG_FILE} $(date) "Killing VPN: [$stat] [$(echo "$stat" | sed -e 's/PId: \[//' -e 's/\].*//')]..." - ${DEBUG} kill -15 $(echo "$stat" | sed -e 's/PId: \[//' -e 's/\].*//') - done <${VPN_STATUS_FILE} + + if [[ -s ${VPN_PID_FILE} ]] + then + daemon_pid=$( cat ${VPN_PID_FILE}) + else + daemon_pid=0 + fi + + ${DEBUG} kill -0 "${daemon_pid}" 2>/dev/null + rc=$? + + if [[ "${daemon_pid}" == "0" ]] || [[ $rc != 0 ]] + then + log_print "${VPN_LOG_FILE}" "${LOG}" "Daemon already stoped!" + +# ${LOG} "($$):" "Daemon already stoped!" +# echo >> ${VPN_LOG_FILE} $(date) "($$):" "Daemon already stoped!" + else + log_print "${VPN_LOG_FILE}" "${LOG}" "Stoping daemon, PId: [${daemon_pid}]..." + +# ${LOG} "($$):" "Stoping daemon, PId: [${daemon_pid}]..." +# echo >> ${VPN_LOG_FILE} $(date) "($$):" "Stoping daemon, PId: [${daemon_pid}]..." + + kill -15 ${daemon_pid} + fi + + >${VPN_PID_FILE} + + vpn_job_tab_deinit } @@ -173,8 +473,33 @@ vpn_stop() vpn_status() { + local daemon_pid + local job_id + + + if [[ -s ${VPN_PID_FILE} ]] + then + daemon_pid=$( cat ${VPN_PID_FILE}) + echo "Daemon PId: (${daemon_pid})" + else + daemon_pid="" + echo "Daemon not running" + fi + + echo "Number of VPN Jobs: (${#VPN_JOB_IDX[@]})" + if [ -f ${VPN_STATUS_FILE} ] then cat ${VPN_STATUS_FILE} fi + + echo -e "Id\tName\t\tPId\tDate\t\t\t\tCommand" + echo "-----------------------------------------------------------------------" + + for job_id in ${VPN_JOB_ID_LIST} + do + vpn_job_tab_get "${job_id}" + + echo -e "${job_id}\t${job_name}\t${job_pid}\t${job_date}\t${job_cmd}" + done } diff --git a/usr/local/sbin/rx3_vpn_adm b/usr/local/sbin/rx3_vpn_adm index 55bc74b..424134b 100755 --- a/usr/local/sbin/rx3_vpn_adm +++ b/usr/local/sbin/rx3_vpn_adm @@ -84,6 +84,19 @@ status() +#-------------------------------------------------------------------------------------------------------------------------- +# Dump +#-------------------------------------------------------------------------------------------------------------------------- + +dump() +{ + vpn_job_tab_dump +} + + + + + #-------------------------------------------------------------------------------------------------------------------------- # Main #-------------------------------------------------------------------------------------------------------------------------- @@ -109,8 +122,12 @@ case "$1" in status ;; + dump) + dump + ;; + *) - echo "Usage: $0 {start|stop|restart|status}" + echo "Usage: $0 {start|stop|restart|status|dump}" RETVAL=1 ;; esac