From 64905cb844d06c0cf12442dd75f7d453ae84e3f9 Mon Sep 17 00:00:00 2001 From: Thomas Ciesla Date: Fri, 9 Jan 2026 16:22:01 +0100 Subject: [PATCH] and again a fix --- jtl-wafi-agent.py | 108 +++++++++++++++++++++++++++++++++------------- 1 file changed, 77 insertions(+), 31 deletions(-) diff --git a/jtl-wafi-agent.py b/jtl-wafi-agent.py index 3b5598a..cb701eb 100644 --- a/jtl-wafi-agent.py +++ b/jtl-wafi-agent.py @@ -1588,27 +1588,49 @@ def _load_initial_request_details(tracker: LiveStatsTracker, shop: str, max_line except: pass - # Path extrahieren - path = '/' - if 'Path: ' in line: - path = line.split('Path: ')[1].split(' |')[0].strip() - elif 'URI: ' in line: - path = line.split('URI: ')[1].split(' |')[0].strip() - - # User-Agent extrahieren + # User-Agent extrahieren (muss VOR URI gemacht werden wegen Format) user_agent = '' - if 'UA: ' in line: - user_agent = line.split('UA: ')[1].split(' |')[0].strip() + if ' | UA: ' in line: + user_agent = line.split(' | UA: ')[1].strip() elif 'User-Agent: ' in line: user_agent = line.split('User-Agent: ')[1].split(' |')[0].strip() + # Path/URI extrahieren + path = '/' + if 'URI: ' in line: + # Format: ... | URI: /path | UA: ... + uri_part = line.split('URI: ')[1] + # Falls UA danach kommt, abschneiden + if ' | UA: ' in uri_part: + path = uri_part.split(' | UA: ')[0].strip() + else: + path = uri_part.strip() + elif 'Path: ' in line: + path = line.split('Path: ')[1].split(' |')[0].strip() + # Bot/Blocked erkennen is_bot = any(x in line for x in ['BOT: ', 'BOT:', 'BLOCKED_BOT:', 'MONITOR_BOT:', 'BANNED_BOT:']) is_blocked = any(x in line for x in ['BANNED', 'BLOCKED']) is_404 = '404' in line - # Request aufzeichnen (mit originalem Zeitstempel falls vorhanden) - tracker.record_request(ip, path, is_bot, is_blocked, is_404, user_agent, timestamp) + # NUR ip_request_details füllen (nicht die Rolling-Window Stats!) + # Die Rolling-Window-Stats werden nur durch Live-Logs gefüllt + if ip not in tracker.ip_request_details: + tracker.ip_request_details[ip] = [] + + # Timestamp verwenden (oder aktuelle Zeit wenn nicht vorhanden) + ts = timestamp if timestamp else time.time() + + tracker.ip_request_details[ip].append({ + 'ts': ts, + 'path': path, + 'ua': user_agent, + 'blocked': is_blocked + }) + + # Limitieren auf max_request_details + if len(tracker.ip_request_details[ip]) > tracker.max_request_details: + tracker.ip_request_details[ip] = tracker.ip_request_details[ip][-tracker.max_request_details:] except Exception: continue @@ -2076,7 +2098,7 @@ if (!$is_whitelisted && file_exists($ip_ban_file)) {{ // Whitelisted IPs skip all rate limiting if ($is_whitelisted) {{ $timestamp = date('Y-m-d H:i:s'); - @file_put_contents($log_file, "[$timestamp] WHITELISTED | IP: $visitor_ip | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] WHITELISTED | IP: $visitor_ip | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); return; }} @@ -2209,7 +2231,7 @@ if ($count > $rate_limit) {{ // === STEP 5: Under limit - log and ALLOW through === $timestamp = date('Y-m-d H:i:s'); $uri = $_SERVER['REQUEST_URI'] ?? '/'; -@file_put_contents($log_file, "[$timestamp] BOT: $detected_bot | IP: $visitor_ip | Count: $count/$rate_limit | URI: $uri\\n", FILE_APPEND | LOCK_EX); +@file_put_contents($log_file, "[$timestamp] BOT: $detected_bot | IP: $visitor_ip | Count: $count/$rate_limit | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); // === STEP 6: Probabilistic cleanup === if (rand(1, $cleanup_probability) === 1) {{ @@ -2402,9 +2424,9 @@ $timestamp = date('Y-m-d H:i:s'); $uri = $_SERVER['REQUEST_URI'] ?? '/'; if ($detected_bot !== null) {{ - @file_put_contents($log_file, "[$timestamp] MONITOR_BOT: $detected_bot | IP: $visitor_ip | Country: $country | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] MONITOR_BOT: $detected_bot | IP: $visitor_ip | Country: $country | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); }} else {{ - @file_put_contents($log_file, "[$timestamp] MONITOR_HUMAN | IP: $visitor_ip | Country: $country | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] MONITOR_HUMAN | IP: $visitor_ip | Country: $country | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); }} // === ALLOW REQUEST THROUGH - NO BLOCKING === @@ -2530,7 +2552,7 @@ if (!$is_whitelisted && file_exists($ip_ban_file)) {{ // Whitelisted IPs skip all rate limiting if ($is_whitelisted) {{ $timestamp = date('Y-m-d H:i:s'); - @file_put_contents($log_file, "[$timestamp] WHITELISTED | IP: $visitor_ip | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] WHITELISTED | IP: $visitor_ip | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); return; }} @@ -2689,7 +2711,7 @@ if ($detected_bot !== null && $bot_mode) {{ }} // Bot under limit - log and allow - @file_put_contents($log_file, "[$timestamp] BOT: $detected_bot | IP: $visitor_ip | Country: $country | Count: $count/$bot_rate_limit | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] BOT: $detected_bot | IP: $visitor_ip | Country: $country | Count: $count/$bot_rate_limit | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); // Cleanup (probabilistic) if (rand(1, $cleanup_probability) === 1) {{ @@ -2712,7 +2734,7 @@ if ($detected_bot === null && $country_mode) {{ // Check if country is unlimited (still log but don't rate-limit) if (in_array($country_lower, $unlimited_countries)) {{ - @file_put_contents($log_file, "[$timestamp] HUMAN | IP: $visitor_ip | Country: $country | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] HUMAN | IP: $visitor_ip | Country: $country | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); return; // Unlimited country - allow through }} @@ -2776,7 +2798,7 @@ if ($detected_bot === null && $country_mode) {{ }} // Human under limit - log and allow - @file_put_contents($log_file, "[$timestamp] HUMAN | IP: $visitor_ip | Country: $country | Count: $count/$country_rate_limit | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] HUMAN | IP: $visitor_ip | Country: $country | Count: $count/$country_rate_limit | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); // Cleanup (probabilistic) if (rand(1, $cleanup_probability) === 1) {{ @@ -2794,9 +2816,9 @@ if ($detected_bot === null && $country_mode) {{ // === STEP 5: No rate-limiting active, just log === if ($detected_bot !== null) {{ - @file_put_contents($log_file, "[$timestamp] BOT: $detected_bot | IP: $visitor_ip | Country: $country | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] BOT: $detected_bot | IP: $visitor_ip | Country: $country | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); }} else {{ - @file_put_contents($log_file, "[$timestamp] HUMAN | IP: $visitor_ip | Country: $country | URI: $uri\\n", FILE_APPEND | LOCK_EX); + @file_put_contents($log_file, "[$timestamp] HUMAN | IP: $visitor_ip | Country: $country | URI: $uri | UA: $user_agent\\n", FILE_APPEND | LOCK_EX); }} return; @@ -3976,18 +3998,26 @@ class JTLWAFiAgent: if 'IP: ' in line: ip = line.split('IP: ')[1].split(' |')[0].strip() - # Path extrahieren - path = '/' - if 'Path: ' in line: - path = line.split('Path: ')[1].split(' |')[0].strip() - - # User-Agent extrahieren + # User-Agent extrahieren (muss VOR URI gemacht werden wegen Format) user_agent = '' - if 'UA: ' in line: - user_agent = line.split('UA: ')[1].split(' |')[0].strip() + if ' | UA: ' in line: + user_agent = line.split(' | UA: ')[1].strip() elif 'User-Agent: ' in line: user_agent = line.split('User-Agent: ')[1].split(' |')[0].strip() + # Path/URI extrahieren + path = '/' + if 'URI: ' in line: + # Format: ... | URI: /path | UA: ... + uri_part = line.split('URI: ')[1] + # Falls UA danach kommt, abschneiden + if ' | UA: ' in uri_part: + path = uri_part.split(' | UA: ')[0].strip() + else: + path = uri_part.strip() + elif 'Path: ' in line: + path = line.split('Path: ')[1].split(' |')[0].strip() + # Bot/Human erkennen is_bot = any(x in line for x in ['BOT: ', 'BOT:', 'BLOCKED_BOT:', 'MONITOR_BOT:', 'BANNED_BOT:']) @@ -4235,6 +4265,8 @@ class JTLWAFiAgent: async def _handle_deactivate_command(self, data: Dict[str, Any]): """Verarbeitet deactivate-Command.""" + global _shop_stats_trackers + command_id = data.get('command_id', 'unknown') shop = data.get('shop') restart_fpm = data.get('restart_fpm', False) @@ -4245,6 +4277,20 @@ class JTLWAFiAgent: success = deactivate_blocking(shop, silent=True) if success: + # Log-File löschen + log_file = os.path.join(VHOSTS_DIR, shop, 'httpdocs', SHOP_LOG_FILE) + if os.path.isfile(log_file): + try: + os.remove(log_file) + logger.info(f"Log-File gelöscht: {log_file}") + except Exception as e: + logger.warning(f"Konnte Log-File nicht löschen: {e}") + + # Stats-Tracker für diesen Shop löschen + if shop in _shop_stats_trackers: + del _shop_stats_trackers[shop] + logger.info(f"Stats-Tracker für {shop} gelöscht") + # PHP-FPM Restart wenn gewünscht fpm_result = None if restart_fpm: @@ -4254,7 +4300,7 @@ class JTLWAFiAgent: else: logger.warning(f"PHP-FPM Restart fehlgeschlagen: {fpm_result['message']}") - message = f'Shop {shop} deaktiviert' + message = f'Shop {shop} deaktiviert (Logs & Stats gelöscht)' if fpm_result: message += f' | FPM: {fpm_result["message"]}'