#!/bin/bash #----------------------------------------------------------------------------------------------------------------------------------- # # Rx3 Network Library # # Copyright (C) 2025-2026 Arnaud G. GIBERT # mailto:arnaud@rx3.net # # This is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this program; If not, see # . # #----------------------------------------------------------------------------------------------------------------------------------- if [[ "${RX3_NETWORK_LIB}" != "" ]] then return else declare -g RX3_NETWORK_LIB=1 fi #----------------------------------------------------------------------------------------------------------------------------------- # Includes #----------------------------------------------------------------------------------------------------------------------------------- : "${RX3_LIB_DIR:=/usr/lib/rx3}" . "${RX3_LIB_DIR}/dns.bash" #----------------------------------------------------------------------------------------------------------------------------------- # Global Variable #----------------------------------------------------------------------------------------------------------------------------------- declare -g NETWORK_OPENVPN_STATUS declare -Ag NETWORK_IP_ROUTE_TAB declare -g NETWORK_IP_ROUTE_ID_LIST declare -Ag NETWORK_IP_ROUTE_IP_IDX declare -g NETWORK_SRC_TYPE declare -Ag NETWORK_SRC_TAB declare -g NETWORK_SRC_ID_LIST declare -Ag NETWORK_SRC_IP_IDX declare -g NETWORK_DST_TYPE declare -Ag NETWORK_DST_TAB declare -g NETWORK_DST_ID_LIST declare -Ag NETWORK_DST_NAME_IDX declare -Ag NETWORK_DST_DEV_IDX declare -g NETWORK_CONFIG_FILE="/etc/sysconfig/rx3-network" declare -g NETWORK_CONFIG_LOCK="/var/lock/network/config" #declare -g NETWORK_CONFIG_LOCK="${NETWORK_CONFIG_FILE}" declare -g NETWORK_LOG_FILE declare -g NETWORK_LOG_LOCK #declare -g NETWORK_LOG_LOCK="${NETWORK_LOG_FILE}" declare -g NETWORK_LOG_TRACE declare -g NETWORK_NC_TIMEOUT #-------------------------------------------------------------------------------------------------------------------------- # is_valid_ip #-------------------------------------------------------------------------------------------------------------------------- is_valid_ip() { local ip=$1 local regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$' if [[ $ip =~ $regex ]] then IFS='.' read -r o1 o2 o3 o4 <<< "$ip" for octet in $o1 $o2 $o3 $o4 do if (( octet < 0 || octet > 255 )) then return 1 fi done return 0 else return 1 fi } #-------------------------------------------------------------------------------------------------------------------------- # ip_to_num #-------------------------------------------------------------------------------------------------------------------------- ip_to_num() { local ip="$1" local a local b local c local d IFS=. read -r a b c d <<< "${ip}" echo $(( (a << 24) + (b << 16) + (c << 8) + d )) } #-------------------------------------------------------------------------------------------------------------------------- # num_to_ip #-------------------------------------------------------------------------------------------------------------------------- num_to_ip() { local num="$1" # Optional safety check if (( num < 0 || num > 4294967295 )) then echo_error "num_to_ip: value out of range (0‑4294967295)" return 1 fi # Extract each byte by shifting and masking local a=$(( (num >> 24) & 255 )) local b=$(( (num >> 16) & 255 )) local c=$(( (num >> 8) & 255 )) local d=$(( num & 255 )) printf '%d.%d.%d.%d\n' "$a" "$b" "$c" "$d" } #-------------------------------------------------------------------------------------------------------------------------- # network_common_load #-------------------------------------------------------------------------------------------------------------------------- network_common_load() { log_trace "Network" "Loading common..." NETWORK_OPENVPN_STATUS="$( sudo /usr/local/sbin/openvpn-status)" NETWORK_TABLE_LIST="" } #-------------------------------------------------------------------------------------------------------------------------- # network_common_dump #-------------------------------------------------------------------------------------------------------------------------- network_common_dump() { echo "NETWORK_OPENVPN_STATUS: [${NETWORK_OPENVPN_STATUS}]" echo echo "NETWORK_TABLE_LIST: [${NETWORK_TABLE_LIST}]" echo } #-------------------------------------------------------------------------------------------------------------------------- # 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 #-------------------------------------------------------------------------------------------------------------------------- network_ip_route_tab_load() { nirtl_id=0 log_trace "Network" "Loading IP Route tab..." while IFS= read -r line do line=${line%%#*} if [[ ! -z "$line" ]] then set ${line} nirtl_ip="$1" nirtl_mask="$2" nirtl_device="$3" var_assign NETWORK_IP_ROUTE_ID_LIST "${nirtl_id}" INC tab_assign NETWORK_IP_ROUTE_TAB "${nirtl_id},IP" "${nirtl_ip}" tab_assign NETWORK_IP_ROUTE_TAB "${nirtl_id},Mask" "${nirtl_mask}" tab_assign NETWORK_IP_ROUTE_TAB "${nirtl_id},Device" "${nirtl_device}" tab_assign NETWORK_IP_ROUTE_IP_IDX "${nirtl_ip}" "${nirtl_id}" nirtl_id=$(( ${nirtl_id} + 1)) fi done <<< ${NETWORK_IP_ROUTE_CONFIG} } #-------------------------------------------------------------------------------------------------------------------------- # network_ip_route_tab_get #-------------------------------------------------------------------------------------------------------------------------- network_ip_route_tab_get() { ip_route_id="$1" ip_route_ip=${NETWORK_IP_ROUTE_TAB["${ip_route_id},IP"]} ip_route_mask=${NETWORK_IP_ROUTE_TAB["${ip_route_id},Mask"]} ip_route_device=${NETWORK_IP_ROUTE_TAB["${ip_route_id},Device"]} } #-------------------------------------------------------------------------------------------------------------------------- # network_ip_route_tab_dump #-------------------------------------------------------------------------------------------------------------------------- network_ip_route_tab_dump() { echo "NETWORK_IP_ROUTE_ID_LIST: [${NETWORK_IP_ROUTE_ID_LIST}]" echo echo "NETWORK_IP_ROUTE_IP_IDX:" for key in "${!NETWORK_IP_ROUTE_IP_IDX[@]}" do echo "[${key}]: [${NETWORK_IP_ROUTE_IP_IDX[${key}]}]" done | sort -n echo echo "NETWORK_IP_ROUTE_TAB:" for key in "${!NETWORK_IP_ROUTE_TAB[@]}" do echo "[${key}]: [${NETWORK_IP_ROUTE_TAB[${key}]}]" done | sort -n echo } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_tab_load #-------------------------------------------------------------------------------------------------------------------------- network_dst_tab_load() { ndtl_id=0 vpn_id=0 log_trace "Network" "Loading Dst tab..." while IFS= read -r line do line=${line%%#*} if [[ ! -z "$line" ]] then set ${line} ndtl_name="$1" ndtl_type="$2" ndtl_device="$3" ndtl_config="$4" ndtl_table="$5" var_assign NETWORK_DST_ID_LIST "${ndtl_id}" INC tab_assign NETWORK_DST_TAB "${ndtl_id},Name" "${ndtl_name}" tab_assign NETWORK_DST_TAB "${ndtl_id},Type" "${ndtl_type}" tab_assign NETWORK_DST_TAB "${ndtl_id},Device" "${ndtl_device}" tab_assign NETWORK_DST_TAB "${ndtl_id},Config" "${ndtl_config}" tab_assign NETWORK_DST_TAB "${ndtl_id},Table" "${ndtl_table}" var_assign NETWORK_TABLE_LIST "${ndtl_table}" INC ndtl_status="$( ip link show dev ${ndtl_device} 2>/dev/null | grep -q ",UP," && echo "1" || echo "0")" if [[ "${ndtl_type}" == "5" ]] then ndtl_host_name="" dns_value="" else ndtl_host_name="vpn${vpn_id}.${NETWORK_DST_NAME}" 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}" tab_assign NETWORK_DST_TAB "${ndtl_id},IP" "${dns_value}" case "${ndtl_type}" in "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)" ;; "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 if [[ "${ndtl_type}" == "1" ]] then ndtl_start_date="${ovpn_stat_connected_date}" ndtl_uptime="$( echo $(( $(date +%s) - ${ovpn_stat_connected_time_t})) | awk '{days = int($1/86400); print days " day" (( days > 1 ) ? "s" : "") strftime(" %H:%M:%S", $1,1)}')" else 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)}')" fi else ndtl_start_date="" ndtl_uptime="" fi tab_assign NETWORK_DST_TAB "${ndtl_id},Bytes_Received" "${ndtl_bytes_received}" tab_assign NETWORK_DST_TAB "${ndtl_id},Bytes_Sent" "${ndtl_bytes_sent}" tab_assign NETWORK_DST_TAB "${ndtl_id},Start_Date" "${ndtl_start_date}" tab_assign NETWORK_DST_TAB "${ndtl_id},Uptime" "${ndtl_uptime}" tab_assign NETWORK_DST_NAME_IDX "${ndtl_name}" "${ndtl_id}" tab_assign NETWORK_DST_DEV_IDX "${ndtl_device}" "${ndtl_id}" ndtl_id=$(( ${ndtl_id} + 1)) fi done <<< ${NETWORK_DST_CONFIG} } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_tab_get #-------------------------------------------------------------------------------------------------------------------------- network_dst_tab_get() { dst_id="$1" dst_name=${NETWORK_DST_TAB["${dst_id},Name"]} dst_type=${NETWORK_DST_TAB["${dst_id},Type"]} dst_device=${NETWORK_DST_TAB["${dst_id},Device"]} dst_config=${NETWORK_DST_TAB["${dst_id},Config"]} dst_table=${NETWORK_DST_TAB["${dst_id},Table"]} dst_status=${NETWORK_DST_TAB["${dst_id},Status"]} dst_host_name=${NETWORK_DST_TAB["${dst_id},Host_Name"]} dst_ip=${NETWORK_DST_TAB["${dst_id},IP"]} dst_bytes_received=${NETWORK_DST_TAB["${dst_id},Bytes_Received"]} dst_bytes_sent=${NETWORK_DST_TAB["${dst_id},Bytes_Sent"]} dst_start_date=${NETWORK_DST_TAB["${dst_id},Start_Date"]} dst_uptime=${NETWORK_DST_TAB["${dst_id},Uptime"]} } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_tab_dump #-------------------------------------------------------------------------------------------------------------------------- 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:" for key in "${!NETWORK_DST_NAME_IDX[@]}" do echo "[${key}]: [${NETWORK_DST_NAME_IDX[${key}]}]" done | sort -n echo echo "NETWORK_DST_DEV_IDX:" for key in "${!NETWORK_DST_DEV_IDX[@]}" do echo "[${key}]: [${NETWORK_DST_DEV_IDX[${key}]}]" done | sort -n echo echo "NETWORK_DST_TAB:" for key in "${!NETWORK_DST_TAB[@]}" do echo "[${key}]: [${NETWORK_DST_TAB[${key}]}]" done | sort -n echo } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_tab_name_lookup #-------------------------------------------------------------------------------------------------------------------------- network_dst_tab_name_lookup() { dst_name="$1" dst_id=${NETWORK_DST_NAME_IDX["${dst_name}"]} } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_tab_dev_lookup #-------------------------------------------------------------------------------------------------------------------------- network_dst_tab_dev_lookup() { dst_device="$1" dst_id=${NETWORK_DST_DEV_IDX["${dst_device}"]} } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_ip_update #-------------------------------------------------------------------------------------------------------------------------- network_dst_ip_update() { local dst_ip_new="$1" if [[ "${dst_ip}" != "${dst_ip_new}" ]] then log_info "Network" "Update [${dst_host_name}]: Old: [${dst_ip}] New: [${dst_ip_new}]" ${DEBUG} /usr/local/sbin/ip_host_update "${dst_host_name/.*}" "${dst_host_name#*.}" "${dst_ip_new}" 60 tab_assign NETWORK_DST_TAB "${dst_id},IP" "${dst_ip_new}" else log_trace "Network" "Skiping [${dst_host_name}]: IP: [${dst_ip}]" fi } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_name_ip_update #-------------------------------------------------------------------------------------------------------------------------- network_dst_name_ip_update() { local dst_name="$1" local dst_ip_new="$2" network_dst_tab_name_lookup "${job_name}" if [[ "${dst_id}" != "" ]] then network_dst_tab_get "${dst_id}" network_dst_ip_update "${dst_ip_new}" else log_error "Network" "dst name not found: [${dst_name}]" fi } #-------------------------------------------------------------------------------------------------------------------------- # network_src_tab_load #-------------------------------------------------------------------------------------------------------------------------- network_src_tab_load() { nstl_id=0 nstl_local_id=0 nstl_port_default=3000 log_trace "Network" "Loading Src tab..." ip_base=$( ip_to_num ${NETWORK_SRC_LOCAL_ADDRESS}) while IFS= read -r line do line=${line%%#*} if [[ ! -z "$line" ]] then set ${line} nstl_ip="$1" nstl_type="$2" nstl_owner="$3" nstl_table="$4" nstl_port_start="$5" nstl_port_range="$6" if [[ "${nstl_port_start}" == "-" ]] then nstl_port_start=${nstl_port_default} fi dns_lookup PTR ${nstl_ip} nstl_host_name="${dns_value}" case "${nstl_type}" in "0") # Local # nstl_device="${NETWORK_SRC_DEVICE}-${nstl_local_id}" # ((nstl_local_id++)) # [[ $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))" 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="" nstl_status="2" nstl_bytes_received="" nstl_bytes_sent="" nstl_uptime="" nstl_last_seen="" ;; "2") # OpenVPN network_common_openvpn_stats_get "" "${nstl_host_name}" if [[ "${ovpn_stat_device}" == "" ]] then 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_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 ;; esac if [[ " ${NETWORK_TABLE_LIST} " != *" ${nstl_table} "* ]] then echo_error "Invalid table number: [${nstl_table}] in network src entry: [${nstl_id}]!" exit 1 fi var_assign NETWORK_SRC_ID_LIST "${nstl_id}" INC tab_assign NETWORK_SRC_TAB "${nstl_id},IP" "${nstl_ip}" tab_assign NETWORK_SRC_TAB "${nstl_id},Host_Name" "${nstl_host_name}" tab_assign NETWORK_SRC_TAB "${nstl_id},Type" "${nstl_type}" tab_assign NETWORK_SRC_TAB "${nstl_id},Owner" "${nstl_owner}" tab_assign NETWORK_SRC_TAB "${nstl_id},Table" "${nstl_table}" tab_assign NETWORK_SRC_TAB "${nstl_id},Port_Start" "${nstl_port_start}" tab_assign NETWORK_SRC_TAB "${nstl_id},Port_Range" "${nstl_port_range}" tab_assign NETWORK_SRC_TAB "${nstl_id},Device" "${nstl_device}" tab_assign NETWORK_SRC_TAB "${nstl_id},Status" "${nstl_status}" tab_assign NETWORK_SRC_TAB "${nstl_id},Bytes_Received" "${nstl_bytes_received}" tab_assign NETWORK_SRC_TAB "${nstl_id},Bytes_Sent" "${nstl_bytes_sent}" tab_assign NETWORK_SRC_TAB "${nstl_id},Uptime" "${nstl_uptime}" tab_assign NETWORK_SRC_TAB "${nstl_id},Last_Seen" "${nstl_last_seen}" tab_assign NETWORK_SRC_IP_IDX "${nstl_ip}" "${nstl_id}" nstl_id=$(( ${nstl_id} + 1)) nstl_port_default=$(( ${nstl_port_start} + ${nstl_port_range})) fi done <<< ${NETWORK_SRC_CONFIG} } #-------------------------------------------------------------------------------------------------------------------------- # network_src_tab_get #-------------------------------------------------------------------------------------------------------------------------- network_src_tab_get() { src_id="$1" src_ip=${NETWORK_SRC_TAB["${src_id},IP"]} src_host_name=${NETWORK_SRC_TAB["${src_id},Host_Name"]} src_type=${NETWORK_SRC_TAB["${src_id},Type"]} src_owner=${NETWORK_SRC_TAB["${src_id},Owner"]} src_table=${NETWORK_SRC_TAB["${src_id},Table"]} src_port_start=${NETWORK_SRC_TAB["${src_id},Port_Start"]} src_port_range=${NETWORK_SRC_TAB["${src_id},Port_Range"]} if [[ "${src_port_range}" != "0" ]] then src_port_end=$(( ${src_port_start} + ${src_port_range} - 1)) else src_port_start="" src_port_end="" fi src_device=${NETWORK_SRC_TAB["${src_id},Device"]} src_status=${NETWORK_SRC_TAB["${src_id},Status"]} src_bytes_received=${NETWORK_SRC_TAB["${src_id},Bytes_Received"]} src_bytes_sent=${NETWORK_SRC_TAB["${src_id},Bytes_Sent"]} src_start_date=${NETWORK_SRC_TAB["${src_id},Start_Date"]} src_uptime=${NETWORK_SRC_TAB["${src_id},Uptime"]} src_last_seen=${NETWORK_SRC_TAB["${src_id},Last_Seen"]} } #-------------------------------------------------------------------------------------------------------------------------- # network_src_tab_dump #-------------------------------------------------------------------------------------------------------------------------- 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 echo "NETWORK_SRC_IP_IDX:" for key in "${!NETWORK_SRC_IP_IDX[@]}" do echo "[${key}]: [${NETWORK_SRC_IP_IDX[${key}]}]" done | sort -n echo echo "NETWORK_SRC_TAB:" for key in "${!NETWORK_SRC_TAB[@]}" do echo "[${key}]: [${NETWORK_SRC_TAB[${key}]}]" done | sort -n echo } #-------------------------------------------------------------------------------------------------------------------------- # network_src_tab_ip_lookup #-------------------------------------------------------------------------------------------------------------------------- network_src_tab_ip_lookup() { src_ip="$1" src_id=${NETWORK_SRC_IP_IDX["${src_ip}"]} } #-------------------------------------------------------------------------------------------------------------------------- # network_tab_load #-------------------------------------------------------------------------------------------------------------------------- network_tab_load() { log_trace "Network" "Loading config..." dns_tab_load network_common_load network_ip_route_tab_load network_dst_tab_load network_src_tab_load dns_tab_save } #-------------------------------------------------------------------------------------------------------------------------- # network_tab_dump #-------------------------------------------------------------------------------------------------------------------------- network_tab_dump() { dns_tab_dump network_common_dump network_ip_route_tab_dump network_dst_tab_dump network_src_tab_dump } #-------------------------------------------------------------------------------------------------------------------------- # network_route_dst_init #-------------------------------------------------------------------------------------------------------------------------- network_route_dst_init() { local dst_id="$1" network_dst_tab_get "${dst_id}" if [[ ${dst_type} == "0" ]] then log_trace "Network" "Copy main default route into table ${dst_table} (VPN Local routing table)" if [[ "$(ip route list match 0.0.0.0 table main)" != "" ]] then ${DEBUG} ip route add $(ip route list match 0.0.0.0 table main) table ${dst_table} fi else log_trace "Network" "Define default route to device: [${dst_device}] into table: [${dst_table}]" if [[ "$(ip link show ${dst_device})" != "" ]] then ${DEBUG} ip route add default dev ${dst_device} table ${dst_table} fi fi # 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} do network_dst_tab_get ${dst_id} for ip_route_id in ${NETWORK_IP_ROUTE_ID_LIST} do network_ip_route_tab_get ${ip_route_id} if [[ "${ip_route_device}" == "${target_device}" ]] then ${DEBUG} ip route add ${ip_route_ip}/${ip_route_mask} dev ${ip_route_device} table ${dst_table} fi done done } #-------------------------------------------------------------------------------------------------------------------------- # network_route_other_init #-------------------------------------------------------------------------------------------------------------------------- network_route_other_init() { local dst_id="$1" network_dst_tab_get ${dst_id} log_trace "Network" "Add other routes in Rx3 VPN table: [${dst_table}]" for ip_route_id in ${NETWORK_IP_ROUTE_ID_LIST} do network_ip_route_tab_get ${ip_route_id} network_dst_tab_dev_lookup ${ip_route_device} if [[ "${dst_id}" == "" ]] then ${DEBUG} ip route add ${ip_route_ip}/${ip_route_mask} table ${dst_table} dev ${ip_route_device} fi done } #-------------------------------------------------------------------------------------------------------------------------- # 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_route_init #-------------------------------------------------------------------------------------------------------------------------- network_route_init() { for dst_id in ${NETWORK_DST_ID_LIST} do 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 } #-------------------------------------------------------------------------------------------------------------------------- # network_route_deinit #-------------------------------------------------------------------------------------------------------------------------- network_route_deinit() { log_trace "Network" "Remove Rx3 routes in VPN tables" for table in ${NETWORK_TABLE_LIST} do for ip_route_id in ${NETWORK_IP_ROUTE_ID_LIST} do network_ip_route_tab_get ${ip_route_id} ${DEBUG} ip route del ${ip_route_ip}/${ip_route_mask} table ${table} dev ${ip_route_device} 2>/dev/null done done for dst_id in ${NETWORK_DST_ID_LIST} do network_dst_tab_get ${dst_id} log_trace "Network" "Remove default route in table: [${dst_table}]" ${DEBUG} ip route del default table ${dst_table} 2>/dev/null done } #-------------------------------------------------------------------------------------------------------------------------- # network_table_set #-------------------------------------------------------------------------------------------------------------------------- network_table_set() { nts_ip=$1 nts_table=$2 network_src_tab_ip_lookup "${nts_ip}" if [[ "${src_id}" == "" ]] then echo_error "IP not found: [${nts_ip}]!" return 1 fi if [[ " ${NETWORK_TABLE_LIST} " != *" ${nts_table} "* ]] then echo_error "Table not found: [${nts_table}]!" return 1 fi tab_assign NETWORK_SRC_TAB "${src_id},Table" "${ts_table}" ${DEBUG} sed "/^NETWORK_SRC_CONFIG=\"/,/^\"/ { s/^\(${nts_ip//./\\.}[[:space:]]\+\([^\t ]\+[[:space:]]\+\)\{2\}\)[^[:space:]]\+/\1${nts_table}/ }" -i ${NETWORK_CONFIG_FILE} ${DEBUG} ip rule del from ${nts_ip} 2>/dev/null ${DEBUG} ip rule add from ${nts_ip} table ${nts_table} } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_address_init_all #-------------------------------------------------------------------------------------------------------------------------- network_dst_address_init_all() { for dst_id in ${NETWORK_DST_ID_LIST} do network_dst_tab_get "${dst_id}" network_dst_ip_update "0.0.0.0" done } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_address_refresh #-------------------------------------------------------------------------------------------------------------------------- network_dst_address_refresh() { local dst_id="$1" local dst_ip_new local proxy_host local proxy_port=8080 network_dst_tab_get "${dst_id}" if [[ ( "${dst_host_name}" != "" )]] then if [[ ${dst_host_name} =~ ([0-9]+) ]] then proxy_host="proxy${BASH_REMATCH[1]}.${NETWORK_DST_PROXY_NAME}" if [[ ( "${dst_status}" == 1) || ( ( "${dst_status}" != 1) && ( "${dst_ip}" != "0.0.0.0")) ]] then if [[ ( ( "${dst_ip}" != "0.0.0.0") && ( "${dst_status}" != 1)) ]] then log_info "Network" "Reseting IP: [${dst_host_name}]: IP: [${dst_ip_new}] Status: (${dst_status})" 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 if [[ "${dst_ip}" != "${dst_ip_new}" ]] then network_dst_ip_update "${dst_ip_new}" else log_trace "Network" "Skiping: [${dst_host_name}]: No changes..." fi else log_info "Network" "Skiping: [${dst_host_name}]: Invalid IP: [${dst_ip_new}]" fi else log_trace "Network" "Skiping: [${dst_host_name}]: Device not Up..." fi else log_info "Network" "Skiping: dst_id: [${dst_id}]: Invalid host_name: [${dst_host_name}]" fi fi } #-------------------------------------------------------------------------------------------------------------------------- # network_dst_address_refresh_all #-------------------------------------------------------------------------------------------------------------------------- network_dst_address_refresh_all() { for dst_id in ${NETWORK_DST_ID_LIST} do network_dst_address_refresh "${dst_id}" done } #-------------------------------------------------------------------------------------------------------------------------- # bridge_up #-------------------------------------------------------------------------------------------------------------------------- function bridge_up { # set -x bu_bridge_device=$1 bu_bridge_network=$2 bu_bridge_mask=$3 bu_bridge_address=$4 bu_peer_address=$5 bu_table=$6 log_trace "Network" "Create bridge [${bu_bridge_device}]..." ${DEBUG} ip link add name ${bu_bridge_device} type bridge log_trace "Network" "Configure host side [${bu_bridge_device}:${bu_bridge_address}/${bu_bridge_mask}]..." ${DEBUG} ip link set ${bu_bridge_device} up ${DEBUG} ip addr add ${bu_bridge_address}/${bu_bridge_mask} dev ${bu_bridge_device} log_trace "Network" "Configure IP rule and routing [${bu_bridge_device}]..." ${DEBUG} ip rule del from ${bu_peer_address} 2>/dev/null ${DEBUG} ip rule add from ${bu_peer_address} table ${bu_table} for bu_tab in ${NETWORK_TABLE_LIST} do ${DEBUG} ip route add ${bu_bridge_network}/${bu_bridge_mask} dev ${bu_bridge_device} table ${bu_tab} done # set +x } #-------------------------------------------------------------------------------------------------------------------------- # bridge_down #-------------------------------------------------------------------------------------------------------------------------- function bridge_down { bd_bridge_device=$1 bd_bridge_network=$2 bd_bridge_mask=$3 bd_bridge_address=$4 bd_peer_address=$5 bd_table=$6 log_trace "Network" "Remove IP routing and rule [${bd_bridge_device}]..." for bd_tab in ${NETWORK_TABLE_LIST} do ${DEBUG} ip route del ${bd_bridge_network}/${bd_bridge_mask} dev ${bd_bridge_device} table ${bd_tab} 2>/dev/null || true done ${DEBUG} ip rule del from ${bd_peer_address} table ${bd_table} 2>/dev/null log_trace "Network" "Remove bridge [${bd_bridge_device}]..." ${DEBUG} ip link show ${bd_bridge_device} &>/dev/null && ${DEBUG} ip link del ${bd_bridge_device} } #-------------------------------------------------------------------------------------------------------------------------- # network_bridge_init #-------------------------------------------------------------------------------------------------------------------------- network_bridge_init() { log_trace "Network" "Add all Bridges" for src_id in ${NETWORK_SRC_ID_LIST} do network_src_tab_get ${src_id} if [[ "${src_type}" == "0" ]] then nbi_bridge_device="${src_device}" nbi_bridge_network="${src_ip%.*}.$(( ${src_ip/*./} - 1))" nbi_bridge_mask="30" nbi_bridge_address="${src_ip%.*}.$(( ${src_ip/*./} + 1))" nbi_peer_address="${src_ip}" bridge_up "${nbi_bridge_device}" "${nbi_bridge_network}" "${nbi_bridge_mask}" "${nbi_bridge_address}" "${nbi_peer_address}" "${src_table}" fi done } #-------------------------------------------------------------------------------------------------------------------------- # network_bridge_deinit #-------------------------------------------------------------------------------------------------------------------------- network_bridge_deinit() { log_trace "Network" "Remove all Bridge" for src_id in ${NETWORK_SRC_ID_LIST} do network_src_tab_get ${src_id} if [[ "${src_type}" == "0" ]] then nbi_bridge_device="${src_device}" nbi_bridge_network="${src_ip%.*}.$(( ${src_ip/*./} - 1))" nbi_bridge_mask="30" nbi_bridge_address="${src_ip%.*}.$(( ${src_ip/*./} + 1))" nbi_peer_address="${src_ip}" bridge_down "${nbi_bridge_device}" "${nbi_bridge_network}" "${nbi_bridge_mask}" "${nbi_bridge_address}" "${nbi_peer_address}" "${src_table}" fi done } #-------------------------------------------------------------------------------------------------------------------------- # network_forward_add #-------------------------------------------------------------------------------------------------------------------------- network_forward_add() { nfa_ip=$1 nfa_port_start=$2 nfa_port_end=$3 ${DEBUG} iptables -t nat -A PREROUTING-VPN -p tcp -m tcp --dport ${nfa_port_start}:${nfa_port_end} -j DNAT --to ${nfa_ip} ${DEBUG} iptables -t nat -A PREROUTING-VPN -p udp -m udp --dport ${nfa_port_start}:${nfa_port_end} -j DNAT --to ${nfa_ip} } #-------------------------------------------------------------------------------------------------------------------------- # network_forward_remove #-------------------------------------------------------------------------------------------------------------------------- network_forward_remove() { nfr_ip=$1 nfr_port_start=$2 nfr_port_end=$3 ${DEBUG} iptables -t nat -D PREROUTING-VPN -p tcp -m tcp --dport ${nfr_port_start}:${nfr_port_end} -j DNAT --to ${nfr_ip} ${DEBUG} iptables -t nat -D PREROUTING-VPN -p udp -m udp --dport ${nfr_port_start}:${nfr_port_end} -j DNAT --to ${nfr_ip} } #-------------------------------------------------------------------------------------------------------------------------- # network_forward_start #-------------------------------------------------------------------------------------------------------------------------- network_forward_start() { log_trace "Network" "Create VPN forward chain" ${DEBUG} iptables -t nat -N PREROUTING-VPN log_trace "Network" "Add jump rule for VPN" for dst_id in ${NETWORK_DST_ID_LIST} do network_dst_tab_get ${dst_id} if [[ "${dst_type}" != "0" ]] then ${DEBUG} iptables -t nat -A PREROUTING -i ${dst_device} -j PREROUTING-VPN fi done log_trace "Network" "Add VPN client addresse rules" for src_id in ${NETWORK_SRC_ID_LIST} do network_src_tab_get ${src_id} if [[ "${src_type}" != "0" ]] then ${DEBUG} ip rule del from ${src_ip} 2>/dev/null ${DEBUG} ip rule add from ${src_ip} table ${src_table} fi if [[ "${src_port_range}" != "0" ]] then network_forward_add "${src_ip}" "${src_port_start}" "${src_port_end}" fi done } #-------------------------------------------------------------------------------------------------------------------------- # network_forward_stop #-------------------------------------------------------------------------------------------------------------------------- network_forward_stop() { log_trace "Network" "Remove VPN client addresse rules" for src_id in ${NETWORK_SRC_ID_LIST} do network_src_tab_get ${src_id} ${DEBUG} ip rule del from ${src_ip} 2>/dev/null if [[ "${src_port_range}" != "0" ]] then network_forward_remove "${src_ip}" "${src_port_start}" "${src_port_end}" fi done log_trace "Network" "Remove Jump rule for VPN" for dst_id in ${NETWORK_DST_ID_LIST} do network_dst_tab_get ${dst_id} if [[ "${dst_type}" != "0" ]] then ${DEBUG} iptables -t nat -D PREROUTING -i ${dst_device} -j PREROUTING-VPN 2>/dev/null fi done log_trace "Network" "Delete VPN forward chain" ${DEBUG} iptables -t nat -X PREROUTING-VPN 2>/dev/null } #-------------------------------------------------------------------------------------------------------------------------- # network_init #-------------------------------------------------------------------------------------------------------------------------- network_init() { file_dir_init ${NETWORK_CONFIG_LOCK} root apache file_lock ${NETWORK_CONFIG_LOCK} READ 9 [ -e "${NETWORK_CONFIG_FILE}" ] && . "${NETWORK_CONFIG_FILE}" file_unlock 9 # By default Loggin is enabled # export LOG="" to disable it if [ -v LOG ] && [[ "${LOG}" == "" ]] then export NETWORK_LOG_FILE="" export NETWORK_LOG_LOCK="" fi # By default Echoing is disabled # export LOG="echo" to enable it if [ ! -v ECHO ] || [[ "${ECHO}" == "" ]] then export ECHO=":" fi log_set "${NETWORK_LOG_FILE}" "${NETWORK_LOG_LOCK}" "${ECHO}" "${NETWORK_LOG_TRACE}" dns_init file_dir_init ${NETWORK_LOG_FILE} root apache file_dir_init ${NETWORK_LOG_LOCK} root apache network_tab_load } #-------------------------------------------------------------------------------------------------------------------------- # network_deinit #-------------------------------------------------------------------------------------------------------------------------- network_deinit() { NETWORK_OPENVPN_STATUS="" NETWORK_IP_ROUTE_TAB=() NETWORK_IP_ROUTE_ID_LIST="" NETWORK_IP_ROUTE_IP_IDX=() NETWORK_SRC_TYPE="" NETWORK_SRC_TAB=() NETWORK_SRC_ID_LIST="" NETWORK_SRC_IP_IDX=() NETWORK_DST_TYPE="" NETWORK_DST_TAB=() NETWORK_DST_ID_LIST="" NETWORK_DST_NAME_IDX=() NETWORK_DST_DEV_IDX=() dns_deinit } #-------------------------------------------------------------------------------------------------------------------------- # network_reinit #-------------------------------------------------------------------------------------------------------------------------- network_reinit() { network_deinit network_init } #-------------------------------------------------------------------------------------------------------------------------- # network_start #-------------------------------------------------------------------------------------------------------------------------- network_start() { log_info "Network" "Starting network..." network_route_init network_bridge_init network_forward_start network_dst_address_init_all log_info "Network" "Network started!" } #-------------------------------------------------------------------------------------------------------------------------- # network_stop #-------------------------------------------------------------------------------------------------------------------------- network_stop() { log_info "Network" "Stoping network..." network_forward_stop network_bridge_deinit network_route_deinit log_info "Network" "Network stoped!" return 0 } #-------------------------------------------------------------------------------------------------------------------------- # network_status #-------------------------------------------------------------------------------------------------------------------------- network_status() { echo "Number of Network IP Route entries: ${#NETWORK_IP_ROUTE_IP_IDX[@]}" echo "Number of Network Src entries: ${#NETWORK_SRC_IP_IDX[@]}" echo "Number of Network Dst entries: ${#NETWORK_DST_DEV_IDX[@]}" echo "Number of DNS cache A entries: ${#DNS_A_TAB[@]}" echo "Number of DNS cache PTR entries: ${#DNS_PTR_TAB[@]}" ( echo "SRC" for src_id in ${NETWORK_SRC_ID_LIST} do network_src_tab_get ${src_id} if [[ "${src_device}" != "" ]] then echo ${src_device} fi done | sort -u echo "DST" for dst_id in ${NETWORK_DST_ID_LIST} do network_dst_tab_get ${dst_id} if [[ "${dst_device}" != "" ]] then echo ${dst_device} fi done | sort -u ) | while read entry do case ${entry} in "SRC") echo echo "Src Devices:" ;; "DST") echo echo "Dst Devices:" ;; *) ip address show $entry | sed -e 's/^[^:]*: //' ;; esac done echo echo "Rules:" ip rule show echo if [[ "${NETWORK_TABLE_LIST}" == "" ]] then echo "Network table list empty" echo else for table in ${NETWORK_TABLE_LIST} do echo "Table ${table}:" ip route list table ${table} echo done fi echo "Forward:" iptables -t nat -L PREROUTING -v -n echo iptables -t nat -L PREROUTING-VPN -v -n }