ids.alfacom.it/extracted_idf/mikrotikcontoll.py
marco370 0bfe3258b5 Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1c71ce6e-1a3e-4f53-bb5d-77cdd22b8ea3
2025-11-11 09:15:10 +00:00

756 lines
32 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
import paramiko
import mysql.connector
from mysql.connector import Error
from datetime import datetime, timedelta
import logging
import re
from dotenv import load_dotenv
import os
# Carica le variabili d'ambiente
load_dotenv()
# Configurazione del logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
# Configurazione del database
db_config = {
'user': os.getenv('DB_USER'),
'password': os.getenv('DB_PASSWORD'),
'host': os.getenv('DB_HOST'),
'database': os.getenv('DB_NAME'),
}
def connect_to_database():
try:
logging.info('🔗 Connessione al database...')
db = mysql.connector.connect(**db_config)
logging.info('✅ Connessione al database riuscita.')
return db
except Error as e:
logging.error(f'❌ Errore di connessione al database: {e}')
exit(1)
def get_routers(cursor):
try:
logging.info('📡 Recupero dell\'elenco dei router dal database...')
cursor.execute("SELECT * FROM routers")
routers = cursor.fetchall()
if not routers:
logging.warning('⚠️ Nessun router trovato nel database.')
exit(0)
logging.info(f'✅ Trovati {len(routers)} router nel database.')
return routers
except Error as e:
logging.error(f'❌ Errore nel recupero dei router: {e}')
exit(1)
def connect_to_router(router_host, ssh_username, ssh_password):
try:
logging.info(f'🔐 Connessione al router {router_host} via SSH...')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(router_host, username=ssh_username, password=ssh_password, timeout=10)
logging.info(f'✅ Connessione SSH al router {router_host} riuscita.')
return ssh
except paramiko.ssh_exception.AuthenticationException as e:
logging.error(f'🔒 Autenticazione fallita per il router {router_host}: {e}')
except paramiko.ssh_exception.SSHException as e:
logging.error(f'📡 Errore SSH con il router {router_host}: {e}')
except Exception as e:
logging.error(f'❌ Errore nella connessione al router {router_host}: {e}')
return None
def get_address_list(ssh, list_name):
try:
command = f"/ip firewall address-list print where list={list_name}"
logging.info(f'⚙️ Esecuzione del comando sul router: {command}')
stdin, stdout, stderr = ssh.exec_command(command)
output = stdout.read().decode('utf-8', errors='ignore')
error_output = stderr.read().decode('utf-8', errors='ignore')
if error_output:
logging.error(f'❌ Errore durante l\'esecuzione del comando: {error_output}')
return []
logging.debug(f'📋 Output del comando "{command}":\n{output}')
return parse_address_list_output(output)
except Exception as e:
logging.error(f'❌ Errore nella get_address_list per {list_name}: {e}')
return []
def add_ip_to_list(ssh, ip_address, list_name, timeout=None):
"""
🆕 Aggiunge un IP alla address-list del router MikroTik
🕐 Supporta timeout automatico per ddos_detect_v03 e whitelist (60 minuti)
"""
try:
# 🆕 Timeout automatico per ddos_detect_v03 E whitelist
if list_name == 'ddos_detect_v03':
timeout = '1h' # 60 minuti per IP DDoS detection
logging.info(f'⏰ Applicando timeout 60min per {ip_address} in {list_name}')
elif list_name == 'whitelist':
timeout = '1h' # 🆕 60 minuti anche per whitelist (sicurezza)
logging.info(f'⏰ Applicando timeout 60min per {ip_address} in whitelist (sicurezza)')
# Costruzione comando con o senza timeout
if timeout:
command = f'/ip firewall address-list add list={list_name} address={ip_address} timeout={timeout} comment="Added by DDoS System - {datetime.now().strftime("%Y-%m-%d %H:%M")} - Timeout: {timeout}"'
else:
command = f'/ip firewall address-list add list={list_name} address={ip_address} comment="Added by DDoS System - {datetime.now().strftime("%Y-%m-%d %H:%M")}"'
logging.info(f' Aggiungendo {ip_address} alla lista {list_name}{"" if not timeout else f" con timeout {timeout}"}...')
stdin, stdout, stderr = ssh.exec_command(command)
error_output = stderr.read().decode('utf-8', errors='ignore')
if error_output and 'already exists' not in error_output.lower():
logging.error(f'❌ Errore aggiungendo {ip_address} a {list_name}: {error_output}')
return False
elif 'already exists' in error_output.lower():
logging.debug(f' IP {ip_address} già presente in {list_name}')
return True
if timeout:
logging.info(f'✅ IP {ip_address} aggiunto alla lista {list_name} con timeout {timeout}')
else:
logging.info(f'✅ IP {ip_address} aggiunto alla lista {list_name}')
return True
except Exception as e:
logging.error(f'❌ Errore nella funzione add_ip_to_list: {e}')
return False
def parse_address_list_output(output):
ips = []
lines = output.strip().split('\n')
current_comment = ''
for line in lines:
line = line.strip()
logging.debug(f'📝 Linea analizzata: {line}')
# Salta le linee vuote
if not line:
continue
# Salta le linee non pertinenti
if line.startswith('Flags:') or line.startswith('Columns:') or line.startswith('#'):
continue
# Se la linea inizia con ';;;', è un commento
if line.startswith(';;;'):
current_comment = line[4:].strip()
continue
# Se la linea inizia con un numero, è un entry
if re.match(r'^\d', line):
parts = line.split()
idx = 0
if len(parts) < 3: # Controllo minimo campi richiesti
continue
index = parts[idx]
idx += 1
# Controlla se il prossimo elemento è un flag
flags = ''
if idx < len(parts) and re.match(r'^[A-Z]+$', parts[idx]):
flags = parts[idx]
idx += 1
# Nome della lista
if idx < len(parts):
list_name = parts[idx]
idx += 1
else:
list_name = ''
# Indirizzo IP
if idx < len(parts):
ip_address = parts[idx]
idx += 1
else:
ip_address = ''
# Creazione dell'entry solo se abbiamo dati validi
if list_name and ip_address:
entry = {
'list_name': list_name,
'ip_address': ip_address,
'comment': current_comment
}
ips.append(entry)
logging.debug(f'✅ Aggiunta entry: {entry}')
# Reset del commento corrente
current_comment = ''
else:
# Linea non riconosciuta
logging.warning(f'⚠️ Linea non riconosciuta: {line}')
logging.debug(f'📊 IP estratti: {len(ips)} entries')
return ips
def insert_ips_into_database(cursor, db, router_id, ips):
if not ips:
logging.info(f' Nessun IP da inserire per router ID {router_id}')
return
inserted_count = 0
updated_count = 0
for ip in ips:
try:
cursor.execute("""
INSERT INTO router_data (router_id, list_name, ip_address, comment)
VALUES (%s, %s, %s, %s)
ON DUPLICATE KEY UPDATE comment=%s, retrieved_at=%s
""", (router_id, ip['list_name'], ip['ip_address'], ip['comment'], ip['comment'], datetime.now()))
if cursor.rowcount == 1:
inserted_count += 1
elif cursor.rowcount == 2:
updated_count += 1
db.commit()
logging.debug(f'💾 Processato IP {ip["ip_address"]} nella lista {ip["list_name"]} per router ID {router_id}')
except mysql.connector.Error as err:
logging.error(f"❌ Errore nell'inserimento di {ip['ip_address']}: {err}")
logging.info(f'📊 Router ID {router_id}: {inserted_count} IP inseriti, {updated_count} IP aggiornati')
def cleanup_old_ips(cursor, db):
"""
🆕 Rimuove gli IP più vecchi delle soglie specificate
📊 AGGIORNATO: ddos_detect_v03 da ip_list, ddos2/ddos3-attackers da router_data
"""
cleanup_stats = {}
try:
logging.info('🧹 === PULIZIA DATABASE ===')
# 🆕 Pulizia tabella ip_list (solo ddos_detect_v03)
logging.info('📋 Pulizia tabella ip_list...')
list_name = 'ddos_detect_v03'
days = 7
logging.info(f'🧹 Pulizia lista {list_name} da ip_list (>{days} giorni)...')
# Prima conta quanti record verranno eliminati
cursor.execute("""
SELECT COUNT(*) as count FROM ip_list
WHERE list_name = %s
AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
""", (list_name, days))
count_result = cursor.fetchone()
records_to_delete = count_result['count'] if count_result else 0
if records_to_delete == 0:
logging.info(f' Nessun record da eliminare per {list_name} in ip_list')
cleanup_stats[f'{list_name}_ip_list'] = 0
else:
# Esegui la pulizia
cursor.execute("""
DELETE FROM ip_list
WHERE list_name = %s
AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
""", (list_name, days))
deleted_count = cursor.rowcount
cleanup_stats[f'{list_name}_ip_list'] = deleted_count
logging.info(f'✅ ip_list {list_name}: eliminati {deleted_count} record più vecchi di {days} giorni')
# 🆕 Pulizia tabella router_data (ddos2-attackers e ddos3-attackers)
logging.info('🎯 Pulizia tabella router_data...')
router_data_policies = [
('ddos2-attackers', 15), # Lista attackers livello 2
('ddos3-attackers', 20) # Lista attackers livello 3
]
for list_name, days in router_data_policies:
logging.info(f'🧹 Pulizia lista {list_name} da router_data (>{days} giorni)...')
# Prima conta quanti record verranno eliminati
cursor.execute("""
SELECT COUNT(*) as count FROM router_data
WHERE list_name = %s
AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
""", (list_name, days))
count_result = cursor.fetchone()
records_to_delete = count_result['count'] if count_result else 0
if records_to_delete == 0:
logging.info(f' Nessun record da eliminare per {list_name} in router_data')
cleanup_stats[f'{list_name}_router_data'] = 0
else:
# Esegui la pulizia
cursor.execute("""
DELETE FROM router_data
WHERE list_name = %s
AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
""", (list_name, days))
deleted_count = cursor.rowcount
cleanup_stats[f'{list_name}_router_data'] = deleted_count
logging.info(f'✅ router_data {list_name}: eliminati {deleted_count} record più vecchi di {days} giorni')
db.commit()
# Statistiche finali
total_deleted = sum(cleanup_stats.values())
logging.info(f'🎯 Pulizia completata: {total_deleted} record totali eliminati')
for key, count in cleanup_stats.items():
if count > 0:
logging.info(f' └─ {key}: {count} record eliminati')
except Error as e:
logging.error(f"❌ Errore durante la pulizia degli IP vecchi: {e}")
db.rollback()
def check_expired_ips_on_router(ssh, router_host):
"""
🆕 Verifica IP scaduti sul router e fornisce statistiche
📊 AGGIORNATO: liste corrette senza ddos_ia
"""
try:
logging.info(f'🕐 Verifica IP scaduti sul router {router_host}...')
# 🆕 Lista delle liste da controllare (senza ddos_ia)
lists_to_check = ['ddos_detect_v03', 'ddos2-attackers', 'ddos3-attackers', 'whitelist']
total_active_ips = 0
timeout_stats = {}
for list_name in lists_to_check:
current_ips = get_address_list(ssh, list_name)
count = len([ip for ip in current_ips if 'ip_address' in ip])
total_active_ips += count
timeout_stats[list_name] = count
if count > 0:
logging.info(f'📊 Lista {list_name}: {count} IP attivi')
logging.info(f'🎯 Router {router_host}: {total_active_ips} IP totali attivi')
# Log specifico per ddos_detect_v03 con timeout
if timeout_stats.get('ddos_detect_v03', 0) > 0:
logging.info(f'⏰ Lista ddos_detect_v03: {timeout_stats["ddos_detect_v03"]} IP con timeout 60min attivi')
return timeout_stats
except Exception as e:
logging.error(f'❌ Errore verifica IP scaduti su router {router_host}: {e}')
return {}
def check_global_whitelist_conflicts(cursor, db):
"""
🆕 Controlla e risolve conflitti tra whitelistGlobale e ddos_detect_v03
"""
try:
logging.info('🛡️ === CONTROLLO WHITELIST GLOBALE ===')
# Trova IP che sono sia in whitelist globale che in ddos_detect_v03
cursor.execute("""
SELECT DISTINCT w.ip_address, w.comment, w.reason
FROM whitelistGlobale w
INNER JOIN ip_list i ON w.ip_address = i.ip_address
WHERE w.active = 1
AND i.list_name = 'ddos_detect_v03'
""")
conflicts = cursor.fetchall()
if not conflicts:
logging.info('✅ Nessun conflitto trovato tra whitelist globale e ddos_detect_v03')
return
logging.info(f'⚠️ Trovati {len(conflicts)} IP in conflitto da risolvere')
resolved_count = 0
for conflict in conflicts:
ip_address = conflict['ip_address']
comment = conflict['comment'] or 'Whitelist globale'
reason = conflict['reason'] or 'Risoluzione automatica conflitto'
# Rimuovi da ddos_detect_v03
cursor.execute("""
DELETE FROM ip_list
WHERE ip_address = %s AND list_name = 'ddos_detect_v03'
""", (ip_address,))
if cursor.rowcount > 0:
resolved_count += 1
logging.info(f'✅ Rimosso {ip_address} da ddos_detect_v03 (motivo: {reason})')
db.commit()
logging.info(f'🎯 Risolti {resolved_count} conflitti whitelist vs blacklist')
except Error as e:
logging.error(f"❌ Errore controllo whitelist globale: {e}")
db.rollback()
def sync_global_whitelist_to_routers(cursor, db, ssh, router_host):
"""
🆕 Sincronizza whitelistGlobale con tutti i router
🕐 AGGIORNATO: applica timeout 60min anche alla whitelist per sicurezza
"""
try:
logging.info(f'🌐 Sincronizzazione whitelist globale per router {router_host}...')
# Recupera IP attivi dalla whitelist globale
cursor.execute("""
SELECT ip_address, comment, reason, last_sync
FROM whitelistGlobale
WHERE active = 1
ORDER BY created_at DESC
""")
global_whitelist = cursor.fetchall()
if not global_whitelist:
logging.info(f' Nessun IP nella whitelist globale')
return 0, 0
logging.info(f'📋 Trovati {len(global_whitelist)} IP nella whitelist globale')
# Ottieni whitelist corrente dal router
current_whitelist = get_address_list(ssh, 'whitelist')
current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
added_count = 0
updated_count = 0
timeout_applied = 0
for entry in global_whitelist:
ip_address = entry['ip_address']
comment = entry['comment'] or 'Whitelist globale'
reason = entry['reason'] or 'IP fidato globale'
if ip_address not in current_whitelist_set:
# 🆕 Aggiungi alla whitelist del router CON TIMEOUT 60min
if add_ip_to_list(ssh, ip_address, 'whitelist'): # Timeout automatico applicato
added_count += 1
timeout_applied += 1 # 🆕 Conta timeout whitelist
# Aggiorna last_sync
cursor.execute("""
UPDATE whitelistGlobale
SET last_sync = NOW()
WHERE ip_address = %s
""", (ip_address,))
updated_count += 1
logging.info(f'✅ IP {ip_address} aggiunto alla whitelist router {router_host} con timeout 60min')
else:
logging.debug(f' IP {ip_address} già presente nella whitelist router {router_host}')
if updated_count > 0:
db.commit()
logging.info(f'🌐 Whitelist globale router {router_host}: {added_count} IP aggiunti, {timeout_applied} timeout applicati')
return added_count, timeout_applied
except Error as e:
logging.error(f"❌ Errore sincronizzazione whitelist globale router {router_host}: {e}")
return 0, 0
def sync_ip_list_to_routers(cursor, db, ssh, router_id, router_host):
"""
🆕 Sincronizza SOLO ddos_detect_v03 dalla tabella ip_list con il router
📊 AGGIORNATO: controlla whitelist globale prima di bloccare IP
"""
try:
# 🆕 Query ottimizzata per SOLO ddos_detect_v03 ESCLUDENDO whitelist globale
logging.info(f'📊 Recupero IP ddos_detect_v03 (esclusi whitelist globale) per router {router_host}...')
cursor.execute("""
SELECT i.list_name, i.ip_address, i.retrieved_at
FROM ip_list i
LEFT JOIN whitelistGlobale w ON i.ip_address = w.ip_address AND w.active = 1
WHERE i.list_name = 'ddos_detect_v03'
AND i.retrieved_at > DATE_SUB(NOW(), INTERVAL 3 DAY)
AND w.ip_address IS NULL -- 🆕 Escludi IP in whitelist globale
ORDER BY i.retrieved_at DESC
LIMIT 3000
""")
ip_list_entries = cursor.fetchall()
if not ip_list_entries:
logging.info(f' Nessun IP ddos_detect_v03 da bloccare (whitelist globale applicata)')
return
logging.info(f'📋 Trovati {len(ip_list_entries)} IP ddos_detect_v03 da sincronizzare (dopo filtro whitelist)')
# Ottieni la lista corrente dal router
current_ips = get_address_list(ssh, 'ddos_detect_v03')
current_ips_set = {entry['ip_address'] for entry in current_ips if 'ip_address' in entry}
# 🆕 Ottieni anche whitelist corrente per doppio controllo
current_whitelist = get_address_list(ssh, 'whitelist')
current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
added_count = 0
timeout_applied = 0
skipped_whitelist = 0
# Processa solo ddos_detect_v03
for entry in ip_list_entries:
ip_address = entry['ip_address']
# 🆕 Doppio controllo: non bloccare IP in whitelist router
if ip_address in current_whitelist_set:
skipped_whitelist += 1
logging.debug(f'🛡️ IP {ip_address} saltato - presente in whitelist router')
continue
if ip_address not in current_ips_set:
if add_ip_to_list(ssh, ip_address, 'ddos_detect_v03'): # Timeout automatico applicato
added_count += 1
timeout_applied += 1
else:
logging.warning(f'⚠️ Fallita aggiunta {ip_address} a ddos_detect_v03')
else:
logging.debug(f' IP {ip_address} già presente in ddos_detect_v03')
# Statistiche
logging.info(f'✅ Lista ddos_detect_v03: aggiunti {added_count} nuovi IP')
logging.info(f'⏰ Timeout 60min applicati: {timeout_applied} IP in ddos_detect_v03')
if skipped_whitelist > 0:
logging.info(f'🛡️ IP saltati per whitelist: {skipped_whitelist}')
logging.info(f'🎯 Sincronizzazione ddos_detect_v03 completata su router {router_host}')
except Error as e:
logging.error(f"❌ Errore durante la sincronizzazione ddos_detect_v03 con router {router_host}: {e}")
def sync_router_data_to_routers(cursor, db, ssh, router_id, router_host):
"""
🆕 Sincronizza ddos2-attackers, ddos3-attackers e whitelist dalla tabella router_data
📊 AGGIORNATO: gestione specifica per router e whitelist CON TIMEOUT
"""
try:
logging.info(f'🎯 Sincronizzazione dati router_data per router {router_host} (ID: {router_id})...')
# 🆕 Query per ddos2-attackers e ddos3-attackers specifici del router
cursor.execute("""
SELECT list_name, ip_address, retrieved_at, whitelist, added_to_router
FROM router_data
WHERE router_id = %s
AND list_name IN ('ddos2-attackers', 'ddos3-attackers')
AND retrieved_at > DATE_SUB(NOW(), INTERVAL 7 DAY)
ORDER BY retrieved_at DESC
LIMIT 2000
""", (router_id,))
router_entries = cursor.fetchall()
total_added = 0
whitelist_timeout_applied = 0
if not router_entries:
logging.info(f' Nessun dato ddos2/ddos3-attackers recente per router {router_host}')
else:
logging.info(f'📋 Trovati {len(router_entries)} record ddos2/ddos3-attackers per router {router_host}')
# Raggruppa per lista
lists_data = {}
whitelist_ips = []
for entry in router_entries:
list_name = entry['list_name']
ip_address = entry['ip_address']
is_whitelist = entry['whitelist'] == 1
if is_whitelist:
whitelist_ips.append(entry)
else:
if list_name not in lists_data:
lists_data[list_name] = []
lists_data[list_name].append(ip_address)
# Processa liste ddos2/ddos3-attackers (SENZA timeout)
for list_name, ip_addresses in lists_data.items():
logging.info(f'🔄 Sincronizzazione lista {list_name} ({len(ip_addresses)} IP) per router {router_host}...')
# Ottieni lista corrente dal router
current_ips = get_address_list(ssh, list_name)
current_ips_set = {entry['ip_address'] for entry in current_ips if 'ip_address' in entry}
added_count = 0
for ip_address in ip_addresses:
if ip_address not in current_ips_set:
if add_ip_to_list(ssh, ip_address, list_name): # Nessun timeout per queste liste
added_count += 1
total_added += 1
if added_count > 0:
logging.info(f'✅ Lista {list_name}: aggiunti {added_count} IP per router {router_host}')
# 🆕 Gestione whitelist specifica CON TIMEOUT
if whitelist_ips:
logging.info(f'🛡️ Elaborazione {len(whitelist_ips)} IP per whitelist router {router_host} (CON TIMEOUT)...')
whitelist_added = 0
# Ottieni whitelist corrente
current_whitelist = get_address_list(ssh, 'whitelist')
current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
for entry in whitelist_ips:
ip_address = entry['ip_address']
if ip_address not in current_whitelist_set:
if add_ip_to_list(ssh, ip_address, 'whitelist'): # 🆕 CON TIMEOUT 60min
# Aggiorna il database: marca come aggiunto al router
cursor.execute("""
UPDATE router_data
SET added_to_router = 1
WHERE ip_address = %s AND router_id = %s AND whitelist = 1
""", (ip_address, router_id))
db.commit()
whitelist_added += 1
whitelist_timeout_applied += 1 # 🆕 Conta timeout whitelist
logging.info(f'✅ IP {ip_address} aggiunto alla whitelist router {router_host} con timeout 60min')
logging.info(f'🛡️ Whitelist router {router_host}: aggiunti {whitelist_added} IP con timeout')
logging.info(f'🎯 Sincronizzazione router_data completata: {total_added} IP ddos2/ddos3-attackers aggiunti')
# 🆕 Gestione IP whitelist non ancora aggiunti (query separata per performance)
cursor.execute("""
SELECT ip_address FROM router_data
WHERE whitelist = 1 AND router_id = %s AND added_to_router = 0
AND retrieved_at > DATE_SUB(NOW(), INTERVAL 7 DAY)
""", (router_id,))
pending_whitelist = cursor.fetchall()
if pending_whitelist:
logging.info(f'🛡️ Trovati {len(pending_whitelist)} IP whitelist pending per router {router_host}...')
current_whitelist = get_address_list(ssh, 'whitelist')
current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
added_whitelist = 0
for ip_entry in pending_whitelist:
ip_address = ip_entry['ip_address']
if ip_address not in current_whitelist_set:
if add_ip_to_list(ssh, ip_address, 'whitelist'): # 🆕 CON TIMEOUT 60min
cursor.execute("""
UPDATE router_data
SET added_to_router = 1
WHERE ip_address = %s AND router_id = %s AND whitelist = 1
""", (ip_address, router_id))
db.commit()
added_whitelist += 1
whitelist_timeout_applied += 1 # 🆕 Conta timeout
if added_whitelist > 0:
logging.info(f'🛡️ Whitelist pending router {router_host}: aggiunti {added_whitelist} IP con timeout')
return whitelist_timeout_applied
except Error as e:
logging.error(f"❌ Errore durante la sincronizzazione router_data per router {router_host}: {e}")
return 0
def main():
logging.info('🚀 === AVVIO SISTEMA CONTROLLO ROUTER MIKROTIK ===')
db = connect_to_database()
cursor = db.cursor(dictionary=True)
try:
# 🆕 FASE 0: Controllo whitelist globale e risoluzione conflitti
logging.info('🛡️ === FASE 0: CONTROLLO WHITELIST GLOBALE ===')
check_global_whitelist_conflicts(cursor, db)
# 🆕 Pulizia IP vecchi (ora gestisce correttamente le tabelle separate)
logging.info('🧹 === FASE 1: PULIZIA IP OBSOLETI ===')
cleanup_old_ips(cursor, db)
# Recupera i router dal database
logging.info('📡 === FASE 2: RECUPERO ROUTER ===')
routers = get_routers(cursor)
logging.info('🔄 === FASE 3: SINCRONIZZAZIONE ROUTER ===')
successful_syncs = 0
failed_syncs = 0
total_ddos_timeouts = 0
total_whitelist_timeouts = 0
for router in routers:
router_id = router['id']
router_host = router['ip_address']
ssh_username = router['ssh_username']
ssh_password = router['ssh_password']
logging.info(f'🎯 Elaborazione router {router_host} (ID: {router_id})...')
ssh = connect_to_router(router_host, ssh_username, ssh_password)
if ssh is None:
failed_syncs += 1
logging.error(f'❌ Saltato router {router_host} - connessione fallita')
continue
try:
# 🆕 Verifica IP scaduti prima della sincronizzazione
current_stats = check_expired_ips_on_router(ssh, router_host)
# 🆕 0. Sincronizza whitelist globale (PRIMA di tutto) CON TIMEOUT
global_added, global_timeouts = sync_global_whitelist_to_routers(cursor, db, ssh, router_host)
total_whitelist_timeouts += global_timeouts
# 1. Sincronizza ddos_detect_v03 da ip_list (con filtro whitelist globale)
sync_ip_list_to_routers(cursor, db, ssh, router_id, router_host)
# 2. Sincronizza ddos2-attackers, ddos3-attackers e whitelist da router_data
router_whitelist_timeouts = sync_router_data_to_routers(cursor, db, ssh, router_id, router_host)
total_whitelist_timeouts += router_whitelist_timeouts
# 🆕 Verifica finale per statistiche timeout
final_stats = check_expired_ips_on_router(ssh, router_host)
ddos_v03_count = final_stats.get('ddos_detect_v03', 0)
if ddos_v03_count > 0:
total_ddos_timeouts += ddos_v03_count
successful_syncs += 1
logging.info(f'✅ Router {router_host} sincronizzato con successo')
except Exception as e:
failed_syncs += 1
logging.error(f'❌ Errore durante elaborazione router {router_host}: {e}')
finally:
ssh.close()
logging.info(f'🔐 Connessione SSH al router {router_host} chiusa.')
# Statistiche finali
logging.info('📊 === STATISTICHE FINALI ===')
logging.info(f'✅ Router sincronizzati con successo: {successful_syncs}')
logging.info(f'❌ Router falliti: {failed_syncs}')
logging.info(f'📡 Router totali processati: {len(routers)}')
logging.info(f'⏰ IP ddos_detect_v03 con timeout 60min attivi: {total_ddos_timeouts}')
logging.info(f'🛡️ IP whitelist con timeout 60min applicati: {total_whitelist_timeouts}')
logging.info('🎯 Gestione automatica whitelist tramite campo router_data.whitelist=1')
logging.info('🛡️ Protezione automatica whitelist globale applicata')
logging.info('⏰ NUOVO: Timeout 60min applicato anche alla whitelist per maggiore sicurezza')
except Exception as e:
logging.error(f'❌ Errore critico nel main: {e}')
finally:
cursor.close()
db.close()
logging.info('🔗 Connessione al database chiusa.')
logging.info('🏁 === FINE ESECUZIONE SISTEMA CONTROLLO ROUTER ===')
if __name__ == '__main__':
main()