geoip_shop_manager.py aktualisiert
This commit is contained in:
@@ -771,7 +771,9 @@ $bot_hash = md5($detected_bot);
|
|||||||
// === STEP 1: Check if this bot-type is banned ===
|
// === STEP 1: Check if this bot-type is banned ===
|
||||||
$ban_file = "$bans_dir/$bot_hash.ban";
|
$ban_file = "$bans_dir/$bot_hash.ban";
|
||||||
if (file_exists($ban_file)) {{
|
if (file_exists($ban_file)) {{
|
||||||
$ban_until = (int)@file_get_contents($ban_file);
|
$ban_content = @file_get_contents($ban_file);
|
||||||
|
$ban_parts = explode('|', $ban_content, 2);
|
||||||
|
$ban_until = (int)$ban_parts[0];
|
||||||
if (time() < $ban_until) {{
|
if (time() < $ban_until) {{
|
||||||
// Bot-type is banned - log and block
|
// Bot-type is banned - log and block
|
||||||
$timestamp = date('Y-m-d H:i:s');
|
$timestamp = date('Y-m-d H:i:s');
|
||||||
@@ -823,9 +825,9 @@ if (file_exists($count_file)) {{
|
|||||||
|
|
||||||
// === STEP 3: Check if limit exceeded ===
|
// === STEP 3: Check if limit exceeded ===
|
||||||
if ($count > $rate_limit) {{
|
if ($count > $rate_limit) {{
|
||||||
// Create ban for this bot-type
|
// Create ban for this bot-type (store timestamp|botname)
|
||||||
$ban_until = $current_time + $ban_duration;
|
$ban_until = $current_time + $ban_duration;
|
||||||
@file_put_contents($ban_file, $ban_until, LOCK_EX);
|
@file_put_contents($ban_file, "$ban_until|$detected_bot", LOCK_EX);
|
||||||
|
|
||||||
// Log the ban
|
// Log the ban
|
||||||
$timestamp = date('Y-m-d H:i:s');
|
$timestamp = date('Y-m-d H:i:s');
|
||||||
@@ -847,7 +849,9 @@ $uri = $_SERVER['REQUEST_URI'] ?? '/';
|
|||||||
if (rand(1, $cleanup_probability) === 1) {{
|
if (rand(1, $cleanup_probability) === 1) {{
|
||||||
$now = time();
|
$now = time();
|
||||||
foreach (glob("$bans_dir/*.ban") as $f) {{
|
foreach (glob("$bans_dir/*.ban") as $f) {{
|
||||||
$ban_time = (int)@file_get_contents($f);
|
$ban_content = @file_get_contents($f);
|
||||||
|
$ban_parts = explode('|', $ban_content, 2);
|
||||||
|
$ban_time = (int)$ban_parts[0];
|
||||||
if ($now > $ban_time) @unlink($f);
|
if ($now > $ban_time) @unlink($f);
|
||||||
}}
|
}}
|
||||||
foreach (glob("$counts_dir/*.count") as $f) {{
|
foreach (glob("$counts_dir/*.count") as $f) {{
|
||||||
@@ -1680,12 +1684,13 @@ def get_shop_log_stats(shop):
|
|||||||
if ban_file.endswith('.ban'):
|
if ban_file.endswith('.ban'):
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(bans_dir, ban_file), 'r') as f:
|
with open(os.path.join(bans_dir, ban_file), 'r') as f:
|
||||||
ban_until = int(f.read().strip())
|
content = f.read().strip()
|
||||||
|
parts = content.split('|', 1)
|
||||||
|
ban_until = int(parts[0])
|
||||||
|
bot_name = parts[1] if len(parts) > 1 else "Unbekannt"
|
||||||
if now < ban_until:
|
if now < ban_until:
|
||||||
active_bans += 1
|
active_bans += 1
|
||||||
# Try to find bot name from hash
|
banned_bots.append(bot_name)
|
||||||
bot_hash = ban_file.replace('.ban', '')
|
|
||||||
banned_bots.append(bot_hash[:8])
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1723,6 +1728,8 @@ def show_logs(shop):
|
|||||||
if rate_limit is not None and ban_duration is not None:
|
if rate_limit is not None and ban_duration is not None:
|
||||||
print(f"🚦 Rate-Limit: {rate_limit} req/min PRO BOT-TYP, Ban: {ban_duration // 60} min")
|
print(f"🚦 Rate-Limit: {rate_limit} req/min PRO BOT-TYP, Ban: {ban_duration // 60} min")
|
||||||
print(f"🚫 Bans: {total_bans} ausgelöst, {active_bans} Bot-Typen aktuell gebannt")
|
print(f"🚫 Bans: {total_bans} ausgelöst, {active_bans} Bot-Typen aktuell gebannt")
|
||||||
|
if banned_bots:
|
||||||
|
print(f" Gebannt: {', '.join(banned_bots)}")
|
||||||
|
|
||||||
if bots:
|
if bots:
|
||||||
print(f"\n🤖 Bot-Statistik (nach Bot-Typ):")
|
print(f"\n🤖 Bot-Statistik (nach Bot-Typ):")
|
||||||
@@ -1758,6 +1765,7 @@ def show_all_logs():
|
|||||||
total_log_entries = 0
|
total_log_entries = 0
|
||||||
total_bans = 0
|
total_bans = 0
|
||||||
total_active_bans = 0
|
total_active_bans = 0
|
||||||
|
all_banned_bots = []
|
||||||
shop_stats = {}
|
shop_stats = {}
|
||||||
all_ips = {}
|
all_ips = {}
|
||||||
all_bots = {}
|
all_bots = {}
|
||||||
@@ -1768,6 +1776,7 @@ def show_all_logs():
|
|||||||
total_log_entries += entries
|
total_log_entries += entries
|
||||||
total_bans += bans
|
total_bans += bans
|
||||||
total_active_bans += active_bans
|
total_active_bans += active_bans
|
||||||
|
all_banned_bots.extend(banned_bots)
|
||||||
|
|
||||||
if activation_time:
|
if activation_time:
|
||||||
runtime_minutes = (datetime.now() - activation_time).total_seconds() / 60
|
runtime_minutes = (datetime.now() - activation_time).total_seconds() / 60
|
||||||
@@ -1783,7 +1792,8 @@ def show_all_logs():
|
|||||||
'ips': ips,
|
'ips': ips,
|
||||||
'bots': bots,
|
'bots': bots,
|
||||||
'bans': bans,
|
'bans': bans,
|
||||||
'active_bans': active_bans
|
'active_bans': active_bans,
|
||||||
|
'banned_bots': banned_bots
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtime_minutes > total_minutes:
|
if runtime_minutes > total_minutes:
|
||||||
@@ -1804,6 +1814,11 @@ def show_all_logs():
|
|||||||
|
|
||||||
total_req_min = total_log_entries / total_minutes if total_minutes > 0 else 0
|
total_req_min = total_log_entries / total_minutes if total_minutes > 0 else 0
|
||||||
|
|
||||||
|
# Zeige aktuell gebannte Bot-Typen ganz oben
|
||||||
|
unique_banned_bots = list(set(all_banned_bots))
|
||||||
|
if unique_banned_bots:
|
||||||
|
print(f"\n🚫 AKTUELL GEBANNTE BOT-TYPEN: {', '.join(sorted(unique_banned_bots))}")
|
||||||
|
|
||||||
print(f"\n📝 Log-Einträge gesamt: {total_log_entries} (⌀ {total_req_min:.1f} req/min, Laufzeit: {format_duration(total_minutes)})")
|
print(f"\n📝 Log-Einträge gesamt: {total_log_entries} (⌀ {total_req_min:.1f} req/min, Laufzeit: {format_duration(total_minutes)})")
|
||||||
if shop_stats:
|
if shop_stats:
|
||||||
for shop in sorted(shop_stats.keys()):
|
for shop in sorted(shop_stats.keys()):
|
||||||
@@ -1827,21 +1842,14 @@ def show_all_logs():
|
|||||||
|
|
||||||
print(f" ├─ {shop_colored} {geo_icon} {mode_icon}: {count} ({req_min:.1f} req/min, seit {runtime_str}) {bar}")
|
print(f" ├─ {shop_colored} {geo_icon} {mode_icon}: {count} ({req_min:.1f} req/min, seit {runtime_str}) {bar}")
|
||||||
|
|
||||||
shop_ips = stats['ips']
|
# Top 3 Bot-Typen für diesen Shop
|
||||||
if shop_ips and count > 0:
|
shop_bots = stats['bots']
|
||||||
top_ip = max(shop_ips.items(), key=lambda x: x[1]['count'])
|
if shop_bots and count > 0:
|
||||||
top_ip_addr = top_ip[0]
|
top_bots = sorted(shop_bots.items(), key=lambda x: x[1], reverse=True)[:3]
|
||||||
top_ip_count = top_ip[1]['count']
|
for i, (bot_name, bot_count) in enumerate(top_bots):
|
||||||
top_ip_ua = top_ip[1]['ua']
|
bot_req_min = bot_count / runtime if runtime > 0 else 0
|
||||||
top_ip_bot = top_ip[1].get('bot') or detect_bot(top_ip_ua)
|
prefix = "└─➤" if i == len(top_bots) - 1 else "├─➤"
|
||||||
top_ip_req_min = top_ip_count / runtime if runtime > 0 else 0
|
print(f" │ {prefix} {bot_name}: {bot_count}x, {bot_req_min:.1f} req/min")
|
||||||
|
|
||||||
if top_ip_bot == 'Unbekannt':
|
|
||||||
display_name = (top_ip_ua[:40] + '...') if len(top_ip_ua) > 43 else top_ip_ua
|
|
||||||
else:
|
|
||||||
display_name = top_ip_bot
|
|
||||||
|
|
||||||
print(f" │ └─➤ Top: {top_ip_addr} ({display_name}) - {top_ip_count}x, {top_ip_req_min:.1f} req/min")
|
|
||||||
|
|
||||||
if total_bans > 0 or total_active_bans > 0:
|
if total_bans > 0 or total_active_bans > 0:
|
||||||
print(f"\n🚫 Rate-Limit Bans: {total_bans} ausgelöst, {total_active_bans} Bot-Typen aktuell gebannt")
|
print(f"\n🚫 Rate-Limit Bans: {total_bans} ausgelöst, {total_active_bans} Bot-Typen aktuell gebannt")
|
||||||
@@ -1856,6 +1864,11 @@ def show_all_logs():
|
|||||||
|
|
||||||
bar = "█" * min(stats['bans'] // 2, 20) if stats['bans'] > 0 else ""
|
bar = "█" * min(stats['bans'] // 2, 20) if stats['bans'] > 0 else ""
|
||||||
print(f" ├─ {shop_colored}: {stats['bans']} bans ({stats['active_bans']} Bot-Typen aktiv) {bar}")
|
print(f" ├─ {shop_colored}: {stats['bans']} bans ({stats['active_bans']} Bot-Typen aktiv) {bar}")
|
||||||
|
|
||||||
|
# Zeige gebannte Bot-Typen
|
||||||
|
if stats['banned_bots']:
|
||||||
|
for bot_name in stats['banned_bots']:
|
||||||
|
print(f" │ └─🚫 {bot_name}")
|
||||||
|
|
||||||
if all_bots:
|
if all_bots:
|
||||||
print(f"\n🤖 Bot-Statistik nach Bot-Typ (alle Shops):")
|
print(f"\n🤖 Bot-Statistik nach Bot-Typ (alle Shops):")
|
||||||
@@ -2005,7 +2018,7 @@ def main():
|
|||||||
shop_mode = get_shop_mode(shop)
|
shop_mode = get_shop_mode(shop)
|
||||||
mode_icon = get_mode_icon(shop_mode)
|
mode_icon = get_mode_icon(shop_mode)
|
||||||
bot_mode = is_bot_mode(shop_mode)
|
bot_mode = is_bot_mode(shop_mode)
|
||||||
entries, _, bots, activation_time, total_bans, active_bans, _ = get_shop_log_stats(shop)
|
entries, _, bots, activation_time, total_bans, active_bans, banned_bots = get_shop_log_stats(shop)
|
||||||
runtime = (datetime.now() - activation_time).total_seconds() / 60 if activation_time else 0
|
runtime = (datetime.now() - activation_time).total_seconds() / 60 if activation_time else 0
|
||||||
|
|
||||||
httpdocs = os.path.join(VHOSTS_DIR, shop, 'httpdocs')
|
httpdocs = os.path.join(VHOSTS_DIR, shop, 'httpdocs')
|
||||||
@@ -2015,7 +2028,12 @@ def main():
|
|||||||
if bot_mode:
|
if bot_mode:
|
||||||
rate_limit, ban_duration = get_shop_rate_limit_config(shop)
|
rate_limit, ban_duration = get_shop_rate_limit_config(shop)
|
||||||
rl_str = f", {rate_limit} req/min/Bot-Typ" if rate_limit else ""
|
rl_str = f", {rate_limit} req/min/Bot-Typ" if rate_limit else ""
|
||||||
ban_str = f", {active_bans} Bot-Typen gebannt" if active_bans > 0 else ""
|
ban_str = ""
|
||||||
|
if active_bans > 0:
|
||||||
|
if banned_bots:
|
||||||
|
ban_str = f", 🚫 {', '.join(banned_bots)}"
|
||||||
|
else:
|
||||||
|
ban_str = f", {active_bans} Bot-Typen gebannt"
|
||||||
print(f" {entries} log entries, {format_duration(runtime)}, {len(BOT_PATTERNS)} Patterns{rl_str}{ban_str}")
|
print(f" {entries} log entries, {format_duration(runtime)}, {len(BOT_PATTERNS)} Patterns{rl_str}{ban_str}")
|
||||||
else:
|
else:
|
||||||
valid, count, _ = validate_existing_cache(httpdocs, get_shop_geo_region(shop))
|
valid, count, _ = validate_existing_cache(httpdocs, get_shop_geo_region(shop))
|
||||||
|
|||||||
Reference in New Issue
Block a user