|
@@ -77,6 +77,14 @@ DESEC_DOMAIN="manager.firewallfalcon.qzz.io"
|
|
|
|
|
|
|
|
SELECTED_USER=""
|
|
SELECTED_USER=""
|
|
|
UNINSTALL_MODE="interactive"
|
|
UNINSTALL_MODE="interactive"
|
|
|
|
|
+BANNER_CACHE_TTL=5
|
|
|
|
|
+BANNER_CACHE_TS=0
|
|
|
|
|
+BANNER_CACHE_OS_NAME=""
|
|
|
|
|
+BANNER_CACHE_UP_TIME=""
|
|
|
|
|
+BANNER_CACHE_RAM_USAGE=""
|
|
|
|
|
+BANNER_CACHE_CPU_LOAD=""
|
|
|
|
|
+BANNER_CACHE_ONLINE_USERS=0
|
|
|
|
|
+BANNER_CACHE_TOTAL_USERS=0
|
|
|
|
|
|
|
|
if [[ $EUID -ne 0 ]]; then
|
|
if [[ $EUID -ne 0 ]]; then
|
|
|
echo -e "${C_RED}❌ Error: This script requires root privileges to run.${C_RESET}"
|
|
echo -e "${C_RED}❌ Error: This script requires root privileges to run.${C_RESET}"
|
|
@@ -97,14 +105,16 @@ check_environment() {
|
|
|
done
|
|
done
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ensure_firewallfalcon_dirs() {
|
|
|
|
|
+ mkdir -p "$DB_DIR" "$SSL_CERT_DIR" "$BANDWIDTH_DIR" "/etc/firewallfalcon/banners" /etc/ssh/sshd_config.d
|
|
|
|
|
+ touch "$DB_FILE"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
initial_setup() {
|
|
initial_setup() {
|
|
|
echo -e "${C_BLUE}⚙️ Initializing FirewallFalcon Manager setup...${C_RESET}"
|
|
echo -e "${C_BLUE}⚙️ Initializing FirewallFalcon Manager setup...${C_RESET}"
|
|
|
check_environment
|
|
check_environment
|
|
|
|
|
|
|
|
- mkdir -p "$DB_DIR"
|
|
|
|
|
- touch "$DB_FILE"
|
|
|
|
|
- mkdir -p "$SSL_CERT_DIR"
|
|
|
|
|
- mkdir -p "$BANDWIDTH_DIR"
|
|
|
|
|
|
|
+ ensure_firewallfalcon_dirs
|
|
|
|
|
|
|
|
echo -e "${C_BLUE}🔹 Configuring user limiter service...${C_RESET}"
|
|
echo -e "${C_BLUE}🔹 Configuring user limiter service...${C_RESET}"
|
|
|
setup_limiter_service
|
|
setup_limiter_service
|
|
@@ -488,15 +498,18 @@ TREOF
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
update_ssh_banners_config() {
|
|
update_ssh_banners_config() {
|
|
|
|
|
+ local tmp_conf
|
|
|
rm -f /usr/local/bin/firewallfalcon-login-info.sh 2>/dev/null
|
|
rm -f /usr/local/bin/firewallfalcon-login-info.sh 2>/dev/null
|
|
|
|
|
|
|
|
if [[ ! -f "/etc/firewallfalcon/banners_enabled" ]]; then
|
|
if [[ ! -f "/etc/firewallfalcon/banners_enabled" ]]; then
|
|
|
- rm -f "$SSHD_FF_CONFIG" 2>/dev/null
|
|
|
|
|
- systemctl reload sshd 2>/dev/null || systemctl reload ssh 2>/dev/null
|
|
|
|
|
|
|
+ if [[ -f "$SSHD_FF_CONFIG" ]]; then
|
|
|
|
|
+ rm -f "$SSHD_FF_CONFIG" 2>/dev/null
|
|
|
|
|
+ systemctl reload sshd 2>/dev/null || systemctl reload ssh 2>/dev/null
|
|
|
|
|
+ fi
|
|
|
return
|
|
return
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
- mkdir -p "/etc/firewallfalcon/banners" /etc/ssh/sshd_config.d
|
|
|
|
|
|
|
+ ensure_firewallfalcon_dirs
|
|
|
|
|
|
|
|
tmp_conf="/tmp/ff_banners_new.conf"
|
|
tmp_conf="/tmp/ff_banners_new.conf"
|
|
|
echo "# FirewallFalcon - Show login info native banners" > "$tmp_conf"
|
|
echo "# FirewallFalcon - Show login info native banners" > "$tmp_conf"
|
|
@@ -521,7 +534,12 @@ update_ssh_banners_config() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
setup_ssh_login_info() {
|
|
setup_ssh_login_info() {
|
|
|
- touch "/etc/firewallfalcon/banners_enabled"
|
|
|
|
|
|
|
+ ensure_firewallfalcon_dirs || return 1
|
|
|
|
|
+ if ! touch "/etc/firewallfalcon/banners_enabled"; then
|
|
|
|
|
+ echo -e "${C_RED}❌ Failed to enable SSH banners. Could not create /etc/firewallfalcon/banners_enabled.${C_RESET}"
|
|
|
|
|
+ return 1
|
|
|
|
|
+ fi
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -647,6 +665,11 @@ _select_user_interface() {
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
mapfile -t all_users < <(cut -d: -f1 "$DB_FILE" | sort)
|
|
mapfile -t all_users < <(cut -d: -f1 "$DB_FILE" | sort)
|
|
|
|
|
+ local -A all_user_lookup=()
|
|
|
|
|
+ local username
|
|
|
|
|
+ for username in "${all_users[@]}"; do
|
|
|
|
|
+ all_user_lookup["$username"]=1
|
|
|
|
|
+ done
|
|
|
|
|
|
|
|
if [ ${#all_users[@]} -ge 15 ]; then
|
|
if [ ${#all_users[@]} -ge 15 ]; then
|
|
|
read -p "👉 Enter a search term (or press Enter to list all): " search_term
|
|
read -p "👉 Enter a search term (or press Enter to list all): " search_term
|
|
@@ -668,16 +691,19 @@ _select_user_interface() {
|
|
|
printf " ${C_GREEN}[%2d]${C_RESET} %s\n" "$((i+1))" "${users[$i]}"
|
|
printf " ${C_GREEN}[%2d]${C_RESET} %s\n" "$((i+1))" "${users[$i]}"
|
|
|
done
|
|
done
|
|
|
echo -e "\n ${C_RED} [ 0]${C_RESET} ↩️ Cancel and return to main menu"
|
|
echo -e "\n ${C_RED} [ 0]${C_RESET} ↩️ Cancel and return to main menu"
|
|
|
|
|
+ echo -e "${C_CYAN}💡 Tip: you can also type the exact username directly.${C_RESET}"
|
|
|
echo
|
|
echo
|
|
|
local choice
|
|
local choice
|
|
|
while true; do
|
|
while true; do
|
|
|
- read -p "👉 Enter the number of the user: " choice
|
|
|
|
|
|
|
+ read -p "👉 Enter the number or exact username: " choice
|
|
|
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 0 ] && [ "$choice" -le "${#users[@]}" ]; then
|
|
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 0 ] && [ "$choice" -le "${#users[@]}" ]; then
|
|
|
if [ "$choice" -eq 0 ]; then
|
|
if [ "$choice" -eq 0 ]; then
|
|
|
SELECTED_USER=""; return
|
|
SELECTED_USER=""; return
|
|
|
else
|
|
else
|
|
|
SELECTED_USER="${users[$((choice-1))]}"; return
|
|
SELECTED_USER="${users[$((choice-1))]}"; return
|
|
|
fi
|
|
fi
|
|
|
|
|
+ elif [[ -n "${all_user_lookup[$choice]+x}" ]]; then
|
|
|
|
|
+ SELECTED_USER="$choice"; return
|
|
|
else
|
|
else
|
|
|
echo -e "${C_RED}❌ Invalid selection. Please try again.${C_RESET}"
|
|
echo -e "${C_RED}❌ Invalid selection. Please try again.${C_RESET}"
|
|
|
fi
|
|
fi
|
|
@@ -695,6 +721,11 @@ _select_multi_user_interface() {
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
mapfile -t all_users < <(cut -d: -f1 "$DB_FILE" | sort)
|
|
mapfile -t all_users < <(cut -d: -f1 "$DB_FILE" | sort)
|
|
|
|
|
+ local -A all_user_lookup=()
|
|
|
|
|
+ local username
|
|
|
|
|
+ for username in "${all_users[@]}"; do
|
|
|
|
|
+ all_user_lookup["$username"]=1
|
|
|
|
|
+ done
|
|
|
|
|
|
|
|
if [ ${#all_users[@]} -ge 15 ]; then
|
|
if [ ${#all_users[@]} -ge 15 ]; then
|
|
|
read -p "👉 Enter a search term (or press Enter to list all): " search_term
|
|
read -p "👉 Enter a search term (or press Enter to list all): " search_term
|
|
@@ -717,11 +748,12 @@ _select_multi_user_interface() {
|
|
|
done
|
|
done
|
|
|
echo -e "\n ${C_GREEN}[all]${C_RESET} Select ALL listed users"
|
|
echo -e "\n ${C_GREEN}[all]${C_RESET} Select ALL listed users"
|
|
|
echo -e " ${C_RED} [0]${C_RESET} ↩️ Cancel and return to main menu"
|
|
echo -e " ${C_RED} [0]${C_RESET} ↩️ Cancel and return to main menu"
|
|
|
- echo -e "\n${C_CYAN}💡 You can select multiple! (e.g. '1 3 5' or '1,3' or '1-4')${C_RESET}"
|
|
|
|
|
|
|
+ echo -e "\n${C_CYAN}💡 You can select multiple by number, range, or exact username.${C_RESET}"
|
|
|
|
|
+ echo -e "${C_CYAN} Examples: '1 3 5' or '1,3' or '1-4' or 'alice bob'${C_RESET}"
|
|
|
echo
|
|
echo
|
|
|
local choice
|
|
local choice
|
|
|
while true; do
|
|
while true; do
|
|
|
- read -p "👉 Enter user numbers: " choice
|
|
|
|
|
|
|
+ read -p "👉 Enter user numbers or usernames: " choice
|
|
|
choice=$(echo "$choice" | tr ',' ' ') # Replace commas with spaces
|
|
choice=$(echo "$choice" | tr ',' ' ') # Replace commas with spaces
|
|
|
|
|
|
|
|
if [[ -z "$choice" ]]; then
|
|
if [[ -z "$choice" ]]; then
|
|
@@ -740,6 +772,7 @@ _select_multi_user_interface() {
|
|
|
|
|
|
|
|
local valid=true
|
|
local valid=true
|
|
|
local selected_indices=()
|
|
local selected_indices=()
|
|
|
|
|
+ local selected_names=()
|
|
|
for token in $choice; do
|
|
for token in $choice; do
|
|
|
if [[ "$token" =~ ^[0-9]+-[0-9]+$ ]]; then
|
|
if [[ "$token" =~ ^[0-9]+-[0-9]+$ ]]; then
|
|
|
local start=${token%-*}
|
|
local start=${token%-*}
|
|
@@ -758,24 +791,35 @@ _select_multi_user_interface() {
|
|
|
elif [[ "$token" =~ ^[0-9]+$ ]]; then
|
|
elif [[ "$token" =~ ^[0-9]+$ ]]; then
|
|
|
if [ "$token" -ge 1 ] && [ "$token" -le "${#users[@]}" ]; then
|
|
if [ "$token" -ge 1 ] && [ "$token" -le "${#users[@]}" ]; then
|
|
|
selected_indices+=($token)
|
|
selected_indices+=($token)
|
|
|
|
|
+ elif [[ -n "${all_user_lookup[$token]+x}" ]]; then
|
|
|
|
|
+ selected_names+=("$token")
|
|
|
else
|
|
else
|
|
|
valid=false; break
|
|
valid=false; break
|
|
|
fi
|
|
fi
|
|
|
|
|
+ elif [[ -n "${all_user_lookup[$token]+x}" ]]; then
|
|
|
|
|
+ selected_names+=("$token")
|
|
|
else
|
|
else
|
|
|
valid=false; break
|
|
valid=false; break
|
|
|
fi
|
|
fi
|
|
|
done
|
|
done
|
|
|
|
|
|
|
|
- if [[ "$valid" == true && ${#selected_indices[@]} -gt 0 ]]; then
|
|
|
|
|
|
|
+ if [[ "$valid" == true && ( ${#selected_indices[@]} -gt 0 || ${#selected_names[@]} -gt 0 ) ]]; then
|
|
|
mapfile -t unique_indices < <(printf "%s\n" "${selected_indices[@]}" | sort -u -n)
|
|
mapfile -t unique_indices < <(printf "%s\n" "${selected_indices[@]}" | sort -u -n)
|
|
|
for idx in "${unique_indices[@]}"; do
|
|
for idx in "${unique_indices[@]}"; do
|
|
|
SELECTED_USERS+=("${users[$((idx-1))]}")
|
|
SELECTED_USERS+=("${users[$((idx-1))]}")
|
|
|
done
|
|
done
|
|
|
|
|
+ mapfile -t unique_names < <(printf "%s\n" "${selected_names[@]}" | sort -u)
|
|
|
|
|
+ for username in "${unique_names[@]}"; do
|
|
|
|
|
+ if ! printf "%s\n" "${SELECTED_USERS[@]}" | grep -Fxq "$username"; then
|
|
|
|
|
+ SELECTED_USERS+=("$username")
|
|
|
|
|
+ fi
|
|
|
|
|
+ done
|
|
|
return
|
|
return
|
|
|
else
|
|
else
|
|
|
- echo -e "${C_RED}❌ Invalid selection. Please check your numbers.${C_RESET}"
|
|
|
|
|
|
|
+ echo -e "${C_RED}❌ Invalid selection. Please check your numbers or usernames.${C_RESET}"
|
|
|
SELECTED_USERS=()
|
|
SELECTED_USERS=()
|
|
|
selected_indices=()
|
|
selected_indices=()
|
|
|
|
|
+ selected_names=()
|
|
|
fi
|
|
fi
|
|
|
done
|
|
done
|
|
|
}
|
|
}
|
|
@@ -852,6 +896,7 @@ create_user() {
|
|
|
generate_client_config "$username" "$password"
|
|
generate_client_config "$username" "$password"
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -864,20 +909,30 @@ delete_user() {
|
|
|
if [[ "$confirm" != "y" ]]; then echo -e "\n${C_YELLOW}❌ Deletion cancelled.${C_RESET}"; return; fi
|
|
if [[ "$confirm" != "y" ]]; then echo -e "\n${C_YELLOW}❌ Deletion cancelled.${C_RESET}"; return; fi
|
|
|
|
|
|
|
|
echo -e "\n${C_BLUE}🗑️ Deleting selected users...${C_RESET}"
|
|
echo -e "\n${C_BLUE}🗑️ Deleting selected users...${C_RESET}"
|
|
|
|
|
+ local username
|
|
|
for username in "${SELECTED_USERS[@]}"; do
|
|
for username in "${SELECTED_USERS[@]}"; do
|
|
|
killall -u "$username" -9 &>/dev/null
|
|
killall -u "$username" -9 &>/dev/null
|
|
|
- sleep 0.2
|
|
|
|
|
- userdel -r "$username" &>/dev/null
|
|
|
|
|
- if [ $? -eq 0 ]; then
|
|
|
|
|
- echo -e " ✅ System user '${C_YELLOW}$username${C_RESET}' deleted."
|
|
|
|
|
|
|
+ if id "$username" &>/dev/null; then
|
|
|
|
|
+ if userdel -r "$username" &>/dev/null; then
|
|
|
|
|
+ echo -e " ✅ System user '${C_YELLOW}$username${C_RESET}' deleted."
|
|
|
|
|
+ else
|
|
|
|
|
+ echo -e " ❌ Failed to delete system user '${C_YELLOW}$username${C_RESET}'."
|
|
|
|
|
+ fi
|
|
|
else
|
|
else
|
|
|
- echo -e " ❌ Failed to delete system user '${C_YELLOW}$username${C_RESET}'."
|
|
|
|
|
|
|
+ echo -e " ℹ️ System user '${C_YELLOW}$username${C_RESET}' was already missing. Removing manager data only."
|
|
|
fi
|
|
fi
|
|
|
rm -f "$BANDWIDTH_DIR/${username}.usage"
|
|
rm -f "$BANDWIDTH_DIR/${username}.usage"
|
|
|
rm -rf "$BANDWIDTH_DIR/pidtrack/${username}"
|
|
rm -rf "$BANDWIDTH_DIR/pidtrack/${username}"
|
|
|
- sed -i "/^$username:/d" "$DB_FILE"
|
|
|
|
|
done
|
|
done
|
|
|
|
|
+
|
|
|
|
|
+ if [[ -f "$DB_FILE" ]]; then
|
|
|
|
|
+ local db_tmp
|
|
|
|
|
+ db_tmp=$(mktemp)
|
|
|
|
|
+ awk -F: 'NR==FNR { drop[$1]=1; next } !($1 in drop)' <(printf "%s\n" "${SELECTED_USERS[@]}") "$DB_FILE" > "$db_tmp" && mv "$db_tmp" "$DB_FILE"
|
|
|
|
|
+ rm -f "$db_tmp" 2>/dev/null
|
|
|
|
|
+ fi
|
|
|
|
|
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1017,27 +1072,56 @@ list_users() {
|
|
|
echo -e "${C_CYAN}=========================================================================================${C_RESET}"
|
|
echo -e "${C_CYAN}=========================================================================================${C_RESET}"
|
|
|
printf "${C_BOLD}${C_WHITE}%-18s | %-12s | %-10s | %-15s | %-20s${C_RESET}\n" "USERNAME" "EXPIRES" "CONNS" "BANDWIDTH" "STATUS"
|
|
printf "${C_BOLD}${C_WHITE}%-18s | %-12s | %-10s | %-15s | %-20s${C_RESET}\n" "USERNAME" "EXPIRES" "CONNS" "BANDWIDTH" "STATUS"
|
|
|
echo -e "${C_CYAN}-----------------------------------------------------------------------------------------${C_RESET}"
|
|
echo -e "${C_CYAN}-----------------------------------------------------------------------------------------${C_RESET}"
|
|
|
-
|
|
|
|
|
- while IFS=: read -r user pass expiry limit bandwidth_gb _extra; do
|
|
|
|
|
- local online_count
|
|
|
|
|
- online_count=$(pgrep -u "$user" sshd | wc -l)
|
|
|
|
|
-
|
|
|
|
|
- local status
|
|
|
|
|
- status=$(get_user_status "$user")
|
|
|
|
|
|
|
|
|
|
- local plain_status
|
|
|
|
|
- plain_status=$(echo -e "$status" | sed 's/\x1b\[[0-9;]*m//g')
|
|
|
|
|
-
|
|
|
|
|
|
|
+ local current_ts
|
|
|
|
|
+ current_ts=$(date +%s)
|
|
|
|
|
+ local -A system_user_lookup=()
|
|
|
|
|
+ local -A locked_user_lookup=()
|
|
|
|
|
+ local -A session_counts=()
|
|
|
|
|
+
|
|
|
|
|
+ while IFS=: read -r system_user _rest; do
|
|
|
|
|
+ [[ -n "$system_user" ]] && system_user_lookup["$system_user"]=1
|
|
|
|
|
+ done < /etc/passwd
|
|
|
|
|
+
|
|
|
|
|
+ while read -r passwd_user _ passwd_status _rest; do
|
|
|
|
|
+ [[ -z "$passwd_user" ]] && continue
|
|
|
|
|
+ if [[ "$passwd_status" == "L" ]]; then
|
|
|
|
|
+ locked_user_lookup["$passwd_user"]=1
|
|
|
|
|
+ fi
|
|
|
|
|
+ done < <(passwd -Sa 2>/dev/null)
|
|
|
|
|
+
|
|
|
|
|
+ while read -r ssh_user ssh_count; do
|
|
|
|
|
+ [[ -n "$ssh_user" && -n "$ssh_count" ]] && session_counts["$ssh_user"]="$ssh_count"
|
|
|
|
|
+ done < <(ps -C sshd -o user= 2>/dev/null | awk 'NF {count[$1]++} END {for (user in count) print user, count[user]}')
|
|
|
|
|
+
|
|
|
|
|
+ while IFS=: read -r user pass expiry limit bandwidth_gb _extra; do
|
|
|
|
|
+ local online_count="${session_counts[$user]:-0}"
|
|
|
local connection_string="$online_count / $limit"
|
|
local connection_string="$online_count / $limit"
|
|
|
-
|
|
|
|
|
- # Bandwidth display
|
|
|
|
|
|
|
+ local plain_status="Active"
|
|
|
|
|
+ local status="${C_GREEN}🟢 Active${C_RESET}"
|
|
|
|
|
+
|
|
|
|
|
+ if [[ -z "${system_user_lookup[$user]+x}" ]]; then
|
|
|
|
|
+ plain_status="Not Found"
|
|
|
|
|
+ status="${C_RED}Not Found${C_RESET}"
|
|
|
|
|
+ elif [[ -n "${locked_user_lookup[$user]+x}" ]]; then
|
|
|
|
|
+ plain_status="Locked"
|
|
|
|
|
+ status="${C_YELLOW}🔒 Locked${C_RESET}"
|
|
|
|
|
+ elif [[ -n "$expiry" && "$expiry" != "Never" ]]; then
|
|
|
|
|
+ local expiry_ts
|
|
|
|
|
+ expiry_ts=$(date -d "$expiry" +%s 2>/dev/null || echo 0)
|
|
|
|
|
+ if [[ "$expiry_ts" =~ ^[0-9]+$ ]] && (( expiry_ts > 0 && expiry_ts < current_ts )); then
|
|
|
|
|
+ plain_status="Expired"
|
|
|
|
|
+ status="${C_RED}🗓️ Expired${C_RESET}"
|
|
|
|
|
+ fi
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
[[ -z "$bandwidth_gb" ]] && bandwidth_gb="0"
|
|
[[ -z "$bandwidth_gb" ]] && bandwidth_gb="0"
|
|
|
local bw_string="Unlimited"
|
|
local bw_string="Unlimited"
|
|
|
if [[ "$bandwidth_gb" != "0" ]]; then
|
|
if [[ "$bandwidth_gb" != "0" ]]; then
|
|
|
local used_bytes=0
|
|
local used_bytes=0
|
|
|
if [[ -f "$BANDWIDTH_DIR/${user}.usage" ]]; then
|
|
if [[ -f "$BANDWIDTH_DIR/${user}.usage" ]]; then
|
|
|
used_bytes=$(cat "$BANDWIDTH_DIR/${user}.usage" 2>/dev/null)
|
|
used_bytes=$(cat "$BANDWIDTH_DIR/${user}.usage" 2>/dev/null)
|
|
|
- [[ -z "$used_bytes" ]] && used_bytes=0
|
|
|
|
|
|
|
+ [[ "$used_bytes" =~ ^[0-9]+$ ]] || used_bytes=0
|
|
|
fi
|
|
fi
|
|
|
local used_gb
|
|
local used_gb
|
|
|
used_gb=$(awk "BEGIN {printf \"%.1f\", $used_bytes / 1073741824}")
|
|
used_gb=$(awk "BEGIN {printf \"%.1f\", $used_bytes / 1073741824}")
|
|
@@ -1045,11 +1129,11 @@ list_users() {
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
local line_color="$C_WHITE"
|
|
local line_color="$C_WHITE"
|
|
|
- case $plain_status in
|
|
|
|
|
- *"Active"*) line_color="$C_GREEN" ;;
|
|
|
|
|
- *"Locked"*) line_color="$C_YELLOW" ;;
|
|
|
|
|
- *"Expired"*) line_color="$C_RED" ;;
|
|
|
|
|
- *"Not Found"*) line_color="$C_DIM" ;;
|
|
|
|
|
|
|
+ case "$plain_status" in
|
|
|
|
|
+ "Active") line_color="$C_GREEN" ;;
|
|
|
|
|
+ "Locked") line_color="$C_YELLOW" ;;
|
|
|
|
|
+ "Expired") line_color="$C_RED" ;;
|
|
|
|
|
+ "Not Found") line_color="$C_DIM" ;;
|
|
|
esac
|
|
esac
|
|
|
|
|
|
|
|
printf "${line_color}%-18s ${C_RESET}| ${C_YELLOW}%-12s ${C_RESET}| ${C_CYAN}%-10s ${C_RESET}| ${C_ORANGE}%-15s ${C_RESET}| %-20s\n" "$user" "$expiry" "$connection_string" "$bw_string" "$status"
|
|
printf "${line_color}%-18s ${C_RESET}| ${C_YELLOW}%-12s ${C_RESET}| ${C_CYAN}%-10s ${C_RESET}| ${C_ORANGE}%-15s ${C_RESET}| %-20s\n" "$user" "$expiry" "$connection_string" "$bw_string" "$status"
|
|
@@ -1114,6 +1198,7 @@ cleanup_expired() {
|
|
|
sed -i "/^$user:/d" "$DB_FILE"
|
|
sed -i "/^$user:/d" "$DB_FILE"
|
|
|
done
|
|
done
|
|
|
echo -e "\n${C_GREEN}✅ Expired users have been cleaned up.${C_RESET}"
|
|
echo -e "\n${C_GREEN}✅ Expired users have been cleaned up.${C_RESET}"
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
else
|
|
else
|
|
|
echo -e "\n${C_YELLOW}❌ Cleanup cancelled.${C_RESET}"
|
|
echo -e "\n${C_YELLOW}❌ Cleanup cancelled.${C_RESET}"
|
|
@@ -1204,6 +1289,7 @@ restore_user_data() {
|
|
|
rm -rf "$temp_dir"
|
|
rm -rf "$temp_dir"
|
|
|
echo -e "\n${C_GREEN}✅ SUCCESS: User data restore completed.${C_RESET}"
|
|
echo -e "\n${C_GREEN}✅ SUCCESS: User data restore completed.${C_RESET}"
|
|
|
|
|
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -2994,35 +3080,51 @@ uninstall_xui_panel() {
|
|
|
fi
|
|
fi
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-show_banner() {
|
|
|
|
|
- local os_name=$(grep -oP 'PRETTY_NAME="\K[^"]+' /etc/os-release || echo "Linux")
|
|
|
|
|
- local up_time=$(uptime -p | sed 's/up //')
|
|
|
|
|
- local ram_usage=$(free -m | awk '/^Mem:/{printf "%.2f", $3*100/$2}')
|
|
|
|
|
-
|
|
|
|
|
- # Efficient CPU Load check (Load Average)
|
|
|
|
|
- local cpu_load=$(cat /proc/loadavg | awk '{print $1}')
|
|
|
|
|
-
|
|
|
|
|
- local online_users=0
|
|
|
|
|
- # Optimize online user count: Get total active sshd procs roughly (may overcount if multiple procs per session but faster)
|
|
|
|
|
- # Or just keep it if DB is small. Let's trust pgrep is okay for menu load.
|
|
|
|
|
|
|
+count_managed_online_sessions() {
|
|
|
|
|
+ if [[ ! -s "$DB_FILE" ]]; then
|
|
|
|
|
+ echo 0
|
|
|
|
|
+ return
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ local session_count
|
|
|
|
|
+ session_count=$(awk -F: 'NR==FNR { users[$1]=1; next } ($1 in users) { count++ } END { print count+0 }' "$DB_FILE" <(ps -C sshd -o user= 2>/dev/null))
|
|
|
|
|
+ [[ "$session_count" =~ ^[0-9]+$ ]] || session_count=0
|
|
|
|
|
+ echo "$session_count"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+invalidate_banner_cache() {
|
|
|
|
|
+ BANNER_CACHE_TS=0
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+refresh_banner_cache() {
|
|
|
|
|
+ local now
|
|
|
|
|
+ now=$(date +%s)
|
|
|
|
|
+ if (( BANNER_CACHE_TS > 0 && now - BANNER_CACHE_TS < BANNER_CACHE_TTL )); then
|
|
|
|
|
+ return
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ BANNER_CACHE_OS_NAME=$(grep -oP 'PRETTY_NAME="\K[^"]+' /etc/os-release 2>/dev/null || echo "Linux")
|
|
|
|
|
+ BANNER_CACHE_UP_TIME=$(uptime -p 2>/dev/null | sed 's/up //' || echo "unknown")
|
|
|
|
|
+ BANNER_CACHE_RAM_USAGE=$(free -m | awk '/^Mem:/{if($2>0){printf "%.2f", $3*100/$2}else{print "0.00"}}')
|
|
|
|
|
+ BANNER_CACHE_CPU_LOAD=$(awk '{print $1}' /proc/loadavg 2>/dev/null)
|
|
|
if [[ -s "$DB_FILE" ]]; then
|
|
if [[ -s "$DB_FILE" ]]; then
|
|
|
- while IFS=: read -r user pass expiry limit; do
|
|
|
|
|
- # Use pgrep -c for speed
|
|
|
|
|
- local count=$(pgrep -c -u "$user" sshd)
|
|
|
|
|
- online_users=$((online_users + count))
|
|
|
|
|
- done < "$DB_FILE"
|
|
|
|
|
|
|
+ BANNER_CACHE_TOTAL_USERS=$(grep -c . "$DB_FILE")
|
|
|
|
|
+ else
|
|
|
|
|
+ BANNER_CACHE_TOTAL_USERS=0
|
|
|
fi
|
|
fi
|
|
|
-
|
|
|
|
|
- local total_users=0
|
|
|
|
|
- if [[ -s "$DB_FILE" ]]; then total_users=$(grep -c . "$DB_FILE"); fi
|
|
|
|
|
-
|
|
|
|
|
|
|
+ BANNER_CACHE_ONLINE_USERS=$(count_managed_online_sessions)
|
|
|
|
|
+ BANNER_CACHE_TS=$now
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+show_banner() {
|
|
|
|
|
+ refresh_banner_cache
|
|
|
clear
|
|
clear
|
|
|
echo
|
|
echo
|
|
|
echo -e "${C_TITLE} FirewallFalcon Manager ${C_RESET}${C_DIM}| v4.0.0 Premium Edition${C_RESET}"
|
|
echo -e "${C_TITLE} FirewallFalcon Manager ${C_RESET}${C_DIM}| v4.0.0 Premium Edition${C_RESET}"
|
|
|
echo -e "${C_BLUE} ─────────────────────────────────────────────────────────${C_RESET}"
|
|
echo -e "${C_BLUE} ─────────────────────────────────────────────────────────${C_RESET}"
|
|
|
- printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "OS" "$os_name" "Uptime: $up_time"
|
|
|
|
|
- printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "Memory" "${ram_usage}% Used" "Online Sessions: ${C_WHITE}${online_users}${C_RESET}"
|
|
|
|
|
- printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "Users" "${total_users} Managed Accounts" "Sys Load (1m): ${C_GREEN}${cpu_load}${C_RESET}"
|
|
|
|
|
|
|
+ printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "OS" "$BANNER_CACHE_OS_NAME" "Uptime: $BANNER_CACHE_UP_TIME"
|
|
|
|
|
+ printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "Memory" "${BANNER_CACHE_RAM_USAGE}% Used" "Online Sessions: ${C_WHITE}${BANNER_CACHE_ONLINE_USERS}${C_RESET}"
|
|
|
|
|
+ printf " ${C_GRAY}%-10s${C_RESET} %-20s ${C_GRAY}|${C_RESET} %s\n" "Users" "${BANNER_CACHE_TOTAL_USERS} Managed Accounts" "Sys Load (1m): ${C_GREEN}${BANNER_CACHE_CPU_LOAD}${C_RESET}"
|
|
|
echo -e "${C_BLUE} ─────────────────────────────────────────────────────────${C_RESET}"
|
|
echo -e "${C_BLUE} ─────────────────────────────────────────────────────────${C_RESET}"
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -3284,6 +3386,7 @@ create_trial_account() {
|
|
|
generate_client_config "$username" "$password"
|
|
generate_client_config "$username" "$password"
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -3397,6 +3500,7 @@ bulk_create_users() {
|
|
|
echo -e "${C_YELLOW}================================================================${C_RESET}"
|
|
echo -e "${C_YELLOW}================================================================${C_RESET}"
|
|
|
echo -e "\n${C_GREEN}✅ Created $created users. Conn Limit: ${limit} | BW: ${bw_display}${C_RESET}"
|
|
echo -e "\n${C_GREEN}✅ Created $created users. Conn Limit: ${limit} | BW: ${bw_display}${C_RESET}"
|
|
|
|
|
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -3701,14 +3805,17 @@ ssh_banner_menu() {
|
|
|
read -p "👉 Enter choice: " banner_choice
|
|
read -p "👉 Enter choice: " banner_choice
|
|
|
case $banner_choice in
|
|
case $banner_choice in
|
|
|
1)
|
|
1)
|
|
|
- touch "/etc/firewallfalcon/banners_enabled"
|
|
|
|
|
- update_ssh_banners_config
|
|
|
|
|
- echo -e "\n${C_GREEN}✅ SSH Login Banner has been enabled!${C_RESET}"
|
|
|
|
|
- echo -e "${C_DIM}Users will see account info when they connect via SSH tunnel.${C_RESET}"
|
|
|
|
|
|
|
+ if setup_ssh_login_info; then
|
|
|
|
|
+ echo -e "\n${C_GREEN}✅ SSH Login Banner has been enabled!${C_RESET}"
|
|
|
|
|
+ echo -e "${C_DIM}Users will see account info when they connect via SSH tunnel.${C_RESET}"
|
|
|
|
|
+ else
|
|
|
|
|
+ echo -e "\n${C_RED}❌ Failed to enable the SSH Login Banner.${C_RESET}"
|
|
|
|
|
+ fi
|
|
|
press_enter
|
|
press_enter
|
|
|
;;
|
|
;;
|
|
|
2)
|
|
2)
|
|
|
rm -f "/etc/firewallfalcon/banners_enabled"
|
|
rm -f "/etc/firewallfalcon/banners_enabled"
|
|
|
|
|
+ invalidate_banner_cache
|
|
|
update_ssh_banners_config
|
|
update_ssh_banners_config
|
|
|
echo -e "\n${C_YELLOW}❌ SSH Login Banner has been disabled.${C_RESET}"
|
|
echo -e "\n${C_YELLOW}❌ SSH Login Banner has been disabled.${C_RESET}"
|
|
|
press_enter
|
|
press_enter
|