firewallfalcons 3 месяцев назад
Родитель
Сommit
89eea06078
1 измененных файлов с 583 добавлено и 58 удалено
  1. 583 58
      menu.sh

+ 583 - 58
menu.sh

@@ -49,6 +49,10 @@ FALCONPROXY_BINARY="/usr/local/bin/falconproxy"
 FALCONPROXY_CONFIG_FILE="$DB_DIR/falconproxy_config.conf"
 LIMITER_SCRIPT="/usr/local/bin/firewallfalcon-limiter.sh"
 LIMITER_SERVICE="/etc/systemd/system/firewallfalcon-limiter.service"
+BANDWIDTH_DIR="$DB_DIR/bandwidth"
+BANDWIDTH_SCRIPT="/usr/local/bin/firewallfalcon-bandwidth.sh"
+BANDWIDTH_SERVICE="/etc/systemd/system/firewallfalcon-bandwidth.service"
+TRIAL_CLEANUP_SCRIPT="/usr/local/bin/firewallfalcon-trial-cleanup.sh"
 
 # --- ZiVPN Variables ---
 ZIVPN_DIR="/etc/zivpn"
@@ -90,10 +94,17 @@ initial_setup() {
     mkdir -p "$DB_DIR"
     touch "$DB_FILE"
     mkdir -p "$SSL_CERT_DIR"
+    mkdir -p "$BANDWIDTH_DIR"
     
     echo -e "${C_BLUE}🔹 Configuring user limiter service...${C_RESET}"
     setup_limiter_service
     
+    echo -e "${C_BLUE}🔹 Configuring bandwidth monitoring service...${C_RESET}"
+    setup_bandwidth_service
+    
+    echo -e "${C_BLUE}🔹 Installing trial account cleanup script...${C_RESET}"
+    setup_trial_cleanup_script
+    
     if [ ! -f "$INSTALL_FLAG_FILE" ]; then
         touch "$INSTALL_FLAG_FILE"
     fi
@@ -211,13 +222,9 @@ while true; do
     # Get count of sshd processes per user in one go is hard in bash without map,
     # so we optimize the per-user check.
     
-    while IFS=: read -r user pass expiry limit; do
+    while IFS=: read -r user pass expiry limit bandwidth_gb _extra; do
         [[ -z "$user" || "$user" == \#* ]] && continue
         
-        # 1. Active Check (Skip if user has no processes to save CPU)
-        # pgrep -u is relatively cheap, but let's be smart.
-        # If connection limit is huge, we might not care.
-        
         # --- Expiry Check ---
         # Only check expiry if we have a valid expiry date
         if [[ "$expiry" != "Never" && "$expiry" != "" ]]; then
@@ -284,6 +291,185 @@ EOF
 }
 
 
+setup_bandwidth_service() {
+    mkdir -p "$BANDWIDTH_DIR"
+    cat > "$BANDWIDTH_SCRIPT" << 'BWEOF'
+#!/bin/bash
+DB_FILE="/etc/firewallfalcon/users.db"
+BW_DIR="/etc/firewallfalcon/bandwidth"
+
+mkdir -p "$BW_DIR"
+
+# Helper: ensure iptables chain exists for a user
+ensure_chain() {
+    local user="$1"
+    local uid
+    uid=$(id -u "$user" 2>/dev/null) || return 1
+    local chain="FF_BW_${user}"
+    
+    if ! iptables -L "$chain" -n &>/dev/null; then
+        iptables -N "$chain" 2>/dev/null
+        iptables -A OUTPUT -m owner --uid-owner "$uid" -j "$chain" 2>/dev/null
+        iptables -A "$chain" -j RETURN 2>/dev/null
+    fi
+}
+
+# Helper: read bytes from chain
+read_bytes() {
+    local user="$1"
+    local chain="FF_BW_${user}"
+    iptables -L "$chain" -vnx 2>/dev/null | awk '/RETURN/{print $2}' | head -1
+}
+
+# Helper: reset counter
+reset_counter() {
+    local user="$1"
+    local chain="FF_BW_${user}"
+    iptables -Z "$chain" 2>/dev/null
+}
+
+# Helper: remove chain for deleted user
+remove_chain() {
+    local user="$1"
+    local uid
+    uid=$(id -u "$user" 2>/dev/null)
+    local chain="FF_BW_${user}"
+    
+    if iptables -L "$chain" -n &>/dev/null; then
+        if [[ -n "$uid" ]]; then
+            iptables -D OUTPUT -m owner --uid-owner "$uid" -j "$chain" 2>/dev/null
+        else
+            iptables -S OUTPUT 2>/dev/null | grep "$chain" | while read -r rule; do
+                iptables $(echo "$rule" | sed 's/^-A/-D/') 2>/dev/null
+            done
+        fi
+        iptables -F "$chain" 2>/dev/null
+        iptables -X "$chain" 2>/dev/null
+    fi
+}
+
+while true; do
+    if [[ ! -f "$DB_FILE" ]]; then
+        sleep 60
+        continue
+    fi
+    
+    while IFS=: read -r user pass expiry limit bandwidth_gb _extra; do
+        [[ -z "$user" || "$user" == \#* ]] && continue
+        
+        # Skip if no bandwidth limit (0 or empty = unlimited)
+        if [[ -z "$bandwidth_gb" || "$bandwidth_gb" == "0" ]]; then
+            remove_chain "$user" 2>/dev/null
+            continue
+        fi
+        
+        # Skip if user doesn't exist on system
+        if ! id "$user" &>/dev/null; then continue; fi
+        
+        # Ensure iptables chain exists
+        ensure_chain "$user"
+        
+        # Read current counter bytes
+        current_bytes=$(read_bytes "$user")
+        [[ -z "$current_bytes" ]] && current_bytes=0
+        
+        # Read accumulated usage
+        usage_file="$BW_DIR/${user}.usage"
+        accumulated=0
+        if [[ -f "$usage_file" ]]; then
+            accumulated=$(cat "$usage_file" 2>/dev/null)
+            [[ -z "$accumulated" ]] && accumulated=0
+        fi
+        
+        # Add current counter to accumulated
+        new_total=$((accumulated + current_bytes))
+        echo "$new_total" > "$usage_file"
+        
+        # Reset iptables counter after reading
+        reset_counter "$user"
+        
+        # Convert quota to bytes (1 GB = 1073741824 bytes)
+        quota_bytes=$(awk "BEGIN {printf \"%.0f\", $bandwidth_gb * 1073741824}")
+        
+        # Lock user if over quota
+        if [[ "$new_total" -ge "$quota_bytes" ]]; then
+            if ! passwd -S "$user" 2>/dev/null | grep -q " L "; then
+                usermod -L "$user" &>/dev/null
+                killall -u "$user" -9 &>/dev/null
+            fi
+        fi
+    done < "$DB_FILE"
+    
+    sleep 30
+done
+BWEOF
+    chmod +x "$BANDWIDTH_SCRIPT"
+
+    cat > "$BANDWIDTH_SERVICE" << EOF
+[Unit]
+Description=FirewallFalcon Bandwidth Monitor
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=$BANDWIDTH_SCRIPT
+Restart=always
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+    pkill -f "firewallfalcon-bandwidth" 2>/dev/null
+
+    if ! systemctl is-active --quiet firewallfalcon-bandwidth; then
+        systemctl daemon-reload
+        systemctl enable firewallfalcon-bandwidth &>/dev/null
+        systemctl start firewallfalcon-bandwidth --no-block &>/dev/null
+    else
+        systemctl restart firewallfalcon-bandwidth --no-block &>/dev/null
+    fi
+}
+
+setup_trial_cleanup_script() {
+    cat > "$TRIAL_CLEANUP_SCRIPT" << 'TREOF'
+#!/bin/bash
+# FirewallFalcon Trial Account Auto-Cleanup
+# Usage: firewallfalcon-trial-cleanup.sh <username>
+DB_FILE="/etc/firewallfalcon/users.db"
+BW_DIR="/etc/firewallfalcon/bandwidth"
+
+username="$1"
+if [[ -z "$username" ]]; then exit 1; fi
+
+# Kill active sessions
+killall -u "$username" -9 &>/dev/null
+sleep 1
+
+# Remove iptables bandwidth chain if exists
+chain="FF_BW_${username}"
+uid=$(id -u "$username" 2>/dev/null)
+if iptables -L "$chain" -n &>/dev/null; then
+    if [[ -n "$uid" ]]; then
+        iptables -D OUTPUT -m owner --uid-owner "$uid" -j "$chain" 2>/dev/null
+    fi
+    iptables -F "$chain" 2>/dev/null
+    iptables -X "$chain" 2>/dev/null
+fi
+
+# Delete system user
+userdel -r "$username" &>/dev/null
+
+# Remove from DB
+sed -i "/^${username}:/d" "$DB_FILE"
+
+# Remove bandwidth tracking
+rm -f "$BW_DIR/${username}.usage"
+TREOF
+    chmod +x "$TRIAL_CLEANUP_SCRIPT"
+}
+
+
 generate_dns_record() {
     echo -e "\n${C_BLUE}⚙️ Generating a random domain...${C_RESET}"
     if ! command -v jq &> /dev/null; then
@@ -462,21 +648,30 @@ create_user() {
     fi
     local password=""
     while true; do
-        read -p "🔑 Enter new password: " password
+        read -p "🔑 Enter password (or press Enter for auto-generated): " password
         if [[ -z "$password" ]]; then
-            echo -e "${C_RED}❌ Password cannot be empty. Please try again.${C_RESET}"
+            password=$(head /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 8)
+            echo -e "${C_GREEN}🔑 Auto-generated password: ${C_YELLOW}$password${C_RESET}"
+            break
         else
             break
         fi
     done
     read -p "🗓️ Enter account duration (in days): " days
     if ! [[ "$days" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
-    read -p "📶 Enter simultaneous connection limit: " limit
+    read -p "📶 Enter simultaneous connection limit [1]: " limit
+    limit=${limit:-1}
     if ! [[ "$limit" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
+    read -p "📦 Enter bandwidth limit in GB (0 = unlimited) [0]: " bandwidth_gb
+    bandwidth_gb=${bandwidth_gb:-0}
+    if ! [[ "$bandwidth_gb" =~ ^[0-9]+\.?[0-9]*$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
     local expire_date
     expire_date=$(date -d "+$days days" +%Y-%m-%d)
     useradd -m -s /usr/sbin/nologin "$username"; echo "$username:$password" | chpasswd; chage -E "$expire_date" "$username"
-    echo "$username:$password:$expire_date:$limit" >> "$DB_FILE"
+    echo "$username:$password:$expire_date:$limit:$bandwidth_gb" >> "$DB_FILE"
+    
+    local bw_display="Unlimited"
+    if [[ "$bandwidth_gb" != "0" ]]; then bw_display="${bandwidth_gb} GB"; fi
     
     clear; show_banner
     echo -e "${C_GREEN}✅ User '$username' created successfully!${C_RESET}\n"
@@ -484,7 +679,8 @@ create_user() {
     echo -e "  - 🔑 Password:          ${C_YELLOW}$password${C_RESET}"
     echo -e "  - 🗓️ Expires on:        ${C_YELLOW}$expire_date${C_RESET}"
     echo -e "  - 📶 Connection Limit:  ${C_YELLOW}$limit${C_RESET}"
-    echo -e "    ${C_DIM}(Active monitoring service will enforce this limit)${C_RESET}"
+    echo -e "  - 📦 Bandwidth Limit:   ${C_YELLOW}$bw_display${C_RESET}"
+    echo -e "    ${C_DIM}(Active monitoring service will enforce these limits)${C_RESET}"
 
     # Auto-ask for config generation
     echo
@@ -538,6 +734,19 @@ delete_user() {
          echo -e "\n${C_RED}❌ Failed to delete system user '$username'.${C_RESET}"
     fi
 
+    # Clean up bandwidth tracking
+    local chain="FF_BW_${username}"
+    if iptables -L "$chain" -n &>/dev/null; then
+        local uid_val
+        uid_val=$(id -u "$username" 2>/dev/null)
+        if [[ -n "$uid_val" ]]; then
+            iptables -D OUTPUT -m owner --uid-owner "$uid_val" -j "$chain" 2>/dev/null
+        fi
+        iptables -F "$chain" 2>/dev/null
+        iptables -X "$chain" 2>/dev/null
+    fi
+    rm -f "$BANDWIDTH_DIR/${username}.usage"
+
     sed -i "/^$username:/d" "$DB_FILE"
     echo -e "${C_GREEN}✅ User '$username' has been completely removed.${C_RESET}"
 }
@@ -548,41 +757,78 @@ edit_user() {
     if [[ "$username" == "NO_USERS" ]] || [[ -z "$username" ]]; then return; fi
     while true; do
         clear; show_banner; echo -e "${C_BOLD}${C_PURPLE}--- Editing User: ${C_YELLOW}$username${C_PURPLE} ---${C_RESET}"
+        
+        # Show current user details
+        local current_line; current_line=$(grep "^$username:" "$DB_FILE")
+        local cur_pass; cur_pass=$(echo "$current_line" | cut -d: -f2)
+        local cur_expiry; cur_expiry=$(echo "$current_line" | cut -d: -f3)
+        local cur_limit; cur_limit=$(echo "$current_line" | cut -d: -f4)
+        local cur_bw; cur_bw=$(echo "$current_line" | cut -d: -f5)
+        [[ -z "$cur_bw" ]] && cur_bw="0"
+        local cur_bw_display="Unlimited"; [[ "$cur_bw" != "0" ]] && cur_bw_display="${cur_bw} GB"
+        
+        # Show bandwidth usage
+        local bw_used_display="N/A"
+        if [[ -f "$BANDWIDTH_DIR/${username}.usage" ]]; then
+            local used_bytes; used_bytes=$(cat "$BANDWIDTH_DIR/${username}.usage" 2>/dev/null)
+            if [[ -n "$used_bytes" && "$used_bytes" != "0" ]]; then
+                bw_used_display=$(awk "BEGIN {printf \"%.2f GB\", $used_bytes / 1073741824}")
+            else
+                bw_used_display="0.00 GB"
+            fi
+        fi
+        
+        echo -e "\n  ${C_DIM}Current: Pass=${C_YELLOW}$cur_pass${C_RESET}${C_DIM} Exp=${C_YELLOW}$cur_expiry${C_RESET}${C_DIM} Conn=${C_YELLOW}$cur_limit${C_RESET}${C_DIM} BW=${C_YELLOW}$cur_bw_display${C_RESET}${C_DIM} Used=${C_CYAN}$bw_used_display${C_RESET}"
         echo -e "\nSelect a detail to edit:\n"
         printf "  ${C_GREEN}[ 1]${C_RESET} %-35s\n" "🔑 Change Password"
         printf "  ${C_GREEN}[ 2]${C_RESET} %-35s\n" "🗓️ Change Expiration Date"
         printf "  ${C_GREEN}[ 3]${C_RESET} %-35s\n" "📶 Change Connection Limit"
+        printf "  ${C_GREEN}[ 4]${C_RESET} %-35s\n" "📦 Change Bandwidth Limit"
+        printf "  ${C_GREEN}[ 5]${C_RESET} %-35s\n" "🔄 Reset Bandwidth Counter"
         echo -e "\n  ${C_RED}[ 0]${C_RESET} ✅ Finish Editing"; echo; read -p "👉 Enter your choice: " edit_choice
         case $edit_choice in
             1)
                local new_pass=""
-               while true; do
-                   read -p "Enter new password: " new_pass
-                   if [[ -z "$new_pass" ]]; then
-                       echo -e "${C_RED}❌ Password cannot be empty. Please try again.${C_RESET}"
-                   else
-                       break
-                   fi
-               done
+               read -p "Enter new password (or press Enter for auto-generated): " new_pass
+               if [[ -z "$new_pass" ]]; then
+                   new_pass=$(head /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 8)
+                   echo -e "${C_GREEN}🔑 Auto-generated: ${C_YELLOW}$new_pass${C_RESET}"
+               fi
                echo "$username:$new_pass" | chpasswd
-               local current_line; current_line=$(grep "^$username:" "$DB_FILE"); local expiry; expiry=$(echo "$current_line" | cut -d: -f3); local limit; limit=$(echo "$current_line" | cut -d: -f4)
-               sed -i "s/^$username:.*/$username:$new_pass:$expiry:$limit/" "$DB_FILE"
-               echo -e "\n${C_GREEN}✅ Password for '$username' changed successfully.${C_RESET}"
-               echo -e "New Password: ${C_YELLOW}$new_pass${C_RESET}"
+               sed -i "s/^$username:.*/$username:$new_pass:$cur_expiry:$cur_limit:$cur_bw/" "$DB_FILE"
+               echo -e "\n${C_GREEN}✅ Password for '$username' changed to: ${C_YELLOW}$new_pass${C_RESET}"
                ;;
             2) read -p "Enter new duration (in days from today): " days
                if [[ "$days" =~ ^[0-9]+$ ]]; then
                    local new_expire_date; new_expire_date=$(date -d "+$days days" +%Y-%m-%d); chage -E "$new_expire_date" "$username"
-                   local current_line; current_line=$(grep "^$username:" "$DB_FILE"); local pass; pass=$(echo "$current_line" | cut -d: -f2); local limit; limit=$(echo "$current_line" | cut -d: -f4)
-                   sed -i "s/^$username:.*/$username:$pass:$new_expire_date:$limit/" "$DB_FILE"
+                   sed -i "s/^$username:.*/$username:$cur_pass:$new_expire_date:$cur_limit:$cur_bw/" "$DB_FILE"
                    echo -e "\n${C_GREEN}✅ Expiration for '$username' set to ${C_YELLOW}$new_expire_date${C_RESET}."
                else echo -e "\n${C_RED}❌ Invalid number of days.${C_RESET}"; fi ;;
             3) read -p "Enter new simultaneous connection limit: " new_limit
                if [[ "$new_limit" =~ ^[0-9]+$ ]]; then
-                   local current_line; current_line=$(grep "^$username:" "$DB_FILE"); local pass; pass=$(echo "$current_line" | cut -d: -f2); local expiry; expiry=$(echo "$current_line" | cut -d: -f3)
-                   sed -i "s/^$username:.*/$username:$pass:$expiry:$new_limit/" "$DB_FILE"
+                   sed -i "s/^$username:.*/$username:$cur_pass:$cur_expiry:$new_limit:$cur_bw/" "$DB_FILE"
                    echo -e "\n${C_GREEN}✅ Connection limit for '$username' set to ${C_YELLOW}$new_limit${C_RESET}."
                else echo -e "\n${C_RED}❌ Invalid limit.${C_RESET}"; fi ;;
+            4) read -p "Enter new bandwidth limit in GB (0 = unlimited): " new_bw
+               if [[ "$new_bw" =~ ^[0-9]+\.?[0-9]*$ ]]; then
+                   sed -i "s/^$username:.*/$username:$cur_pass:$cur_expiry:$cur_limit:$new_bw/" "$DB_FILE"
+                   local bw_msg="Unlimited"; [[ "$new_bw" != "0" ]] && bw_msg="${new_bw} GB"
+                   echo -e "\n${C_GREEN}✅ Bandwidth limit for '$username' set to ${C_YELLOW}$bw_msg${C_RESET}."
+                   # Unlock user if they were locked due to bandwidth
+                   if [[ "$new_bw" == "0" ]] || [[ -f "$BANDWIDTH_DIR/${username}.usage" ]]; then
+                       local used_bytes; used_bytes=$(cat "$BANDWIDTH_DIR/${username}.usage" 2>/dev/null || echo 0)
+                       local new_quota_bytes; new_quota_bytes=$(awk "BEGIN {printf \"%.0f\", $new_bw * 1073741824}")
+                       if [[ "$new_bw" == "0" ]] || [[ "$used_bytes" -lt "$new_quota_bytes" ]]; then
+                           usermod -U "$username" &>/dev/null
+                       fi
+                   fi
+               else echo -e "\n${C_RED}❌ Invalid bandwidth value.${C_RESET}"; fi ;;
+            5)
+               echo "0" > "$BANDWIDTH_DIR/${username}.usage"
+               # Unlock user if they were locked due to bandwidth
+               usermod -U "$username" &>/dev/null
+               echo -e "\n${C_GREEN}✅ Bandwidth counter for '$username' has been reset to 0.${C_RESET}"
+               ;;
             0) return ;;
             *) echo -e "\n${C_RED}❌ Invalid option.${C_RESET}" ;;
         esac
@@ -668,11 +914,11 @@ list_users() {
         return
     fi
     echo -e "${C_BOLD}${C_PURPLE}--- 📋 Managed Users ---${C_RESET}"
-    echo -e "${C_CYAN}======================================================================${C_RESET}"
-    printf "${C_BOLD}${C_WHITE}%-20s | %-12s | %-15s | %-20s${C_RESET}\n" "USERNAME" "EXPIRES" "CONNECTIONS" "STATUS"
-    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"
+    echo -e "${C_CYAN}-----------------------------------------------------------------------------------------${C_RESET}"
     
-    while IFS=: read -r user pass expiry limit; do
+    while IFS=: read -r user pass expiry limit bandwidth_gb _extra; do
         local online_count
         online_count=$(pgrep -u "$user" sshd | wc -l)
         
@@ -683,6 +929,20 @@ list_users() {
         plain_status=$(echo -e "$status" | sed 's/\x1b\[[0-9;]*m//g')
         
         local connection_string="$online_count / $limit"
+        
+        # Bandwidth display
+        [[ -z "$bandwidth_gb" ]] && bandwidth_gb="0"
+        local bw_string="Unlimited"
+        if [[ "$bandwidth_gb" != "0" ]]; then
+            local used_bytes=0
+            if [[ -f "$BANDWIDTH_DIR/${user}.usage" ]]; then
+                used_bytes=$(cat "$BANDWIDTH_DIR/${user}.usage" 2>/dev/null)
+                [[ -z "$used_bytes" ]] && used_bytes=0
+            fi
+            local used_gb
+            used_gb=$(awk "BEGIN {printf \"%.1f\", $used_bytes / 1073741824}")
+            bw_string="${used_gb}/${bandwidth_gb}GB"
+        fi
 
         local line_color="$C_WHITE"
         case $plain_status in
@@ -692,17 +952,18 @@ list_users() {
             *"Not Found"*) line_color="$C_DIM" ;;
         esac
 
-        printf "${line_color}%-20s ${C_RESET}| ${C_YELLOW}%-12s ${C_RESET}| ${C_CYAN}%-15s ${C_RESET}| %-20s\n" "$user" "$expiry" "$connection_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"
     done < <(sort "$DB_FILE")
-    echo -e "${C_CYAN}======================================================================${C_RESET}\n"
+    echo -e "${C_CYAN}=========================================================================================${C_RESET}\n"
 }
 
 renew_user() {
     _select_user_interface "--- 🔄 Renew a User ---"; local u=$SELECTED_USER; if [[ "$u" == "NO_USERS" || -z "$u" ]]; then return; fi
     read -p "👉 Enter number of days to extend the account: " days; if ! [[ "$days" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
     local new_expire_date; new_expire_date=$(date -d "+$days days" +%Y-%m-%d); chage -E "$new_expire_date" "$u"
-    local line; line=$(grep "^$u:" "$DB_FILE"); local pass; pass=$(echo "$line"|cut -d: -f2); local limit; limit=$(echo "$line"|cut -d: -f4)
-    sed -i "s/^$u:.*/$u:$pass:$new_expire_date:$limit/" "$DB_FILE"
+    local line; line=$(grep "^$u:" "$DB_FILE"); local pass; pass=$(echo "$line"|cut -d: -f2); local limit; limit=$(echo "$line"|cut -d: -f4); local bw; bw=$(echo "$line"|cut -d: -f5)
+    [[ -z "$bw" ]] && bw="0"
+    sed -i "s/^$u:.*/$u:$pass:$new_expire_date:$limit:$bw/" "$DB_FILE"
     echo -e "\n${C_GREEN}✅ User '$u' has been renewed. New expiration date is ${C_YELLOW}${new_expire_date}${C_RESET}."
 }
 
@@ -719,7 +980,7 @@ cleanup_expired() {
         return
     fi
     
-    while IFS=: read -r user pass expiry limit; do
+    while IFS=: read -r user pass expiry limit bandwidth_gb _extra; do
         local expiry_ts
         expiry_ts=$(date -d "$expiry" +%s 2>/dev/null || echo 0)
         
@@ -740,6 +1001,15 @@ cleanup_expired() {
         for user in "${expired_users[@]}"; do
             echo " - Deleting ${C_YELLOW}$user...${C_RESET}"
             killall -u "$user" -9 &>/dev/null
+            # Clean up bandwidth chain
+            local chain="FF_BW_${user}"
+            local uid_val; uid_val=$(id -u "$user" 2>/dev/null)
+            if iptables -L "$chain" -n &>/dev/null; then
+                [[ -n "$uid_val" ]] && iptables -D OUTPUT -m owner --uid-owner "$uid_val" -j "$chain" 2>/dev/null
+                iptables -F "$chain" 2>/dev/null
+                iptables -X "$chain" 2>/dev/null
+            fi
+            rm -f "$BANDWIDTH_DIR/${user}.usage"
             userdel -r "$user" &>/dev/null
             sed -i "/^$user:/d" "$DB_FILE"
         done
@@ -2235,7 +2505,7 @@ show_banner() {
     
     clear
     echo
-    echo -e "${C_TITLE}   FirewallFalcon Manager ${C_RESET}${C_DIM}| v3.5.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}"
     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}"
@@ -2439,6 +2709,22 @@ uninstall_script() {
     rm -f "$LIMITER_SERVICE"
     rm -f "$LIMITER_SCRIPT"
     
+    echo -e "\n${C_BLUE}🗑️ Removing bandwidth monitoring service...${C_RESET}"
+    systemctl stop firewallfalcon-bandwidth &>/dev/null
+    systemctl disable firewallfalcon-bandwidth &>/dev/null
+    rm -f "$BANDWIDTH_SERVICE"
+    rm -f "$BANDWIDTH_SCRIPT"
+    rm -f "$TRIAL_CLEANUP_SCRIPT"
+    
+    # Clean up iptables bandwidth chains
+    iptables -S OUTPUT 2>/dev/null | grep 'FF_BW_' | while read -r rule; do
+        iptables $(echo "$rule" | sed 's/^-A/-D/') 2>/dev/null
+    done
+    iptables -L 2>/dev/null | grep 'Chain FF_BW_' | awk '{print $2}' | while read -r chain; do
+        iptables -F "$chain" 2>/dev/null
+        iptables -X "$chain" 2>/dev/null
+    done
+    
     chattr -i /etc/resolv.conf &>/dev/null
 
     purge_nginx "silent"
@@ -2469,6 +2755,240 @@ uninstall_script() {
 
 # --- NEW FEATURES ---
 
+create_trial_account() {
+    clear; show_banner
+    echo -e "${C_BOLD}${C_PURPLE}--- ⏱️ Create Trial/Test Account ---${C_RESET}"
+    
+    # Ensure 'at' daemon is available
+    if ! command -v at &>/dev/null; then
+        echo -e "${C_YELLOW}⚠️ 'at' command not found. Installing...${C_RESET}"
+        apt-get update > /dev/null 2>&1 && apt-get install -y at || {
+            echo -e "${C_RED}❌ Failed to install 'at'. Cannot schedule auto-expiry.${C_RESET}"
+            return
+        }
+        systemctl enable atd &>/dev/null
+        systemctl start atd &>/dev/null
+    fi
+    
+    # Ensure atd is running
+    if ! systemctl is-active --quiet atd; then
+        systemctl start atd &>/dev/null
+    fi
+    
+    echo -e "\n${C_CYAN}Select trial duration:${C_RESET}\n"
+    printf "  ${C_GREEN}[ 1]${C_RESET} ⏱️  1 Hour\n"
+    printf "  ${C_GREEN}[ 2]${C_RESET} ⏱️  2 Hours\n"
+    printf "  ${C_GREEN}[ 3]${C_RESET} ⏱️  3 Hours\n"
+    printf "  ${C_GREEN}[ 4]${C_RESET} ⏱️  6 Hours\n"
+    printf "  ${C_GREEN}[ 5]${C_RESET} ⏱️  12 Hours\n"
+    printf "  ${C_GREEN}[ 6]${C_RESET} 📅  1 Day\n"
+    printf "  ${C_GREEN}[ 7]${C_RESET} 📅  3 Days\n"
+    printf "  ${C_GREEN}[ 8]${C_RESET} ⚙️  Custom (enter hours)\n"
+    echo -e "\n  ${C_RED}[ 0]${C_RESET} ↩️ Cancel"
+    echo
+    read -p "👉 Select duration: " dur_choice
+    
+    local duration_hours=0
+    local duration_label=""
+    case $dur_choice in
+        1) duration_hours=1;   duration_label="1 Hour" ;;
+        2) duration_hours=2;   duration_label="2 Hours" ;;
+        3) duration_hours=3;   duration_label="3 Hours" ;;
+        4) duration_hours=6;   duration_label="6 Hours" ;;
+        5) duration_hours=12;  duration_label="12 Hours" ;;
+        6) duration_hours=24;  duration_label="1 Day" ;;
+        7) duration_hours=72;  duration_label="3 Days" ;;
+        8) read -p "👉 Enter custom duration in hours: " custom_hours
+           if ! [[ "$custom_hours" =~ ^[0-9]+$ ]] || [[ "$custom_hours" -lt 1 ]]; then
+               echo -e "\n${C_RED}❌ Invalid number of hours.${C_RESET}"; return
+           fi
+           duration_hours=$custom_hours
+           duration_label="$custom_hours Hours"
+           ;;
+        0) echo -e "\n${C_YELLOW}❌ Cancelled.${C_RESET}"; return ;;
+        *) echo -e "\n${C_RED}❌ Invalid option.${C_RESET}"; return ;;
+    esac
+    
+    # Username
+    local rand_suffix=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 5)
+    local default_username="trial_${rand_suffix}"
+    read -p "👤 Username [${default_username}]: " username
+    username=${username:-$default_username}
+    
+    if id "$username" &>/dev/null || grep -q "^$username:" "$DB_FILE"; then
+        echo -e "\n${C_RED}❌ Error: User '$username' already exists.${C_RESET}"; return
+    fi
+    
+    # Password
+    local password=$(head /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 8)
+    read -p "🔑 Password [${password}]: " custom_pass
+    password=${custom_pass:-$password}
+    
+    # Connection limit
+    read -p "📶 Connection limit [1]: " limit
+    limit=${limit:-1}
+    if ! [[ "$limit" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
+    
+    # Bandwidth limit
+    read -p "📦 Bandwidth limit in GB (0 = unlimited) [0]: " bandwidth_gb
+    bandwidth_gb=${bandwidth_gb:-0}
+    if ! [[ "$bandwidth_gb" =~ ^[0-9]+\.?[0-9]*$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
+    
+    # Calculate expiry
+    local expire_date
+    if [[ "$duration_hours" -ge 24 ]]; then
+        local days=$((duration_hours / 24))
+        expire_date=$(date -d "+$days days" +%Y-%m-%d)
+    else
+        # For sub-day durations, set expiry to tomorrow to be safe (at job does the real cleanup)
+        expire_date=$(date -d "+1 day" +%Y-%m-%d)
+    fi
+    local expiry_timestamp
+    expiry_timestamp=$(date -d "+${duration_hours} hours" '+%Y-%m-%d %H:%M:%S')
+    
+    # Create the system user
+    useradd -m -s /usr/sbin/nologin "$username"
+    echo "$username:$password" | chpasswd
+    chage -E "$expire_date" "$username"
+    echo "$username:$password:$expire_date:$limit:$bandwidth_gb" >> "$DB_FILE"
+    
+    # Schedule auto-cleanup via 'at'
+    echo "$TRIAL_CLEANUP_SCRIPT $username" | at now + ${duration_hours} hours 2>/dev/null
+    
+    local bw_display="Unlimited"
+    if [[ "$bandwidth_gb" != "0" ]]; then bw_display="${bandwidth_gb} GB"; fi
+    
+    clear; show_banner
+    echo -e "${C_GREEN}✅ Trial account created successfully!${C_RESET}\n"
+    echo -e "${C_YELLOW}========================================${C_RESET}"
+    echo -e "  ⏱️  ${C_BOLD}TRIAL ACCOUNT${C_RESET}"
+    echo -e "${C_YELLOW}========================================${C_RESET}"
+    echo -e "  - 👤 Username:          ${C_YELLOW}$username${C_RESET}"
+    echo -e "  - 🔑 Password:          ${C_YELLOW}$password${C_RESET}"
+    echo -e "  - ⏱️ Duration:          ${C_CYAN}$duration_label${C_RESET}"
+    echo -e "  - 🕐 Auto-expires at:   ${C_RED}$expiry_timestamp${C_RESET}"
+    echo -e "  - 📶 Connection Limit:  ${C_YELLOW}$limit${C_RESET}"
+    echo -e "  - 📦 Bandwidth Limit:   ${C_YELLOW}$bw_display${C_RESET}"
+    echo -e "${C_YELLOW}========================================${C_RESET}"
+    echo -e "\n${C_DIM}The account will be automatically deleted when the trial expires.${C_RESET}"
+    
+    # Auto-ask for config generation
+    echo
+    read -p "👉 Generate client config for this trial user? (y/n): " gen_conf
+    if [[ "$gen_conf" == "y" || "$gen_conf" == "Y" ]]; then
+        generate_client_config "$username" "$password"
+    fi
+}
+
+view_user_bandwidth() {
+    _select_user_interface "--- 📊 View User Bandwidth ---"
+    local u=$SELECTED_USER
+    if [[ "$u" == "NO_USERS" || -z "$u" ]]; then return; fi
+    
+    clear; show_banner
+    echo -e "${C_BOLD}${C_PURPLE}--- 📊 Bandwidth Details: ${C_YELLOW}$u${C_PURPLE} ---${C_RESET}\n"
+    
+    local line; line=$(grep "^$u:" "$DB_FILE")
+    local bandwidth_gb; bandwidth_gb=$(echo "$line" | cut -d: -f5)
+    [[ -z "$bandwidth_gb" ]] && bandwidth_gb="0"
+    
+    local used_bytes=0
+    if [[ -f "$BANDWIDTH_DIR/${u}.usage" ]]; then
+        used_bytes=$(cat "$BANDWIDTH_DIR/${u}.usage" 2>/dev/null)
+        [[ -z "$used_bytes" ]] && used_bytes=0
+    fi
+    
+    local used_mb; used_mb=$(awk "BEGIN {printf \"%.2f\", $used_bytes / 1048576}")
+    local used_gb; used_gb=$(awk "BEGIN {printf \"%.3f\", $used_bytes / 1073741824}")
+    
+    echo -e "  ${C_CYAN}Data Used:${C_RESET}        ${C_WHITE}${used_gb} GB${C_RESET} (${used_mb} MB)"
+    
+    if [[ "$bandwidth_gb" == "0" ]]; then
+        echo -e "  ${C_CYAN}Bandwidth Limit:${C_RESET}  ${C_GREEN}Unlimited${C_RESET}"
+        echo -e "  ${C_CYAN}Status:${C_RESET}           ${C_GREEN}No quota restrictions${C_RESET}"
+    else
+        local quota_bytes; quota_bytes=$(awk "BEGIN {printf \"%.0f\", $bandwidth_gb * 1073741824}")
+        local percentage; percentage=$(awk "BEGIN {printf \"%.1f\", ($used_bytes / $quota_bytes) * 100}")
+        local remaining_bytes; remaining_bytes=$((quota_bytes - used_bytes))
+        if [[ "$remaining_bytes" -lt 0 ]]; then remaining_bytes=0; fi
+        local remaining_gb; remaining_gb=$(awk "BEGIN {printf \"%.3f\", $remaining_bytes / 1073741824}")
+        
+        echo -e "  ${C_CYAN}Bandwidth Limit:${C_RESET}  ${C_YELLOW}${bandwidth_gb} GB${C_RESET}"
+        echo -e "  ${C_CYAN}Remaining:${C_RESET}        ${C_WHITE}${remaining_gb} GB${C_RESET}"
+        echo -e "  ${C_CYAN}Usage:${C_RESET}            ${C_WHITE}${percentage}%${C_RESET}"
+        
+        # Progress bar
+        local bar_width=30
+        local filled; filled=$(awk "BEGIN {printf \"%.0f\", ($percentage / 100) * $bar_width}")
+        if [[ "$filled" -gt "$bar_width" ]]; then filled=$bar_width; fi
+        local empty=$((bar_width - filled))
+        local bar_color="$C_GREEN"
+        if (( $(awk "BEGIN {print ($percentage > 80)}" ) )); then bar_color="$C_RED"
+        elif (( $(awk "BEGIN {print ($percentage > 50)}" ) )); then bar_color="$C_YELLOW"
+        fi
+        printf "  ${C_CYAN}Progress:${C_RESET}         ${bar_color}["
+        for ((i=0; i<filled; i++)); do printf "█"; done
+        for ((i=0; i<empty; i++)); do printf "░"; done
+        printf "]${C_RESET} ${percentage}%%\n"
+        
+        if [[ "$used_bytes" -ge "$quota_bytes" ]]; then
+            echo -e "\n  ${C_RED}⚠️ USER HAS EXCEEDED BANDWIDTH QUOTA — ACCOUNT LOCKED${C_RESET}"
+        fi
+    fi
+}
+
+bulk_create_users() {
+    clear; show_banner
+    echo -e "${C_BOLD}${C_PURPLE}--- 👥 Bulk Create Users ---${C_RESET}"
+    
+    read -p "👉 Enter username prefix (e.g., 'user'): " prefix
+    if [[ -z "$prefix" ]]; then echo -e "\n${C_RED}❌ Prefix cannot be empty.${C_RESET}"; return; fi
+    
+    read -p "🔢 How many users to create? " count
+    if ! [[ "$count" =~ ^[0-9]+$ ]] || [[ "$count" -lt 1 ]] || [[ "$count" -gt 100 ]]; then
+        echo -e "\n${C_RED}❌ Invalid count (1-100).${C_RESET}"; return
+    fi
+    
+    read -p "🗓️ Account duration (in days): " days
+    if ! [[ "$days" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
+    
+    read -p "📶 Connection limit per user [1]: " limit
+    limit=${limit:-1}
+    if ! [[ "$limit" =~ ^[0-9]+$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
+    
+    read -p "📦 Bandwidth limit in GB per user (0 = unlimited) [0]: " bandwidth_gb
+    bandwidth_gb=${bandwidth_gb:-0}
+    if ! [[ "$bandwidth_gb" =~ ^[0-9]+\.?[0-9]*$ ]]; then echo -e "\n${C_RED}❌ Invalid number.${C_RESET}"; return; fi
+    
+    local expire_date
+    expire_date=$(date -d "+$days days" +%Y-%m-%d)
+    local bw_display="Unlimited"; [[ "$bandwidth_gb" != "0" ]] && bw_display="${bandwidth_gb} GB"
+    
+    echo -e "\n${C_BLUE}⚙️ Creating $count users with prefix '${prefix}'...${C_RESET}\n"
+    echo -e "${C_YELLOW}================================================================${C_RESET}"
+    printf "${C_BOLD}${C_WHITE}%-20s | %-15s | %-12s${C_RESET}\n" "USERNAME" "PASSWORD" "EXPIRES"
+    echo -e "${C_YELLOW}----------------------------------------------------------------${C_RESET}"
+    
+    local created=0
+    for ((i=1; i<=count; i++)); do
+        local username="${prefix}${i}"
+        if id "$username" &>/dev/null || grep -q "^$username:" "$DB_FILE"; then
+            echo -e "${C_RED}  ⚠️ Skipping '$username' — already exists${C_RESET}"
+            continue
+        fi
+        local password=$(head /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 8)
+        useradd -m -s /usr/sbin/nologin "$username"
+        echo "$username:$password" | chpasswd
+        chage -E "$expire_date" "$username"
+        echo "$username:$password:$expire_date:$limit:$bandwidth_gb" >> "$DB_FILE"
+        printf "  ${C_GREEN}%-20s${C_RESET} | ${C_YELLOW}%-15s${C_RESET} | ${C_CYAN}%-12s${C_RESET}\n" "$username" "$password" "$expire_date"
+        created=$((created + 1))
+    done
+    
+    echo -e "${C_YELLOW}================================================================${C_RESET}"
+    echo -e "\n${C_GREEN}✅ Created $created users. Conn Limit: ${limit} | BW: ${bw_display}${C_RESET}"
+}
+
 generate_client_config() {
     local user=$1
     local pass=$2
@@ -2817,22 +3337,24 @@ main_menu() {
         show_banner
         
         echo
-        echo -e "   ${C_TITLE}═══════════════[ ${C_BOLD}👤 USER MANAGEMENT ${C_RESET}${C_TITLE}]═══════════════${C_RESET}"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "1" "Create New User" "5" "Unlock User Account"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "2" "Delete User" "6" "Edit User Details"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "3" "Renew User Account" "7" "List Managed Users"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "4" "Lock User Account" "8" "Generate Client Config"
+        echo -e "   ${C_TITLE}═══════════════════[ ${C_BOLD}👤 USER MANAGEMENT ${C_RESET}${C_TITLE}]═══════════════════${C_RESET}"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "1" "✨ Create New User" "6" "✏️  Edit User Details"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "2" "🗑️  Delete User" "7" "📋 List Managed Users"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "3" "🔄 Renew User Account" "8" "📱 Generate Client Config"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "4" "🔒 Lock User Account" "9" "⏱️  Create Trial Account"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "5" "🔓 Unlock User Account" "10" "📊 View User Bandwidth"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "11" "👥 Bulk Create Users"
         
         echo
-        echo -e "   ${C_TITLE}════════════[ ${C_BOLD}🌐 VPN & PROTOCOLS ${C_RESET}${C_TITLE}]═════════════${C_RESET}"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "9" "Protocol Manager" "11" "Traffic Monitor (Lite)"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "10" "DT Proxy Manager" "12" "Block Torrent (Anti-P2P)"
+        echo -e "   ${C_TITLE}══════════════[ ${C_BOLD}🌐 VPN & PROTOCOLS ${C_RESET}${C_TITLE}]═══════════════${C_RESET}"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "12" "🔌 Protocol Manager" "14" "📈 Traffic Monitor (Lite)"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "13" "DT Proxy Manager" "15" "🚫 Block Torrent (Anti-P2P)"
 
         echo
-        echo -e "   ${C_TITLE}════════════[ ${C_BOLD}⚙️ SYSTEM SETTINGS ${C_RESET}${C_TITLE}]═════════════${C_RESET}"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "13" "CloudFlare Free Domain" "16" "Backup User Data"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "14" "SSH Banner Config" "17" "Restore User Data"
-        printf "     ${C_CHOICE}[%2s]${C_RESET} %-25s ${C_CHOICE}[%2s]${C_RESET} %-25s\n" "15" "Auto-Reboot Task" "18" "Cleanup Expired Users"
+        echo -e "   ${C_TITLE}══════════════[ ${C_BOLD}⚙️ SYSTEM SETTINGS ${C_RESET}${C_TITLE}]═══════════════${C_RESET}"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "16" "☁️  CloudFlare Free Domain" "19" "💾 Backup User Data"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "17" "🎨 SSH Banner Config" "20" "📥 Restore User Data"
+        printf "     ${C_CHOICE}[%2s]${C_RESET} %-28s ${C_CHOICE}[%2s]${C_RESET} %-28s\n" "18" "🔄 Auto-Reboot Task" "21" "🧹 Cleanup Expired Users"
 
         echo
         echo -e "   ${C_DANGER}═══════════════════[ ${C_BOLD}🔥 DANGER ZONE ${C_RESET}${C_DANGER}]═══════════════════${C_RESET}"
@@ -2848,18 +3370,21 @@ main_menu() {
             6) edit_user; press_enter ;;
             7) list_users; press_enter ;;
             8) client_config_menu; press_enter ;;
+            9) create_trial_account; press_enter ;;
+            10) view_user_bandwidth; press_enter ;;
+            11) bulk_create_users; press_enter ;;
             
-            9) protocol_menu ;;
-            10) dt_proxy_menu ;;
-            11) traffic_monitor_menu ;;
-            12) torrent_block_menu ;;
+            12) protocol_menu ;;
+            13) dt_proxy_menu ;;
+            14) traffic_monitor_menu ;;
+            15) torrent_block_menu ;;
             
-            13) dns_menu; press_enter ;;
-            14) ssh_banner_menu ;;
-            15) auto_reboot_menu ;;
-            16) backup_user_data; press_enter ;;
-            17) restore_user_data; press_enter ;;
-            18) cleanup_expired; press_enter ;;
+            16) dns_menu; press_enter ;;
+            17) ssh_banner_menu ;;
+            18) auto_reboot_menu ;;
+            19) backup_user_data; press_enter ;;
+            20) restore_user_data; press_enter ;;
+            21) cleanup_expired; press_enter ;;
             
             99) uninstall_script ;;
             0) exit 0 ;;