From b1c51d6cfdbc1d46b835013e4ba71ace2c5366ca Mon Sep 17 00:00:00 2001 From: "Arnaud G. GIBERT" Date: Mon, 1 Sep 2025 01:09:29 +0200 Subject: [PATCH] - Improve device up api events, - Improve openvpn stats reporting, - Add a new conection state for gateways device up with no gateway client conected. --- usr/local/lib/network.bash | 332 +++++++++++++++++++++++----- usr/local/sbin/openvpn-down | 19 +- usr/local/sbin/openvpn-up | 15 +- var/www/cgi-bin/vpn-admin_board.cgi | 25 ++- 4 files changed, 305 insertions(+), 86 deletions(-) diff --git a/usr/local/lib/network.bash b/usr/local/lib/network.bash index 637ee2f..b4cb3ab 100644 --- a/usr/local/lib/network.bash +++ b/usr/local/lib/network.bash @@ -168,6 +168,72 @@ network_common_dump() +#-------------------------------------------------------------------------------------------------------------------------- +# network_common_openvpn_stats_get +#-------------------------------------------------------------------------------------------------------------------------- + +network_common_openvpn_stats_get() +{ + local device="$1" + local client="$2" + + + if [[ "${client}" == "" ]] + then + client=".*" + else + if [[ "${device}" == "" ]] + then + tmp="$( echo "${NETWORK_OPENVPN_STATUS}" | grep "CLIENT_LIST,${client},")" + tmp="${tmp/*\//}" + device="${tmp/.status*/}" + fi + fi + + if [[ "${device}" != "" ]] + then + if [[ "${NETWORK_OPENVPN_STATUS}" =~ ("${device}.status: TITLE") ]] + then + # OpenVPN Server Mode + + OIFS="${IFS}" + IFS="," + set XXX/$( echo "${NETWORK_OPENVPN_STATUS}" | grep "${device}\.status: CLIENT_LIST,${client},") &>/dev/null + IFS="${OIFS}" + + tmp="${1/XXX*\//}" + ovpn_stat_device="${tmp/.status*/}" + ovpn_stat_client_name="$2" + ovpn_stat_address_ext="$3" + ovpn_stat_address_int="$4" + ovpn_stat_address_int6="$5" + ovpn_stat_bytes_received="$6" + ovpn_stat_bytes_sent="$7" + ovpn_stat_connected_date="$8" + ovpn_stat_connected_time_t="$9" + ovpn_stat_user_name="$10" + ovpn_stat_client_id="$11" + ovpn_stat_peer_id="$12" + ovpn_stat_cipher="$13" + else + # OpenVPN Client Mode + + set XXX/$( echo "${NETWORK_OPENVPN_STATUS}" | grep "${device}\.status:") &>/dev/null + + tmp="${1/XXX*\//}" + ovpn_stat_device="${tmp/.status*/}" + ovpn_stat_bytes_received="${18/bytes,}" + ovpn_stat_bytes_sent="${22/bytes,}" + fi + else + ovpn_stat_device="" + fi + } + + + + + #-------------------------------------------------------------------------------------------------------------------------- # network_ip_route_tab_load #-------------------------------------------------------------------------------------------------------------------------- @@ -232,6 +298,7 @@ network_ip_route_tab_dump() { echo "NETWORK_IP_ROUTE_ID_LIST: [${NETWORK_IP_ROUTE_ID_LIST}]" echo + echo "NETWORK_IP_ROUTE_IP_IDX:" @@ -242,6 +309,7 @@ network_ip_route_tab_dump() echo + echo "NETWORK_IP_ROUTE_TAB:" for key in "${!NETWORK_IP_ROUTE_TAB[@]}" @@ -293,8 +361,6 @@ network_dst_tab_load() ndtl_status="$( ip link show dev ${ndtl_device} 2>/dev/null | grep -q ",UP," && echo "1" || echo "0")" - - tab_assign NETWORK_DST_TAB "${ndtl_id},Status" "${ndtl_status}" if [[ "${ndtl_type}" == "5" ]] @@ -303,8 +369,8 @@ network_dst_tab_load() dns_value="" else ndtl_host_name="vpn${vpn_id}.${NETWORK_DST_NAME}" - dns_lookup "A" "${ndtl_host_name}" "NOCACHE" - vpn_id=$((${vpn_id} + 1)) + dns_lookup "A" "${ndtl_host_name}" "NOCACHE" + vpn_id=$((${vpn_id} + 1)) fi tab_assign NETWORK_DST_TAB "${ndtl_id},Host_Name" "${ndtl_host_name}" @@ -312,24 +378,35 @@ network_dst_tab_load() case "${ndtl_type}" in - "0"|"1") + "0") ndtl_bytes_received="$( cat /sys/class/net/${ndtl_device}/statistics/rx_bytes 2>/dev/null | numfmt --to=iec-i --suffix=B)" ndtl_bytes_sent="$( cat /sys/class/net/${ndtl_device}/statistics/tx_bytes 2>/dev/null | numfmt --to=iec-i --suffix=B)" - ;; + ;; - "2") - set $( echo "${NETWORK_OPENVPN_STATUS}" | grep ${ndtl_device}'\.') &>/dev/null - -# i=1; while [[ $i -lt 50 ]]; do eval "val=\${$i}"; echo "($i):[${val}]" 1>&2; i=$(( $i + 1)); done - - ndtl_bytes_received="$( echo ${18/bytes,} | numfmt --to=iec-i --suffix=B)" - ndtl_bytes_sent="$( echo ${22/bytes,} | numfmt --to=iec-i --suffix=B)" - ;; + "1"|"2") + network_common_openvpn_stats_get "${ndtl_device}" "" + + if [[ ( "${ndtl_type}" == "1") && ( "${ndtl_status}" == "1") && ( "${ovpn_stat_client_name}" == "") ]] + then + ndtl_status="2" + + ndtl_bytes_received="" + ndtl_bytes_sent="" + else + ndtl_bytes_received="$( echo ${ovpn_stat_bytes_received} | numfmt --to=iec-i --suffix=B)" + ndtl_bytes_sent="$( echo ${ovpn_stat_bytes_sent} | numfmt --to=iec-i --suffix=B)" + fi + ;; esac + + + tab_assign NETWORK_DST_TAB "${ndtl_id},Status" "${ndtl_status}" + + if [[ "${ndtl_status}" == "1" ]] then - + ndtl_start_date="$( stat -c %Z /sys/class/net/${ndtl_device})" ndtl_uptime="$( echo $(( $(date +%s) - ${ndtl_start_date})) | awk '{days = int($1/86400); print days " day" (( days > 1 ) ? "s" : "") strftime(" %H:%M:%S", $1,1)}')" else @@ -388,8 +465,19 @@ network_dst_tab_get() network_dst_tab_dump() { + echo "NETWORK_DST_TYPE:" + + for key in "${!NETWORK_DST_TYPE[@]}" + do + echo "[${key}]: [${NETWORK_DST_TYPE[${key}]}]" + done | sort -n + + echo + + echo "NETWORK_DST_ID_LIST: [${NETWORK_DST_ID_LIST}]" echo + echo "NETWORK_DST_NAME_IDX:" @@ -400,6 +488,7 @@ network_dst_tab_dump() echo + echo "NETWORK_DST_DEV_IDX:" for key in "${!NETWORK_DST_DEV_IDX[@]}" @@ -409,6 +498,7 @@ network_dst_tab_dump() echo + echo "NETWORK_DST_TAB:" for key in "${!NETWORK_DST_TAB[@]}" @@ -548,53 +638,55 @@ network_src_tab_load() # [[ $nstl_host_name =~ ([0-9]+) ]] # nstl_device="${NETWORK_SRC_LOCAL_DEVICE}-${BASH_REMATCH[1]}" - ip_num=$(ip_to_num ${nstl_ip}) - device_num="$(( ( ${ip_num} - ${ip_base}) / 4))" + ip_num=$(ip_to_num ${nstl_ip}) + device_num="$(( ( ${ip_num} - ${ip_base}) / 4))" nstl_device="${NETWORK_SRC_LOCAL_DEVICE}-${device_num}" - ;;& + nstl_status="$( ip link show dev ${nstl_device} 2>/dev/null | grep -q ",UP," && echo "1" || echo "0")" + + if [[ "${nstl_status}" == 1 ]] + then + nstl_bytes_received="$( cat /sys/class/net/${nstl_device}/statistics/rx_bytes 2>/dev/null | numfmt --to=iec-i --suffix=B)" + nstl_bytes_sent="$( cat /sys/class/net/${nstl_device}/statistics/tx_bytes 2>/dev/null | numfmt --to=iec-i --suffix=B)" + nstl_start_date="$( stat -c %Z /sys/class/net/${nstl_device})" + nstl_uptime="$( echo $(( $(date +%s) - ${nstl_start_date})) | awk '{days = int($1/86400); print days " day" (( days > 1 ) ? "s" : "") strftime(" %H:%M:%S", $1,1)}')" + else + nstl_bytes_received="" + nstl_bytes_sent="" + nstl_uptime="" + nstl_last_seen="" + fi + ;; "1") # Routed - nstl_device="" - ;;& - - "0"|"1") # Local + Routed + nstl_device="" nstl_status="2" nstl_bytes_received="" nstl_bytes_sent="" nstl_uptime="" nstl_last_seen="" - ;; + ;; "2") # OpenVPN -# nstl_device="tun0" -# nstl_status_line="$( echo "${NETWORK_OPENVPN_STATUS}" | grep "${nstl_device}.status: CLIENT_LIST.*${nstl_ip},")" + network_common_openvpn_stats_get "" "${nstl_host_name}" - nstl_status_line="$( echo "${NETWORK_OPENVPN_STATUS}" | grep "CLIENT_LIST,.*${nstl_ip},")" - - if [[ "${nstl_status_line}" == "" ]] + if [[ "${ovpn_stat_device}" == "" ]] then - nstl_device="" - nstl_status="0" + nstl_device="" + nstl_status="0" nstl_bytes_received="" nstl_bytes_sent="" nstl_start_date="" nstl_uptime="" nstl_last_seen="$( stat -c "%x" /etc/openvpn/status/${nstl_host_name}.status 2>/dev/null | sed -e 's/\..*//')" - else - nstl_status="1" - - IFS=, - set ${nstl_status_line} &>/dev/null - unset IFS - - nstl_device="$( echo $1 | sed -e "s%.*/%%" -e 's/.status.*//')" - nstl_bytes_received=$( echo ${6} | numfmt --to=iec-i --suffix=B) - nstl_bytes_sent=$( echo ${7} | numfmt --to=iec-i --suffix=B) - nstl_start_date=${8} - nstl_uptime=$( echo "$(($(date +%s) - $(date -d "${nstl_start_date}" +%s)))" | awk '{days = int($1/86400); print days " day" (( days > 1 ) ? "s" : "") strftime(" %H:%M:%S", $1,1)}') + nstl_device="${ovpn_stat_device}" + nstl_status="1" + nstl_bytes_received=$( echo ${ovpn_stat_bytes_sent} | numfmt --to=iec-i --suffix=B) + nstl_bytes_sent=$( echo ${ovpn_stat_bytes_sent} | numfmt --to=iec-i --suffix=B) + nstl_start_date=${ovpn_stat_connected_date} + nstl_uptime=$( echo "$(($(date +%s) - $(date -d "${nstl_start_date}" +%s)))" | awk '{days = int($1/86400); print days " day" (( days > 1 ) ? "s" : "") strftime(" %H:%M:%S", $1,1)}') nstl_last_seen="$(stat -c "%x" /etc/openvpn/status/${nstl_host_name}.status 2>/dev/null | sed -e 's/\..*//')" fi ;; @@ -680,6 +772,16 @@ network_src_tab_get() network_src_tab_dump() { + echo "NETWORK_SRC_TYPE:" + + for key in "${!NETWORK_SRC_TYPE[@]}" + do + echo "[${key}]: [${NETWORK_SRC_TYPE[${key}]}]" + done | sort -n + + echo + + echo "NETWORK_SRC_ID_LIST: [${NETWORK_SRC_ID_LIST}]" echo @@ -772,7 +874,7 @@ network_route_dst_init() local dst_id="$1" - network_dst_tab_get ${dst_id} + network_dst_tab_get "${dst_id}" if [[ ${dst_type} == "0" ]] then @@ -792,8 +894,22 @@ network_route_dst_init() fi - target_device=${dst_device} - +# network_route_rx3_init ${dst_device} +} + + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# network_route_rx3_init +#-------------------------------------------------------------------------------------------------------------------------- + +network_route_rx3_init() +{ + local target_device="$1" + + log_trace "Network" "Add [${target_device}] Rx3 routes in VPN tables" for dst_id in ${NETWORK_DST_ID_LIST} @@ -806,7 +922,7 @@ network_route_dst_init() if [[ "${ip_route_device}" == "${target_device}" ]] then - ${DEBUG} ip route add ${ip_route_ip}/${ip_route_mask} table ${dst_table} dev ${ip_route_device} + ${DEBUG} ip route add ${ip_route_ip}/${ip_route_mask} dev ${ip_route_device} table ${dst_table} fi done done @@ -845,6 +961,111 @@ network_route_other_init() +#-------------------------------------------------------------------------------------------------------------------------- +# network_device_init +#-------------------------------------------------------------------------------------------------------------------------- + +network_device_init() +{ + local dst_id="$1" + local device_name="$2" + + + log_trace "Network" "Init dst_id: [${dst_id}] device_name: [${device_name}]" + + if [[ "${dst_id}" == "" ]] + then + network_dst_tab_dev_lookup "${device_name}" + fi + + if [[ "${dst_id}" != "" ]] + then + network_route_dst_init "${dst_id}" + + device_name="${dst_device}" + fi + + network_route_rx3_init "${device_name}" +} + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# network_device_deinit +#-------------------------------------------------------------------------------------------------------------------------- + +network_device_deinit() +{ + local dst_id="$1" + local device_name="$2" + + + log_trace "Network" "DeInit dst_id: [${dst_id}] device_name: [${device_name}]" + + if [[ "${dst_id}" == "" ]] + then + network_dst_tab_dev_lookup "${device_name}" + fi + + if [[ "${dst_id}" != "" ]] + then + network_dst_tab_get "${dst_id}" + + network_dst_ip_update "0.0.0.0" + fi +} + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# network_dst_init +#-------------------------------------------------------------------------------------------------------------------------- +# +#network_device_name_init() +#{ +# local dst_id="$1" +# +# +# if [[ "${dst_id}" != "" ]] +# then +# network_dst_tab_get "${dst_id}" +# +# network_route_dst_init "${dst_id}" +# +# network_route_rx3_init "${dst_device}" +# +# fi +# +# network_route_rx3_init "${target_device}" +#} + + + + +#-------------------------------------------------------------------------------------------------------------------------- +# network_device_name_init +#-------------------------------------------------------------------------------------------------------------------------- +# +#network_device_name_init() +#{ +# local target_device="$1" +# +# +# network_dst_tab_dev_lookup ${target_device} +# +# if [[ "${dst_id}" != "" ]] +# then +# network_route_dst_init "${dst_id}" +# fi +# +# network_route_rx3_init "${target_device}" +#} + + + + #-------------------------------------------------------------------------------------------------------------------------- # network_route_init #-------------------------------------------------------------------------------------------------------------------------- @@ -853,9 +1074,15 @@ network_route_init() { for dst_id in ${NETWORK_DST_ID_LIST} do - network_route_dst_init ${dst_id} - network_route_other_init ${dst_id} + network_device_init "${dst_id}" "" + network_route_other_init "${dst_id}" done + +# for dst_id in ${NETWORK_DST_ID_LIST} +# do +# network_route_dst_init ${dst_id} +# network_route_other_init ${dst_id} +# done } @@ -964,13 +1191,18 @@ network_dst_address_refresh() network_dst_tab_get "${dst_id}" - if [[ ( "${dst_host_name}" != "" ) ]] + if [[ ( "${dst_host_name}" != "" )]] then if [[ ${dst_host_name} =~ ([0-9]+) ]] then proxy_host="proxy${BASH_REMATCH[1]}.${NETWORK_DST_PROXY_NAME}" - dst_ip_new="$( nc -w ${NETWORK_NC_TIMEOUT} ${proxy_host} ${proxy_port} 2>/dev/null)" + if [[ ( "${dst_ip}" != "0.0.0.0") && ( "${dst_status}" != 1)]] + then + dst_ip_new="0.0.0.0" + else + dst_ip_new="$( nc -w ${NETWORK_NC_TIMEOUT} ${proxy_host} ${proxy_port} 2>/dev/null)" + fi if is_valid_ip "${dst_ip_new}" then diff --git a/usr/local/sbin/openvpn-down b/usr/local/sbin/openvpn-down index 1f8499f..1cf319a 100755 --- a/usr/local/sbin/openvpn-down +++ b/usr/local/sbin/openvpn-down @@ -39,23 +39,8 @@ Local_Netmask="$5" network_init -network_dst_tab_dev_lookup "${Dev}" -network_dst_tab_get "${dst_id}" +log_info "VPN-Down" "[${Dev}]: Local_MTU: [${Local_MTU}] Remote_MTU: [${Remote_MTU}] Local_Address: [${Local_Address}] Local_Netmask: [${Local_Netmask}] Dst_Table: [${dst_table}] Phase: [${Phase}] Status: [OK]" - -line="[${Dev}]: Local_MTU: [${Local_MTU}] Remote_MTU: [${Remote_MTU}] Local_Address: [${Local_Address}] Local_Netmask: [${Local_Netmask}] Dst_Table: [${dst_table}] Phase: [${Phase}]" - -if [[ "${dst_table}" != "" ]] -then - log_info "VPN-Down" "$line" " Status: [OK]" - - remote_address=0.0.0.0 - - log_trace "VPN-Down" "[${Dev}]: set ${remote_address} to vpn${id}.vpn.rx3" - - ${DEBUG} ip_host_update vpn${id} vpn.rx3 ${remote_address} 60 -else - log_error "VPN-Down" "$line" " Status: [ERROR]!" -fi +network_device_deinit "" "${Dev}" log_trace "VPN-Down" "[${Dev}]: Done!" diff --git a/usr/local/sbin/openvpn-up b/usr/local/sbin/openvpn-up index a84c00d..6eb794d 100755 --- a/usr/local/sbin/openvpn-up +++ b/usr/local/sbin/openvpn-up @@ -40,20 +40,9 @@ Local_Netmask="$5" network_init -network_dst_tab_dev_lookup "${Dev}" -network_dst_tab_get "${dst_id}" +log_info "VPN-Up" "[${Dev}]: Local_MTU: [${Local_MTU}] Remote_MTU: [${Remote_MTU}] Local_Address: [${Local_Address}] Local_Netmask: [${Local_Netmask}] Phase: [${Phase}] Status: [OK]" -line="[${Dev}]: Local_MTU: [${Local_MTU}] Remote_MTU: [${Remote_MTU}] Local_Address: [${Local_Address}] Local_Netmask: [${Local_Netmask}] Dst_Table: [${dst_table}] Dst_Id: [${dst_id}] Phase: [${Phase}]" - -if [[ "${dst_table}" != "" ]] -then - log_info "VPN-Up" "$line" " Status: [OK]" - log_trace "VPN-Up" "[${Dev}]: ip route add table: [${dst_table}] default dev: [${Dev}]" - - network_route_dst_init ${dst_id} -else - log_error "VPN-Up" "$line" " Status: [ERROR]!" -fi +network_device_init "" "${Dev}" log_trace "VPN-Up" "[${Dev}]: Done!" diff --git a/var/www/cgi-bin/vpn-admin_board.cgi b/var/www/cgi-bin/vpn-admin_board.cgi index d6c3935..e520b03 100755 --- a/var/www/cgi-bin/vpn-admin_board.cgi +++ b/var/www/cgi-bin/vpn-admin_board.cgi @@ -129,12 +129,25 @@ Destination_Status_Board() then echo -n "${dst_id}${dst_name}${NETWORK_DST_TYPE[${dst_type}]}${dst_device}" - if [[ "${dst_status}" == 1 ]] - then - echo -n "\"Up\"" - else - echo -n "\"Down\"" - fi + case "${dst_status}" + in + "0") + echo -n "\"Down\"" + ;; + + "1") + echo -n "\"Up\"" + ;; + + "2") + echo -n "\"Unready\"" + ;; + + *) + echo -n "\"Unknown\"" + ;; + esac + echo "${dst_ip:--}${dst_host_name:--}${dst_config:--}${dst_table}${dst_bytes_received:--}${dst_bytes_sent:--}${dst_uptime:--}" else