Una dashboard PHP che trasforma i log grezzi del WAF in informazioni operative: risk scoring in tempo reale, arricchimento geografico e blocco automatico degli IP tramite firewalld — senza alcuna infrastruttura esterna.
Ogni applicazione web esposta alla rete pubblica riceve, nel giro di pochi minuti dalla messa online, un flusso costante di richieste automatizzate: scanner di vulnerabilità alla ricerca di exploit noti, bot che raccolgono contenuti, tentativi di brute-force contro i form di login e richieste di ricognizione che mappano la struttura del sito. La risposta standard a questa realtà è implementare un Web Application FirewallUn WAF (Web Application Firewall) è un livello di sicurezza che si interpone tra internet e l'applicazione web, ispezionando il traffico HTTP e bloccando le richieste malevole in base a regole configurabili. — un WAF — che filtra il traffico secondo regole predefinite. Ma un WAF da solo genera dati, non comprensione. I log si accumulano, lo storage cresce e nella maggior parte dei casi nessuno li guarda fino a quando qualcosa non è già andato storto.
Questo è il problema che ho voluto risolvere. SecureLog è una WAF Dashboard che ho progettato e costruito per trasformare i dati grezzi dei log HTTP in intelligence operativa: un sistema che non si limita a mostrare ciò che accade sulla propria infrastruttura web, ma lo analizza, lo valuta e — quando le evidenze lo giustificano — agisce autonomamente bloccando gli indirizzi IP malevoli a livello di firewall.
In questo articolo descrivo l'architettura, le motivazioni dietro le scelte progettuali e il modo in cui ogni componente collabora per creare un sistema di monitoraggio della sicurezza a ciclo chiuso.
Il problema: log senza contesto
Un tipico web server LAMP/LEMPLAMP sta per Linux, Apache, MySQL, PHP. LEMP sostituisce Apache con Nginx. Entrambi sono stack server standard per l'hosting di applicazioni web. genera log di accesso nel Combined Log FormatUn formato di log standard utilizzato da Apache e Nginx. Ogni riga registra l'IP del client, il timestamp, il metodo HTTP, l'URI, il codice di stato, la dimensione della risposta, il referrer e la stringa user agent.: una riga per richiesta, contenente l'IP del client, il timestamp, il metodo HTTP, l'URI richiesto, il codice di stato, il referrer e lo user agent. Su un sito mediamente trafficato, questo significa decine di migliaia di righe al giorno.
I dati grezzi ci sono, ma estrarne significato è una sfida completamente diversa. Quali di quelle 30.000 richieste giornaliere sono visitatori legittimi? Quali sono crawler dei motori di ricerca? Quali stanno cercando /wp-login.php su un sito che non usa WordPress? Quali stanno tentando una SQL injectionUna tecnica di attacco in cui istruzioni SQL malevole vengono inserite nei campi di input o negli URL, nel tentativo di manipolare o estrarre dati dal database dell'applicazione. attraverso i parametri della query? E soprattutto — quali indirizzi IP lo stanno facendo in modo sufficientemente persistente da giustificare il blocco a livello di firewall?
Rispondere a queste domande manualmente non è sostenibile. Avevo bisogno di una pipeline automatizzata in grado di importare i log, arricchirli con analisi delle minacce e dati di geolocalizzazione, presentare i risultati attraverso un'interfaccia intuitiva e fornire capacità di risposta sia manuali che automatizzate.
Panoramica dell'architettura
SecureLog è costruito su un backend PHP con un frontend JavaScript, progettato per funzionare a fianco del web server che monitora. L'architettura segue una chiara separazione delle responsabilità su sei componenti, ciascuno implementato come un file distinto con un compito specifico.
Il frontend (index.php) è un'applicazione a pagina singola con una struttura di navigazione a sidebar, costruita con JavaScript vanilla e Chart.jsUna libreria JavaScript open-source per la creazione di grafici responsivi e animati. SecureLog la utilizza per le linee di tendenza del traffico e le visualizzazioni della distribuzione dei codici di stato HTTP.. Comunica in modo asincrono con il backend attraverso un API gateway unificato (api.php) che instrada tutte le richieste AJAXAsynchronous JavaScript and XML — una tecnica per effettuare richieste HTTP dal browser senza ricaricare la pagina, consentendo aggiornamenti dei dati in tempo reale nella dashboard. alla funzione handler appropriata. L'autenticazione e la gestione delle sessioni sono affidate a un modulo di sicurezza dedicato (auth.php e login.php), che impone HTTPS, parametri sicuri per i cookie e la validazione del token CSRFCross-Site Request Forgery: un attacco che induce il browser dell'utente a effettuare richieste indesiderate. SecureLog lo previene generando e validando un token univoco per ogni sessione..
Sul lato dell'elaborazione backend, un processore di log CLI (LogProcessor.php) viene eseguito come task pianificato, leggendo i log di accesso grezzi in modo incrementale e passando ogni riga attraverso il motore di analisi del rischio (RiskAnalyzer.php). Infine, uno script di sincronizzazione del firewall (SynchronizeFirewall.sh) colma il divario tra le decisioni dell'applicazione e la configurazione di firewalldLo strumento predefinito di gestione del firewall sui sistemi RHEL/CentOS/AlmaLinux. Supporta gli ipset — collezioni nominate di indirizzi IP utilizzabili nelle regole del firewall per il blocco massivo efficiente. del sistema operativo, applicando ban e sblocchi in tempo reale.
Il motore di analisi del rischio
Al cuore di SecureLog c'è la classe RiskAnalyzer — il componente che trasforma una riga di log grezza in una valutazione quantificata della minaccia. La filosofia di progettazione è diretta: ogni richiesta riceve un punteggio di rischio numerico, calcolato valutando segnali indipendenti multipli e sommando i loro contributi ponderati.
L'analisi procede attraverso sei controlli sequenziali:
Rilevamento di scanner aggressivi. La stringa user agent viene confrontata con una libreria configurabile di firme di scanner malevoli noti — strumenti come Nikto, sqlmap, DirBuster e utilità di ricognizione simili. Una corrispondenza positiva contribuisce con un componente di punteggio elevato, poiché la sola presenza di questi strumenti indica un'attività di probing deliberata.
Riconoscimento di pattern di attacco. L'URI completo della richiesta viene scansionato alla ricerca di firme di vettori di attacco comuni: frammenti di SQL injection (UNION SELECT, OR 1=1), sequenze di path traversalUn attacco che utilizza sequenze come ../../ negli URL per uscire dalla directory root del web server e accedere a file arbitrari sul server, come /etc/passwd., payload XSSCross-Site Scripting: un attacco in cui codice JavaScript malevolo viene iniettato nelle pagine web visualizzate da altri utenti, tipicamente attraverso parametri URL o campi di input. e tentativi di command injection. La libreria di firme viene caricata da un file di configurazione centralizzato e compilata in espressioni regolariEspressioni di pattern-matching utilizzate per identificare stringhe che corrispondono a una struttura specifica. RiskAnalyzer compila tutte le firme di ogni categoria in una singola regex per le prestazioni, usando preg_quote() per un escaping sicuro. ottimizzate all'avvio.
Probing di file sensibili. Le richieste dirette a file che non dovrebbero mai essere accessibili dall'esterno — file di configurazione, archivi di backup, directory di version control, dump di database — vengono segnalate con un punteggio dedicato. Questo intercetta la fase di ricognizione che tipicamente precede un attacco mirato.
Analisi delle anomalie dello user agent. Le stringhe user agent mancanti o sospettosamente corte ricevono una penalità di punteggio. I browser legittimi inviano sempre uno user agent sostanzioso; la sua assenza è un forte indicatore di strumenti automatizzati. I bot passivi noti — crawler dei motori di ricerca, servizi di monitoraggio — vengono identificati separatamente e valutati a un livello inferiore.
Analisi della lunghezza dell'URI. Le richieste con URI superiori a 200 caratteri ricevono un componente di punteggio aggiuntivo. URI anormalmente lunghi sono caratteristici degli attacchi di injection, dove il payload è incorporato nella query string.
Valutazione del codice di stato HTTP. Risposte 404 ripetute dallo stesso IP suggeriscono un probing sistematico di percorsi inesistenti — una tecnica di enumerazione classica.
I sei punteggi individuali vengono sommati in un punteggio di rischio composito, che viene poi classificato in cinque livelli di gravità: CLEAN, LOW, MEDIUM, HIGH e CRITICAL. Le soglie per ogni livello sono definite nella configurazione centralizzata, rendendo il sistema regolabile senza modifiche al codice.
La pipeline di elaborazione dei log
Lo script LogProcessor.php è la spina dorsale operativa del sistema. Viene eseguito come processo CLICommand Line Interface — lo script è progettato per essere eseguito dal terminale del server o da uno scheduler cron, non attraverso un browser web. Rifiuta esplicitamente l'esecuzione via HTTP per sicurezza., tipicamente attivato da cronUno scheduler di job basato sul tempo in Unix/Linux. Il processore di log di SecureLog è tipicamente pianificato per essere eseguito ogni pochi minuti, garantendo un'analisi quasi in tempo reale senza consumo costante di risorse. a intervalli regolari, ed esegue tre fasi distinte in sequenza.
Fase 1: Importazione incrementale dei log. Il processore legge i file di log di accesso per ogni sito monitorato, partendo dall'ultima posizione di offset nota. Questa è una scelta progettuale critica — il sistema non rielabora mai dati già visti, il che mantiene i tempi di esecuzione prevedibili indipendentemente dalla dimensione del file di log. Ogni riga di log viene analizzata usando un approccio ibrido: lo script tenta prima un parser regex standard per il Combined Log Format, e ricorre a un parser a delimitazione di tabulazione quando il formato devia. I dati analizzati vengono normalizzati: indirizzi IP, user agent e referrer vengono risolti in ID interni attraverso una cache in memoriaUn array associativo PHP che memorizza le lookup di database precedentemente risolte (siti, IP, user agent, referrer) per la durata del batch. Questo elimina le query SELECT ridondanti quando lo stesso IP o user agent appare migliaia di volte in un singolo file di log. supportata da lookup nel database, minimizzando le query ridondanti. Ogni riga viene poi passata attraverso il RiskAnalyzer, e sia il record di accesso che la sua valutazione del rischio vengono inseriti nel database usando operazioni batchInvece di eseguire un INSERT per ogni riga di log, il processore accumula i record e li esegue in batch configurabili. Questo riduce drasticamente il numero di round-trip verso il database e migliora il throughput su file di log di grandi dimensioni. per efficienza.
Fase 2: Risoluzione della geolocalizzazione. Dopo il completamento della fase di importazione, il processore identifica tutti gli indirizzi IP privi di dati geografici e li risolve attraverso chiamate API concorrenti a un servizio di geolocalizzazione. I risultati — paese, città, ISP e numero di sistema autonomoUn ASN (Autonomous System Number) identifica l'operatore di rete responsabile di un blocco di indirizzi IP. Conoscere l'ASN aiuta a distinguere il traffico proveniente da provider di hosting legittimi, servizi cloud e reti notoriamente malevole. — vengono memorizzati insieme al record dell'IP. Questo arricchimento è essenziale per le capacità di analisi geografica della dashboard e per identificare pattern come il traffico di attacco concentrato da regioni specifiche.
Fase 3: Elaborazione automatica dei ban. La fase finale è dove l'analisi diventa azione. La classe BanProcessor interroga il database degli eventi di rischio alla ricerca di indirizzi IP la cui attività cumulativa di minaccia supera soglie configurabili. Le soglie sono differenziate per gravità: un singolo evento CRITICAL può essere sufficiente a innescare un ban, mentre eventi di gravità LOW richiedono un conteggio più alto entro una finestra temporale di lookbackUna finestra temporale configurabile (default: 24 ore) entro la quale vengono contati gli eventi di rischio. Gli eventi più vecchi della finestra di lookback sono esclusi dal calcolo delle soglie, impedendo che dati obsoleti inneschino ban su IP il cui comportamento è cambiato. definita — tipicamente 24 ore. Quando un IP supera la soglia, il processore aggiorna il suo stato a BANNED e imposta il flag di sincronizzazione del firewall a PENDING, segnalando che la modifica non è ancora stata applicata a livello di sistema operativo.
L'intera esecuzione è protetta da un meccanismo di lock fileUna tecnica di mutua esclusione: lo script crea un file temporaneo all'avvio e lo rimuove al completamento. Se il lock file esiste già, lo script si interrompe, impedendo a due istanze di elaborare gli stessi dati contemporaneamente. che impedisce la sovrapposizione di istanze concorrenti — una salvaguardia essenziale quando l'elaborazione è pianificata a intervalli frequenti.
Sincronizzazione del firewall
Il ponte tra le decisioni di SecureLog e l'effettiva applicazione a livello di rete è SynchronizeFirewall.sh — uno script Bash che legge lo stato del database e applica le modifiche alla configurazione di firewalld del server attraverso gli ipsetCollezioni nominate di indirizzi IP gestite da firewalld. SecureLog mantiene due ipset: bad_ips per gli indirizzi IPv4 e bad_ipv6s per gli indirizzi IPv6. L'appartenenza a questi set attiva regole del firewall che bloccano tutto il traffico dagli IP elencati..
La sincronizzazione opera in quattro fasi, gestendo IPv4 e IPv6 separatamente per adattarsi alle diverse famiglie di ipset richieste da firewalld. Per ogni versione del protocollo, lo script elabora due operazioni: aggiunta (applicazione di nuovi ban) e rimozione (revoca dei ban per gli IP il cui stato è cambiato in ALLOWED o WHITELISTED). In ogni caso, lo script interroga esclusivamente i record dove firewall_status = 'PENDING', elabora solo quelle modifiche e aggiorna lo stato a APPLIED dopo l'esecuzione avvenuta con successo.
Questo design — separare la decisione (cosa bloccare) dall'applicazione (come bloccare) — offre diversi vantaggi. L'applicazione PHP non necessita mai di privilegi root; scrive soltanto nel database. Lo script Bash, che richiede permessi elevati per modificare firewalld, opera su un'interfaccia minimale e ben definita: una singola colonna del database che funge da coda di messaggi. Un meccanismo di sicurezza garantisce che un "IP sicuro" predefinito — tipicamente l'indirizzo dell'amministratore — non venga mai aggiunto a una lista di blocco, indipendentemente da ciò che produce l'analisi del rischio.
Dopo aver elaborato tutte le modifiche pendenti, lo script attiva un firewall-cmd --reload solo se almeno una modifica è stata effettuata, e produce un report riassuntivo di tutte le operazioni eseguite.
L'interfaccia della dashboard
Il frontend è un'applicazione a pagina singola strutturata attorno a cinque tab funzionali, accessibili attraverso una navigazione a sidebar scura. L'intero flusso di dati è asincrono: ogni vista si popola attraverso chiamate API a api.php, e l'interfaccia supporta il deep linking e la navigazione nella cronologia del browser attraverso un sistema di routing URLLa dashboard utilizza l'API HTML5 History (pushState/popState) per mantenere URL raggiungibili via bookmark per ogni tab e stato dei filtri. Navigare a /dashboard/?tab=logs&ip=1.2.3.4 ripristina la vista esatta. personalizzato.
Panoramica. Il tab principale presenta otto indicatori chiave di performance in una griglia di card: richieste totali, eventi critici negli ultimi sette giorni, IP bloccati, IP unici, nazioni uniche, traffico utile (sette giorni e totale) e minacce totali. Sotto i KPI, tre pannelli di visualizzazione mostrano il trend del traffico nell'ultima settimana come grafico a linea, la distribuzione dei codici di stato HTTP come grafico a ciambella e una classifica delle dieci pagine più visitate. Un quarto pannello — la tabella di scomposizione del rischio — mostra il conteggio degli eventi per ogni categoria di minaccia (scanner aggressivi, pattern di attacco, probing di file sensibili), fornendo una visione diretta sulla natura delle minacce rilevate.
Traffico & Log. Una tabella paginata e filtrabile che mostra i singoli record dei log di accesso con i relativi punteggi di rischio. Ogni riga può essere espansa per visualizzare i dettagli completi, e gli indirizzi IP sono cliccabili: selezionandone uno si filtra l'intera vista per mostrare tutte le richieste provenienti da quell'indirizzo. Da questo tab, i singoli IP possono essere bloccati o sbloccati con un'unica azione, e le operazioni massive consentono di bloccare o sbloccare tutti gli IP visibili nella pagina corrente o nell'intero set di risultati filtrati.
Gestione Ban. Una vista dedicata al monitoraggio e alla gestione dell'inventario completo degli IP. Ogni voce mostra l'indirizzo IP, la sua origine geografica, il punteggio di rischio medio calcolato dalla tabella risk_analysis_events e lo stato corrente (BANNED, ALLOWED o WHITELISTED). I filtri consentono di isolare gli IP per stato, nazione o livello di rischio. Da qualsiasi voce, l'amministratore può navigare direttamente alla cronologia completa dei log per quell'IP.
Blacklist. Un'interfaccia di blocco manuale per aggiungere indirizzi IP alla lista di blocco in modo proattivo — prima che l'analisi automatizzata li rilevi. Utile per integrare threat intelligence da fonti esterne o bloccare immediatamente attori malevoli noti.
Whitelist. L'inverso: un meccanismo di protezione che garantisce che indirizzi IP specifici — servizi di monitoraggio, sistemi partner, indirizzi dell'amministratore — non siano mai soggetti a ban automatizzato, indipendentemente dai loro pattern di traffico.
L'intera interfaccia supporta il filtro multi-sito: un selettore a tendina in cima alla pagina consente di passare tra dati aggregati per tutti i siti monitorati e viste filtrate per singoli domini. Questo rende SecureLog adatto ad ambienti che ospitano più proprietà web sulla stessa infrastruttura.
Progettazione della sicurezza
Uno strumento di monitoraggio della sicurezza che sia esso stesso insicuro sarebbe peggio che inutile — sarebbe un rischio. Il livello di autenticazione di SecureLog implementa diverse misure difensive che riflettono questa consapevolezza.
I cookie di sessione sono configurati con i flag secure, httponly e SameSite=Lax. L'attributo httponlyUn attributo del cookie che impedisce a JavaScript lato client di leggere il valore del cookie tramite document.cookie. È una difesa critica contro il session hijacking attraverso vulnerabilità XSS. impedisce a JavaScript di leggere il cookie di sessione, mitigando il session hijacking via XSS. L'attributo SameSite fornisce una protezione di base contro il CSRF. Tutto il traffico è forzato su HTTPS tramite redirect lato server, e il form di login valida un token CSRF ad ogni invio. I tentativi di autenticazione falliti vengono registrati con l'IP del client per scopi di audit, e un ritardo deliberato viene introdotto dopo i tentativi falliti per rallentare gli attacchi brute-force.
Sul lato API, ogni richiesta viene validata per l'autenticazione prima di qualsiasi operazione sui dati. L'API gateway restituisce risposte JSONJavaScript Object Notation — un formato leggero per lo scambio di dati. Tutta la comunicazione tra il frontend della dashboard e il backend api.php utilizza JSON, sia per i corpi delle richieste (via POST) che per le risposte. strutturate con codici di stato HTTP appropriati, e gli errori del database in produzione vengono registrati lato server senza esporre dettagli interni al client.
I componenti CLI impongono un contesto di esecuzione rigoroso: LogProcessor.php rifiuta l'esecuzione se acceduto via HTTP, e RiskAnalyzer.php blocca l'accesso diretto al file tramite browser. Sono protezioni semplici ma essenziali contro l'esposizione accidentale.
Il modello dati
Il design del database di SecureLog segue una struttura normalizzata incentrata su alcune tabelle principali. La tabella ip_addresses memorizza gli IP unici con i relativi metadati geografici. La tabella ip_management traccia lo stato di sicurezza di ogni IP (BANNED, ALLOWED, WHITELISTED) insieme al flag firewall_status (PENDING o APPLIED) — la colonna cruciale che guida il ciclo di sincronizzazione. I log di accesso sono memorizzati con chiavi esterne verso tabelle di lookup normalizzate per siti, indirizzi IP, referrer e user agent, mantenendo la tabella principale dei log compatta ed efficiente nelle query. Gli eventi di analisi del rischio sono registrati in una tabella separata collegata al log di accesso, abilitando query aggregate per gravità, intervallo temporale e IP senza scansionare l'intero log.
La separazione tra status (lo stato desiderato) e firewall_status (lo stato applicato) è la chiave di volta architettonica dell'intero sistema. Tutte le operazioni di scrittura nell'applicazione PHP — che siano innescate dal processore automatico di ban, da azioni manuali attraverso la dashboard, o dalla gestione di whitelist/blacklist — impostano firewall_status a PENDING. Lo script Bash di sincronizzazione consuma poi questi record pendenti e li applica a firewalld. Questo pattern è essenzialmente un'architettura event-drivenUn pattern di progettazione in cui i cambiamenti di stato vengono registrati come eventi in uno store condiviso, e i consumer a valle li elaborano indipendentemente. In SecureLog, la colonna del database funge da coda di eventi, l'applicazione PHP da produttore e lo script Bash da consumer. leggera, implementata senza l'overhead di una coda di messaggi dedicata.
Perché ho costruito questo sistema
Nel mio lavoro di gestione dell'infrastruttura web, mi sono trovato ripetutamente nella stessa situazione: il WAF faceva il suo lavoro filtrando il traffico, i log si accumulavano, ma il divario tra dati grezzi e processo decisionale informato rimaneva ampio. Le soluzioni SIEMSecurity Information and Event Management — piattaforme enterprise (come Splunk, IBM QRadar o Microsoft Sentinel) che aggregano dati di sicurezza da fonti multiple, correlano eventi e forniscono alerting. Efficaci ma tipicamente costose e complesse da implementare. commerciali esistono, ma sono tipicamente progettate per ambienti di scala enterprise e comportano costi di licenza sproporzionati per implementazioni di piccole e medie dimensioni. Alternative open-source come lo stack ELKElasticsearch, Logstash e Kibana — una piattaforma open-source di aggregazione e visualizzazione dei log. Potente e flessibile, ma richiede un'infrastruttura dedicata (tipicamente 8+ GB di RAM per il solo Elasticsearch) e manutenzione continua. sono potenti ma richiedono un'infrastruttura significativa e competenze operative per la manutenzione.
Volevo qualcosa di costruito ad hoc: uno strumento che potesse essere implementato a fianco di un web server esistente, che non richiedesse alcuna infrastruttura aggiuntiva oltre a un database MySQL, e che potesse chiudere il ciclo dall'analisi dei log all'applicazione delle regole del firewall senza intervento manuale. SecureLog è il risultato — non un aggregatore di log generico, ma un sistema specializzato progettato per una singola missione ben definita: comprendere il panorama delle minacce delle proprie applicazioni web e rispondervi automaticamente.
Il codice è strutturato per essere manutenibile da un singolo sviluppatore o da un piccolo team. Ogni file include documentazione inline estesa — non solo commenti che spiegano cosa fa il codice, ma perché sono state fatte determinate scelte, incluse note datate su bug fix e correzioni progettuali. Questo riflette un principio che applico in tutto il mio lavoro: il codice che non può essere compreso sei mesi dopo da qualcuno diverso dal suo autore è un debito tecnico, non un asset.
Conclusioni
SecureLog dimostra che un monitoraggio efficace della sicurezza web non richiede uno stack enterprise complesso e multi-livello. Un'applicazione PHP ben progettata, uno script Bash con i giusti privilegi, un database che funge da livello di coordinamento e una chiara separazione tra analisi, decisione e applicazione possono produrre un sistema che è simultaneamente trasparente, reattivo e manutenibile.
L'insight architetturale chiave è il ciclo chiuso: i log entrano nel sistema, vengono analizzati e valutati, i punteggi guidano decisioni automatizzate, le decisioni vengono sincronizzate con il firewall e i risultati sono visibili in tempo reale attraverso la dashboard. In ogni fase, l'amministratore mantiene il pieno controllo — i ban automatizzati possono essere sovrascritti, le whitelist proteggono gli indirizzi affidabili e la cronologia completa di ogni decisione è auditabile.
Se gestisci un'infrastruttura web e ti trovi di fronte a sfide simili — o se sei interessato a discutere i dettagli tecnici dell'implementazione — non esitare a contattarmi.