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
150 lines
5.8 KiB
Python
150 lines
5.8 KiB
Python
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()
|