import pandas as pd from sqlalchemy import create_engine import logging from collections import defaultdict from datetime import datetime, timedelta # Configurazione del logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) # Connessione al database engine = create_engine('mysql+mysqlconnector://root:Hdgtejskjjc0-@localhost/LOG_MIKROTIK') # Soglie di rilevamento THRESHOLD_SYN_FLOOD = 100 # Numero di pacchetti SYN senza ACK in un intervallo di tempo THRESHOLD_ACK_FLOOD = 100 # Numero di pacchetti ACK senza sessioni attive THRESHOLD_FIN_RST_FLOOD = 100 # Numero di pacchetti FIN o RST THRESHOLD_NULL_XMAS_SCAN = 50 # Numero di pacchetti Null o Xmas # Strutture dati per memorizzare i pacchetti syn_packets = defaultdict(int) ack_packets = defaultdict(int) fin_rst_packets = defaultdict(int) null_xmas_packets = defaultdict(int) # Report dei rilevamenti detection_report = { "SYN Flood": 0, "ACK Flood": 0, "FIN/RST Flood": 0, "Null/Xmas Scan": 0, "Suspicious IPs": defaultdict(int) } # Nome del file per tenere traccia dell'ultimo ID analizzato ULTIMO_ANALIZZATO_FILE = 'ultimo_analizzato.txt' # Funzione per leggere l'ultimo ID analizzato dal file def read_ultimo_analizzato(): try: with open(ULTIMO_ANALIZZATO_FILE, 'r') as f: return int(f.read().strip()) except FileNotFoundError: logging.info(f"File '{ULTIMO_ANALIZZATO_FILE}' non trovato. Partenza da ID = 0.") return 0 except ValueError: logging.error(f"Errore nella lettura del file '{ULTIMO_ANALIZZATO_FILE}'.") return 0 # Funzione per scrivere l'ultimo ID analizzato nel file def write_ultimo_analizzato(last_analyzed_id): with open(ULTIMO_ANALIZZATO_FILE, 'w') as f: f.write(str(last_analyzed_id)) # Funzione per analizzare il traffico sulla base delle regole def analyze_traffic(data): for index, row in data.iterrows(): ip_src = row['Messaggio2'].split(':')[0] # IP di origine (estratto da Messaggio2) flags = row['Messaggio1'] # Flags TCP (da Messaggio1) # Rileva SYN flood if "SYN" in flags and "ACK" not in flags: syn_packets[ip_src] += 1 if syn_packets[ip_src] > THRESHOLD_SYN_FLOOD: detection_report["SYN Flood"] += 1 detection_report["Suspicious IPs"][ip_src] += 1 logging.info(f"[ALERT] Possibile SYN Flood da {ip_src} - {syn_packets[ip_src]} pacchetti SYN senza ACK") # Rileva ACK flood if "ACK" in flags and "SYN" not in flags: ack_packets[ip_src] += 1 if ack_packets[ip_src] > THRESHOLD_ACK_FLOOD: detection_report["ACK Flood"] += 1 detection_report["Suspicious IPs"][ip_src] += 1 logging.info(f"[ALERT] Possibile ACK Flood da {ip_src} - {ack_packets[ip_src]} pacchetti ACK sospetti") # Rileva FIN/RST flood if "FIN" in flags or "RST" in flags: fin_rst_packets[ip_src] += 1 if fin_rst_packets[ip_src] > THRESHOLD_FIN_RST_FLOOD: detection_report["FIN/RST Flood"] += 1 detection_report["Suspicious IPs"][ip_src] += 1 logging.info(f"[ALERT] Possibile FIN/RST Flood da {ip_src} - {fin_rst_packets[ip_src]} pacchetti FIN/RST") # Rileva Null Scan o Xmas Tree Scan if flags == "" or "FIN, PSH, URG" in flags: # Verifica per Null o Xmas Tree Scan null_xmas_packets[ip_src] += 1 if null_xmas_packets[ip_src] > THRESHOLD_NULL_XMAS_SCAN: detection_report["Null/Xmas Scan"] += 1 detection_report["Suspicious IPs"][ip_src] += 1 logging.info(f"[ALERT] Possibile Null/Xmas Scan da {ip_src} - {null_xmas_packets[ip_src]} pacchetti") # Funzione per estrarre i dati dal database in blocchi def fetch_network_data(last_analyzed_id, limit=10000): query = f""" SELECT ID, Data, Ora, IndirizzoIP, Messaggio1, Messaggio2, Messaggio3 FROM Esterna WHERE ID > {last_analyzed_id} ORDER BY ID ASC LIMIT {limit} """ return pd.read_sql(query, engine) # Funzione per generare il report al termine dell'analisi def generate_report(): logging.info("\n--- Report di rilevamento DDoS ---\n") logging.info(f"Totale SYN Flood rilevati: {detection_report['SYN Flood']}") logging.info(f"Totale ACK Flood rilevati: {detection_report['ACK Flood']}") logging.info(f"Totale FIN/RST Flood rilevati: {detection_report['FIN/RST Flood']}") logging.info(f"Totale Null/Xmas Scan rilevati: {detection_report['Null/Xmas Scan']}") logging.info("\n--- IP sospetti rilevati ---\n") for ip, count in detection_report['Suspicious IPs'].items(): logging.info(f"IP {ip} rilevato in {count} attività sospette") # Funzione principale def main(): last_analyzed_id = read_ultimo_analizzato() # Inizializza l'ID di partenza batch_size = 10000 total_records_analyzed = 0 while True: logging.info(f"Estrazione di un nuovo blocco di dati da ID > {last_analyzed_id}...") network_data = fetch_network_data(last_analyzed_id, limit=batch_size) if network_data.empty: logging.info("Nessun nuovo dato da analizzare. Analisi completata.") break # Aggiorna l'ultimo ID analizzato last_analyzed_id = network_data['ID'].max() total_records_analyzed += len(network_data) write_ultimo_analizzato(last_analyzed_id) # Salva l'ID aggiornato # Analizza il traffico del blocco corrente analyze_traffic(network_data) # Logging per ogni blocco processato logging.info(f"Blocco analizzato: {len(network_data)} record.") logging.info(f"Totale record analizzati: {total_records_analyzed}") # Genera il report finale generate_report() if __name__ == "__main__": main()