فهرست منبع

Update menu.sh

firewallfalcons 3 ماه پیش
والد
کامیت
35e85550f9
1فایلهای تغییر یافته به همراه91 افزوده شده و 171 حذف شده
  1. 91 171
      menu.sh

+ 91 - 171
menu.sh

@@ -204,12 +204,15 @@ check_and_free_ports() {
 }
 
 setup_limiter_service() {
-    # Updated logic: No logging, smart 120s lockout
+    # Combined limiter + bandwidth monitoring
     cat > "$LIMITER_SCRIPT" << 'EOF'
 #!/bin/bash
 DB_FILE="/etc/firewallfalcon/users.db"
+BW_DIR="/etc/firewallfalcon/bandwidth"
+PID_DIR="$BW_DIR/pidtrack"
+
+mkdir -p "$BW_DIR" "$PID_DIR"
 
-# Loop continuously with optimized sleep
 while true; do
     if [[ ! -f "$DB_FILE" ]]; then
         sleep 30
@@ -218,15 +221,10 @@ while true; do
     
     current_ts=$(date +%s)
     
-    # Cache active users to minimize pgrep calls inside loop
-    # 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 bandwidth_gb _extra; do
         [[ -z "$user" || "$user" == \#* ]] && continue
         
         # --- Expiry Check ---
-        # Only check expiry if we have a valid expiry date
         if [[ "$expiry" != "Never" && "$expiry" != "" ]]; then
              expiry_ts=$(date -d "$expiry" +%s 2>/dev/null || echo 0)
              if [[ $expiry_ts -lt $current_ts && $expiry_ts -ne 0 ]]; then
@@ -239,7 +237,6 @@ while true; do
         fi
         
         # --- Connection Limit Check ---
-        # Optimization: pgrep -c is faster than pipe to wc
         online_count=$(pgrep -c -u "$user" sshd)
         if ! [[ "$limit" =~ ^[0-9]+$ ]]; then limit=1; fi
         
@@ -252,214 +249,124 @@ while true; do
                 killall -u "$user" -9 &>/dev/null
             fi
         fi
-    done < "$DB_FILE"
-    
-    # Sleep increased to 25 seconds to reduce CPU load
-    sleep 25
-done
-EOF
-    chmod +x "$LIMITER_SCRIPT"
-
-    cat > "$LIMITER_SERVICE" << EOF
-[Unit]
-Description=FirewallFalcon Active User Limiter
-After=network.target
-
-[Service]
-Type=simple
-ExecStart=$LIMITER_SCRIPT
-Restart=always
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-
-    # Force kill any old limiter process to prevent systemctl restart hanging
-    pkill -f "firewallfalcon-limiter" 2>/dev/null
-
-    if ! systemctl is-active --quiet firewallfalcon-limiter; then
-        systemctl daemon-reload
-        systemctl enable firewallfalcon-limiter &>/dev/null
-        systemctl start firewallfalcon-limiter --no-block &>/dev/null
         
-    else
-        # Restart if already running to apply new logic
-        systemctl restart firewallfalcon-limiter --no-block &>/dev/null
+        # --- Bandwidth Check ---
+        [[ -z "$bandwidth_gb" || "$bandwidth_gb" == "0" ]] && continue
         
-    fi
-}
-
-
-setup_bandwidth_service() {
-    mkdir -p "$BANDWIDTH_DIR"
-    cat > "$BANDWIDTH_SCRIPT" << 'BWEOF'
-#!/bin/bash
-# FirewallFalcon Bandwidth Monitor v4
-
-DB_FILE="/etc/firewallfalcon/users.db"
-BW_DIR="/etc/firewallfalcon/bandwidth"
-PID_DIR="$BW_DIR/pidtrack"
-LOG="/tmp/ff-bw-debug.log"
-
-mkdir -p "$BW_DIR" "$PID_DIR"
-
-# APPEND log (don't overwrite on restart)
-echo "" >> "$LOG"
-echo "=== BW Monitor v4 started $(date) ===" >> "$LOG"
-
-# Trap errors
-trap 'echo "[$(date +%H:%M:%S)] CRASHED at line $LINENO: $BASH_COMMAND" >> "$LOG"' ERR
-
-get_bytes() {
-    # Read rchar+wchar from /proc/$1/io
-    local f="/proc/$1/io"
-    if [ ! -r "$f" ]; then echo 0; return; fi
-    local r w
-    r=$(grep '^rchar:' "$f" 2>/dev/null | awk '{print $2}')
-    w=$(grep '^wchar:' "$f" 2>/dev/null | awk '{print $2}')
-    [ -z "$r" ] && r=0
-    [ -z "$w" ] && w=0
-    echo $((r + w))
-}
-
-while true; do
-    if [ ! -f "$DB_FILE" ]; then
-        sleep 30
-        continue
-    fi
-
-    while IFS=: read -r user pass expiry limit bwlimit rest; do
-        # Skip empty/comments
-        [ -z "$user" ] && continue
-        case "$user" in \#*) continue ;; esac
-
-        # Skip if no bandwidth limit
-        [ -z "$bwlimit" ] && continue
-        [ "$bwlimit" = "0" ] && continue
-
-        # Skip if user doesn't exist
-        id "$user" >/dev/null 2>&1 || continue
-
+        # Get user UID
         user_uid=$(id -u "$user" 2>/dev/null)
-        [ -z "$user_uid" ] && continue
-
-        # --- Find sshd PIDs for this user ---
+        [[ -z "$user_uid" ]] && continue
+        
+        # Find sshd PIDs for this user via loginuid
         pids=""
-
-        # Method 1: pgrep direct match
+        
+        # Method 1: pgrep
         m1=$(pgrep -u "$user" sshd 2>/dev/null | tr '\n' ' ')
         pids="$m1"
-
-        # Method 2: loginuid scan (catches privsep processes)
+        
+        # Method 2: loginuid scan
         for p in /proc/[0-9]*/loginuid; do
-            [ ! -f "$p" ] && continue
+            [[ ! -f "$p" ]] && continue
             luid=$(cat "$p" 2>/dev/null)
-            [ -z "$luid" ] && continue
-            [ "$luid" = "4294967295" ] && continue
-            [ "$luid" != "$user_uid" ] && continue
-
+            [[ -z "$luid" || "$luid" == "4294967295" ]] && continue
+            [[ "$luid" != "$user_uid" ]] && continue
+            
             pid_dir=$(dirname "$p")
             pid_num=$(basename "$pid_dir")
-
-            # Must be sshd
+            
             cname=$(cat "$pid_dir/comm" 2>/dev/null)
-            [ "$cname" != "sshd" ] && continue
-
-            # Skip main daemon (ppid=1)
-            ppid=$(grep '^PPid:' "$pid_dir/status" 2>/dev/null | awk '{print $2}')
-            [ "$ppid" = "1" ] && continue
-
+            [[ "$cname" != "sshd" ]] && continue
+            
+            ppid_val=$(awk '/^PPid:/{print $2}' "$pid_dir/status" 2>/dev/null)
+            [[ "$ppid_val" == "1" ]] && continue
+            
             pids="$pids $pid_num"
         done
-
-        # Deduplicate PIDs
+        
+        # Deduplicate
         pids=$(echo "$pids" | tr ' ' '\n' | sort -u | grep -v '^$' | tr '\n' ' ')
-
+        
         # Read accumulated usage
         usagefile="$BW_DIR/${user}.usage"
         accumulated=0
-        if [ -f "$usagefile" ]; then
+        if [[ -f "$usagefile" ]]; then
             accumulated=$(cat "$usagefile" 2>/dev/null)
-            case "$accumulated" in
-                ''|*[!0-9]*) accumulated=0 ;;
-            esac
+            if ! [[ "$accumulated" =~ ^[0-9]+$ ]]; then accumulated=0; fi
         fi
-
-        echo "[$(date +%H:%M:%S)] user=$user uid=$user_uid bw=${bwlimit}GB acc=$accumulated pids=[$pids]" >> "$LOG"
-
-        if [ -z "$pids" ]; then
-            # No active sessions, clean up stale pid files
+        
+        if [[ -z "$pids" ]]; then
             rm -f "$PID_DIR/${user}__"*.last 2>/dev/null
             continue
         fi
-
+        
         delta_total=0
-
+        
         for pid in $pids; do
-            [ -z "$pid" ] && continue
-            cur=$(get_bytes "$pid")
+            [[ -z "$pid" ]] && continue
+            io_file="/proc/$pid/io"
+            if [[ -r "$io_file" ]]; then
+                rchar=$(awk '/^rchar:/{print $2}' "$io_file" 2>/dev/null)
+                wchar=$(awk '/^wchar:/{print $2}' "$io_file" 2>/dev/null)
+                [[ -z "$rchar" ]] && rchar=0
+                [[ -z "$wchar" ]] && wchar=0
+                cur=$((rchar + wchar))
+            else
+                cur=0
+            fi
+            
             pidfile="$PID_DIR/${user}__${pid}.last"
-
-            if [ -f "$pidfile" ]; then
+            
+            if [[ -f "$pidfile" ]]; then
                 prev=$(cat "$pidfile" 2>/dev/null)
-                case "$prev" in ''|*[!0-9]*) prev=0 ;; esac
-
-                if [ "$cur" -ge "$prev" ] 2>/dev/null; then
+                if ! [[ "$prev" =~ ^[0-9]+$ ]]; then prev=0; fi
+                
+                if [[ "$cur" -ge "$prev" ]]; then
                     d=$((cur - prev))
                 else
                     d=$cur
                 fi
                 delta_total=$((delta_total + d))
             fi
-            # Save current (also serves as baseline for first-seen PIDs)
             echo "$cur" > "$pidfile"
         done
-
+        
         # Clean up dead PID files
-        for f in "$PID_DIR/${user}__"*.last 2>/dev/null; do
-            [ ! -f "$f" ] && continue
-            fpid=$(basename "$f" .last | sed "s/^${user}__//")
-            if [ ! -d "/proc/$fpid" ]; then
-                rm -f "$f"
-            fi
+        for f in "$PID_DIR/${user}__"*.last; do
+            [[ ! -f "$f" ]] && continue
+            fpid=$(basename "$f" .last)
+            fpid=${fpid#${user}__}
+            [[ ! -d "/proc/$fpid" ]] && rm -f "$f"
         done
-
+        
         # Update total
         new_total=$((accumulated + delta_total))
         echo "$new_total" > "$usagefile"
-
-        if [ "$delta_total" -gt 0 ] 2>/dev/null; then
-            echo "[$(date +%H:%M:%S)]   delta=$delta_total new_total=$new_total" >> "$LOG"
-        fi
-
-        # Check quota (convert GB to bytes)
-        quota_bytes=$(awk "BEGIN {printf \"%.0f\", $bwlimit * 1073741824}")
-
-        if [ "$new_total" -ge "$quota_bytes" ] 2>/dev/null; then
-            locked=$(passwd -S "$user" 2>/dev/null | grep -c " L ")
-            if [ "$locked" = "0" ]; then
-                usermod -L "$user" 2>/dev/null
-                killall -u "$user" -9 2>/dev/null
-                echo "[$(date +%H:%M:%S)]   *** LOCKED $user ($new_total >= $quota_bytes)" >> "$LOG"
+        
+        # Check quota
+        quota_bytes=$(awk "BEGIN {printf \"%.0f\", $bandwidth_gb * 1073741824}")
+        
+        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 15
 done
-BWEOF
-    chmod +x "$BANDWIDTH_SCRIPT"
+EOF
+    chmod +x "$LIMITER_SCRIPT"
 
-    cat > "$BANDWIDTH_SERVICE" << EOF
+    cat > "$LIMITER_SERVICE" << EOF
 [Unit]
-Description=FirewallFalcon Bandwidth Monitor
+Description=FirewallFalcon Active User Limiter
 After=network.target
 
 [Service]
 Type=simple
-ExecStart=$BANDWIDTH_SCRIPT
+ExecStart=$LIMITER_SCRIPT
 Restart=always
 RestartSec=5
 
@@ -467,15 +374,28 @@ RestartSec=5
 WantedBy=multi-user.target
 EOF
 
-    pkill -f "firewallfalcon-bandwidth" 2>/dev/null
+    pkill -f "firewallfalcon-limiter" 2>/dev/null
 
-    if ! systemctl is-active --quiet firewallfalcon-bandwidth; then
+    if ! systemctl is-active --quiet firewallfalcon-limiter; then
         systemctl daemon-reload
-        systemctl enable firewallfalcon-bandwidth &>/dev/null
-        systemctl start firewallfalcon-bandwidth --no-block &>/dev/null
+        systemctl enable firewallfalcon-limiter &>/dev/null
+        systemctl start firewallfalcon-limiter --no-block &>/dev/null
+        
     else
-        systemctl restart firewallfalcon-bandwidth --no-block &>/dev/null
+        systemctl restart firewallfalcon-limiter --no-block &>/dev/null
+        
+    fi
+}
+
+setup_bandwidth_service() {
+    mkdir -p "$BANDWIDTH_DIR"
+    # Bandwidth monitoring is now integrated into the limiter service above.
+    # Stop the old standalone bandwidth service if it exists.
+    if systemctl is-active --quiet firewallfalcon-bandwidth 2>/dev/null; then
+        systemctl stop firewallfalcon-bandwidth &>/dev/null
+        systemctl disable firewallfalcon-bandwidth &>/dev/null
     fi
+    rm -f "$BANDWIDTH_SERVICE" "$BANDWIDTH_SCRIPT" 2>/dev/null
 }
 
 setup_trial_cleanup_script() {