Guida completa all'implementazione di Netfilter e Suricata su Linux

Ultimo aggiornamento: 1 marzo 2026
  • NFQUEUE consente a Netfilter di delegare le decisioni di filtraggio e marcatura ai processi dello spazio utente, abilitando firewall e router IP dinamici.
  • Suricata fornisce un motore IDS/IPS multiprocesso con supporto per NFQUEUE, AF_PACKET e regole compatibili con Snort ed Emerging Threats.
  • L'integrazione di NFQUEUE con Suricata, database, Memcached o Pfsense consente di creare soluzioni di sicurezza e routing avanzate con software libero.
  • Le prestazioni dipendono in larga misura dalla progettazione dei thread e dalla logica dello spazio utente, per cui è fondamentale ottimizzare e selezionare attentamente il traffico da ispezionare.

Implementazione di Netfilter e Suricata

Se lavorate con reti su GNU/Linux ( le migliori distribuzioni Linux per sicurezza e privacy ) e siete interessati ad andare oltre il tipico firewall statico, probabilmente vi state chiedendo come combinare Netfilter, NFQUEUE e Suricata per costruire un IDS/IPS veramente flessibile senza spendere una fortuna in hardware proprietario. È proprio questo l'aspetto che esploreremo in questo articolo, integrando elementi di basso livello (kernel, code, C) con strumenti di alto livello (Suricata, regole, MySQL, Memcached, pfSense).

L'idea di base è molto potente: sfruttare il fatto che il kernel (vedi come ottimizzare il kernel Linux ) può accodare i pacchetti nello spazio utente e lasciare che un programma personalizzato decida cosa farne. Questo può essere utilizzato per il filtraggio del traffico (firewall avanzato, IPS), il routing dinamico o l'integrazione della logica di business (database, cache, rilevamento di attacchi alle applicazioni web, VoIP, ecc.). E se aggiungiamo Suricata come motore IDS/IPS multi-processo, otteniamo una combinazione molto robusta per ambienti che vanno dai laboratori ai data center ad alto traffico.

NFQUEUE e Netfilter: elevare il firewall allo spazio utente

In un tipico sistema GNU/Linux, le regole di Netfilter/iptables (o nftables) vengono solitamente utilizzate come policy statiche che risiedono interamente nello spazio kernel . Le interfacce e gli appliance (incluse molte soluzioni basate su Netfilter o Packet Filter di BSD) memorizzano la configurazione in file di testo, XML o SQLite e, quando qualcosa cambia, rigenerano e ricaricano le regole. Questo approccio è flessibile, ma la logica rimane una sorta di istantanea del firewall con piccole modifiche dinamiche (limiti di connessioni al secondo, conntrack, corrispondenza del paese, livello 7 se disponibile, ecc.).

Ciò che NFQUEUE propone è una vera rivoluzione: invece di lasciare che sia sempre il kernel a prendere la decisione finale, possiamo delegarla a un processo utente . Il kernel mette il pacchetto in una coda numerata e un'applicazione che utilizza la libreria libnetfilter_queue lo recupera, lo analizza e restituisce un verdetto: accettarlo, scartarlo o persino contrassegnarlo per l'instradamento tramite policy. È come avere un "giudice" programmabile, scritto in C, Python o Perl, sopra il firewall.

Il bello di tutto ciò è che il nostro programma può letteralmente fare qualsiasi cosa vogliamo: interrogare /dev/urandom, un database, un servizio web, una cache distribuita o un algoritmo sofisticato prima di rispondere al kernel. In termini architetturali, il firewall cessa di essere un semplice insieme di regole statiche e diventa una pipeline in cui Netfilter, code e applicazioni utente si incastrano come pezzi di un puzzle.

NFQUEUE è composto da due parti: il target NFQUEUE in iptables , che invia i pacchetti a una coda specifica, e la libreria utente libnetfilter_queue , che consente di leggere questi pacchetti ed emettere un verdetto. Non si tratta di un semplice sniffer come tcpdump: qui abbiamo la possibilità di decidere direttamente il percorso seguito dal pacchetto.

monitor di sistema avanzato per Linux
Articolo correlato:
Advanced System Monitor per Linux: una guida completa

Configurazione di base di iptables con NFQUEUE

Dal punto di vista di iptables, l'utilizzo di NFQUEUE è piuttosto semplice: si aggiunge una regola alla catena di cui si è interessati per inviare alla coda i pacchetti che soddisfano determinati criteri (indirizzo IP di origine/destinazione, porte, stati, moduli aggiuntivi come GeoIP o layer7 se disponibili, ecc.).

Ad esempio, se vogliamo inviare a NFQUEUE tutti i ping che arrivano all'host stesso:

iptables -I INPUT -p icmp -j NFQUEUE

Questo invia i pacchetti ICMP in entrata alla coda 0 (a meno che non sia specificato diversamente). Potremmo specificare un'altra coda con qualcosa come `--queue-num 3` . Quando elenchiamo le regole con i contatori (`iptables -L -n -v -x`), vedremo i contatori aumentare, indicando che i pacchetti vengono accodati . Un dettaglio importante: se ci sono pacchetti nella coda e nessun processo utente li recupera ed elabora, il comportamento predefinito è quello di rifiutarli, quindi un errore dell'applicazione, per impostazione predefinita, comporta il blocco del traffico.

Programmazione contro libnetfilter_queue: il “hello world” in C

Per unirsi alla coda dallo spazio utente, si utilizza la libreria libnetfilter_queue (che a sua volta si basa su libnfnetlink). Su distribuzioni come Debian, è sufficiente installare i pacchetti di sviluppo:

apt-get install libnfnetlink-dev libnetfilter-queue-dev gcc

Lo scheletro di un programma minimale che accetta sempre pacchetti consiste in pochi passaggi molto chiari: aprire la libreria, scollegare eventuali gestori esistenti, collegarsi al protocollo AF_INET, creare la coda con una funzione di callback, definire la modalità di copia ed entrare in un ciclo di ricezione . La funzione di callback viene eseguita per ogni pacchetto in coda, estraendo l'ID e restituendo il verdetto.

In pratica, il flusso è più o meno questo: `nfq_open` per ottenere l'handle, `nfq_unbind_pf` per liberarlo, `nfq_bind_pf` per associarlo ad AF_INET, `nfq_create_queue` per registrare la callback nella coda 0, `nfq_set_mode` per indicare se si desiderano i metadati o l'intero pacchetto, un ciclo con `recv()` sul descrittore e `nfq_handle_packet` per elaborare ciascun pacchetto . All'uscita, la coda viene distrutta con `nfq_destroy_queue` e l'handle viene chiuso con `nfq_close`.

Questo tipo di "hello world" consente una misurazione chiara dell'impatto di NFQUEUE. Se compiliamo l'esempio con qualcosa del tipo:

gcc -o nftest code.c -lnfnetlink -lnetfilter_queue

E se mettiamo in coda il traffico di un iperf (ad esempio, la porta TCP 5001 in INPUT e OUTPUT), vedremo che il codice che si limita ad accettare pacchetti influisce a malapena sulle prestazioni su una rete gigabit . Tuttavia, c'è un dettaglio fondamentale: la stampa di informazioni nella funzione di callback (printf, fflush, ecc.) penalizza significativamente il throughput, come si può notare confrontando iperf con e senza debug a schermo.

Opzioni NFQUEUE avanzate: bypass, bilanciamento e fail-open

NFQUEUE incorpora diverse interessanti opzioni di iptables che modificano il comportamento predefinito delle code e che è opportuno conoscere prima di entrare in un ambiente di produzione o ad alte prestazioni, poiché influenzano il modo in cui vengono gestiti gli errori delle applicazioni utente o il riempimento delle code.

Il comando `--queue-bypass` consente di garantire che, se nessun processo è in ascolto sulla coda, i pacchetti non vengano scartati ma inoltrati al successivo hop nella catena iptables. Questo può essere utile se si desidera che il sistema "si apra in caso di guasto" quando il servizio utente non è disponibile, sebbene da un punto di vista della sicurezza sia un'arma a doppio taglio.

L' opzione `--queue-balance` consente di distribuire i pacchetti su un intervallo di code (ad esempio, da 0 a 3) e quindi di avere più processi o thread indipendenti che consumano da ciascuna coda . Il codice di Netfilter garantisce che i pacchetti provenienti dallo stesso flusso finiscano sempre nella stessa coda, il che semplifica notevolmente il mantenimento della coerenza nella logica decisionale.

Esiste anche la modalità `--fail-open` , che controlla cosa succede quando la coda si riempie perché il processo utente è troppo lento. Abilitandola, il kernel accetta i pacchetti direttamente invece di scartarli, prevenendo così massicce interruzioni del traffico. Anche in questo caso, si può trattare di un problema di sicurezza, perché se vogliamo prendere decisioni caso per caso, la perdita dei pacchetti decisionali significa non riuscire a raggiungere tale obiettivo.

Per monitorare l'andamento delle code, Netfilter espone informazioni nel filesystem pseudo-files /proc/net/netfilter/nfnetlink_queue , che possono essere facilmente interrogate da script o strumenti di monitoraggio.

Integrazione della logica aziendale: test con Memcached e MySQL

Una volta che il processo "hello world" è sotto controllo, il passo successivo naturale è quello di arricchire la callback con chiamate a sistemi esterni . Un esperimento tipico prevede di decidere se accettare o rifiutare un pacchetto in base alla presenza o meno dell'indirizzo IP di origine in un qualsiasi backend, come un database MySQL o una cache Memcached.

  Come modificare le impostazioni DNS sul router per migliorare la velocità e la sicurezza

Nel caso di Memcached, il demone viene installato (apt-get install memcached) e viene caricata una chiave, ad esempio authorized , con l'indirizzo IP di nostro interesse. Possiamo farlo con un semplice comando echo e netcat, e poi verificare con un comando get che il valore sia memorizzato correttamente. A questo punto, il programma NFQUEUE, oltre a ottenere l'ID del pacchetto, riceve l'intero pacchetto utilizzando NFQNL_COPY_PACKET , estrae l'intestazione IP (struct iphdr) e converte l'indirizzo sorgente in una stringa con inet_ntop.

Per evitare di sprecare tempo aprendo connessioni con ogni pacchetto, la connessione Memcached viene inizializzata una sola volta nel metodo main (memcached_create, memcached_server_list_append, memcached_server_push) e il gestore viene memorizzato in variabili globali. Nella funzione di callback, viene chiamata memcached_get con la chiave desiderata, l'indirizzo IP di origine viene confrontato con il valore recuperato e, se corrispondono, viene restituito NF_ACCEPT; altrimenti, viene restituito NF_DROP. Se la chiave non esiste o si verifica un errore, il pacchetto viene scartato per precauzione.

Utilizzando iperf, questa strategia riduce la velocità di trasmissione a circa 140 Mbit/s su una rete gigabit , e si osserva che la coda inizia a subire perdite (indicate, ad esempio, da simboli all'interno del codice stesso). In altre parole, la semplice chiamata di un servizio di cache per ogni pacchetto comporta già un costo significativo, sebbene rimanga una soluzione praticabile per volumi di traffico medi se ottimizzata.

Con MySQL, l'approccio è simile ma più complesso: vengono installate la libreria server e client, viene creato un database (ad esempio, nfqueue) con una semplice tabella chiamata authorized(ip varchar(50)) e viene inserito l'indirizzo IP consentito. Nel programma, `mysql_init` e `mysql_real_connect` vengono eseguiti all'avvio e nella funzione di callback viene costruita una query come `select * from authorized where ip like 'xxxx'`. Se la query viene eseguita correttamente e viene trovata una riga, il pacchetto viene accettato; altrimenti, viene scartato.

Con la cache delle query MySQL abilitata, i test producono circa 188 Mbit/s , che scendono a 103 Mbit/s quando la cache delle query è disabilitata. Questi valori, pur essendo lontani dai gigabit, dimostrano che anche con l'approccio meno elegante (single-thread, senza ottimizzazione) , è possibile gestire volumi di traffico rispettabili utilizzando decisioni basate sul database o sulla cache.

Prestazioni, multithreading e utilizzo della CPU

I test con iperf, Memcached e MySQL dimostrano chiaramente che il limite prestazionale non è imposto tanto da NFQUEUE in sé, quanto dalla logica che aggiungiamo nello spazio utente e da come la implementiamo. Un eseguibile che restituisce solo NF_ACCEPT raggiunge quasi un gigabit senza problemi; non appena introduciamo operazioni di I/O o chiamate di rete, la velocità di trasmissione cala e la CPU della macchina NFQUEUE, del demone Memcached o di MySQL viene spinta al limite.

Dal punto di vista architetturale, ciò ha due implicazioni. Da un lato, conferma che delegare le decisioni del firewall alle applicazioni utente per volumi di traffico significativi è perfettamente fattibile , a patto che si tenga conto dei costi effettivi di ogni chiamata. Dall'altro lato, dimostra che per sfruttare al massimo le capacità della piattaforma, è necessario considerare il multithreading o il multiprocessing . NFQUEUE consente di distribuire il traffico su più code; potremmo avviare diverse copie della nostra applicazione, ognuna in ascolto su una coda diversa, e sfruttare più core senza la complessità di pthreads o di fork massivi.

Un'altra ottimizzazione ovvia sarebbe quella di limitare il traffico che passa attraverso NFQUEUE . Nei test, l'intero flusso iperf veniva messo in coda, ma in uno scenario reale potremmo mettere in coda solo i pacchetti con stato NEW, consentire il passaggio dei pacchetti ESTABLISHED/RELATED e riservare la logica più complessa per i login o per i pattern sospetti.

In definitiva, l'utilizzo della CPU e la progettazione dei thread sono fondamentali: se il processo utente non è all'altezza, la coda si riempie e dobbiamo ricorrere a strumenti come fail-open o accept drops, perdendo parte del controllo preciso a cui mira questo approccio.

Routing dinamico con marchio Netfilter

NFQUEUE non si limita a dire semplicemente "accetta" o "getta". Può essere utilizzato anche per applicare flag Netfilter (fwmark) ai pacchetti e combinarli con ip rule e iproute2 per creare schemi di routing politico in stile VRF altamente flessibili e quasi leggeri.

In linea generale, la procedura sarebbe la seguente: definire diverse tabelle di routing in /etc/iproute2/rt_tables , ad esempio una per la connessione lenta e una per quella veloce; assegnare a ciascuna tabella una diversa rotta predefinita (una tramite fibra e un'altra tramite un collegamento più limitato); utilizzare la regola ip per specificare che i pacchetti con fwmark 1 vadano alla tabella veloce, quelli con fwmark 2 alla tabella lenta, ecc.; e infine, utilizzare NFQUEUE per contrassegnare i pacchetti in modo appropriato prima di restituire il verdetto.

Per impostare un verdetto dalla callback, si usa `nfq_set_verdict2` , che è simile a `nfq_set_verdict` ma consente di impostare un valore di verdetto che `ip rule` vedrà in seguito. Combinando tutto ciò, è possibile costruire un router IP che decide dove instradare in base a criteri arbitrari: da cose assurde come la dimensione pari/dispari dei pacchetti a input esterni come algoritmi di previsione del traffico, eventi sui social media o segnali provenienti da sistemi di monitoraggio.

Il risultato è un sistema in cui il kernel continua a inoltrare i pacchetti alla velocità usuale, ma il percorso esatto che ogni flusso segue è delegato a un software esterno che può cambiare idea in tempo reale senza modificare regole statiche.

NFQUEUE e Suricata: IPS di alto livello in GNU/Linux

Tutto quanto sopra può essere programmato manualmente in C, ma quando si tratta di rilevamento delle intrusioni e ispezione approfondita dei pacchetti, l'opzione più sensata è solitamente quella di affidarsi a un motore IDS/IPS maturo . È qui che entra in gioco Suricata, nato proprio come alternativa multi-processo a Snort, con funzionalità IPS fin dall'inizio e una forte attenzione allo sfruttamento dei numerosi core CPU oggi disponibili.

Suricata è stato scritto da zero e distribuito con licenza GPLv2 ; l'Open Information Security Foundation (OISF) gestisce sia il motore che un ecosistema piuttosto completo di regole e documentazione. A differenza di Snort 2.x, che ha ereditato un core a singolo thread e vi è stato applicato tramite patch, Suricata è stato progettato per suddividere il carico di lavoro su più thread: acquisizione, decodifica, rilevamento e output, con diverse strategie di ripartizione del carico.

A livello funzionale, Suricata offre supporto nativo per IPv6, ispezione di livello 7 (HTTP tramite libreria HTP molto avanzata), riconoscimento del protocollo indipendente dalle porte , ricostruzione del flusso e un sistema molto potente di variabili di sessione (flowbit) per correlare le diverse fasi di un attacco distribuito su più connessioni TCP.

Un ulteriore punto di forza è la sua compatibilità con le regole di Snort e la capacità di utilizzare sia i set di firme di Sourcefire VRT che quelli di Emerging Threats (le versioni gratuite ET Open e a pagamento ET Pro). Inoltre, esporta gli eventi in formati molto utili (fast.log, JSON in eve.json) per l'integrazione con SIEM, ELK, Splunk e altri sistemi.

Suricata come IPS in Linux: modalità di cattura e NFQUEUE

Su GNU/Linux, Suricata può operare in diverse modalità a seconda di come viene intercettato il traffico: NFQUEUE, AF_PACKET, PF_RING, libpcap, NFLOG, IPFW, DAG, Napatech … Ognuna ha i suoi vantaggi e requisiti. A livello di puro IPS, le due più importanti sono NFQUEUE e AF_PACKET.

Nella modalità NFQ (NFQUEUE) , il flusso è simile a quello descritto in precedenza: un insieme di regole iptables invia i pacchetti a una coda; Suricata, in esecuzione nello spazio utente, legge da tale coda, ne ispeziona il contenuto secondo le proprie regole e restituisce un verdetto al kernel: NF_ACCEPT, NF_DROP o NF_REPEAT. Quest'ultima opzione può essere utilizzata per reinserire il pacchetto nella stessa tabella iptables dopo aver applicato ulteriori marcatori o modifiche.

Questa modalità è molto flessibile e facile da implementare nelle infrastrutture esistenti , poiché richiede solo la modifica delle regole in punti specifici (ad esempio, FORWARD, INPUT, OUTPUT) lasciando tutto il resto invariato. Il costo è rappresentato dal sovraccarico aggiuntivo dovuto al passaggio dei pacchetti attraverso NFQUEUE, con il già citato impatto se il volume è molto elevato o le regole richiedono molte risorse.

In modalità AF_PACKET , Suricata opera più vicino all'interfaccia di rete, copiando i pacchetti attraverso i socket AF_PACKET. Questo approccio a copia zero è molto più veloce , ma richiede che il sistema funzioni come un gateway con due interfacce e che il blocco del traffico venga eseguito a livello di inoltro tra le schede di rete: il pacchetto da bloccare semplicemente non viene passato dall'interfaccia di input all'interfaccia di output.

  Le migliori alternative sicure a Google Drive per recuperare la tua privacy

In entrambe le modalità, Suricata può essere combinato con Netfilter, ma NFQUEUE si adatta particolarmente bene agli scenari in cui si desidera riutilizzare tutta la logica di iptables (policies, intervalli, regole precedenti) e inviare a Suricata solo il traffico che si desidera analizzare in dettaglio.

Installazione di base di Suricata dal codice sorgente

Per coloro che preferiscono compilare Suricata invece di usare i pacchetti, il processo sulle distribuzioni di tipo Debian/Ubuntu prevede innanzitutto l'installazione delle dipendenze di compilazione (build-essential, libpcre, libpcap-dev, libnet-dev, libyaml-dev, zlib, libcap-ng-dev, libjansson-dev, ecc.), il download del tarball dal sito ufficiale e l'esecuzione dei classici ./configure, make, make install.

Durante la fase di configurazione, lo script indicherà quali funzionalità di supporto sono state abilitate: AF_PACKET sì/no, PF_RING, NFQUEUE sì/no, NFLOG, IPFW, supporto per libnss, libjansson, Prelude, PCRE JIT, Lua, GeoIP, ecc. È importante verificare che NFQUEUE sia abilitato se si desidera lavorare in tale modalità e che la libreria di acquisizione di interesse sia stata individuata.

Dopo aver installato il binario, è possibile eseguire `make install-conf` per distribuire una configurazione predefinita in `/etc/suricata` e `make install-rules` per scaricare e posizionare un set di regole sulle minacce emergenti in `/etc/suricata/rules`. Questi set possono quindi essere aggiornati utilizzando strumenti come `suricata-update`.

Sui sistemi Red Hat/CentOS, la logica è simile, utilizzando yum o dnf per le dipendenze (libpcap-devel, pcre-devel, libnet-devel, libyaml-devel, jansson-devel, ecc.) e quindi compilando con gli stessi passaggi. Per motivi di prestazioni, è anche consigliabile disabilitare LRO/GRO nell'interfaccia di acquisizione tramite ethtool, poiché queste funzioni di offload possono influire sulla visibilità dei pacchetti a livello IDS.

Configurazione di Suricata: YAML, variabili e threading

La configurazione principale di Suricata risiede nel file /etc/suricata/suricata.yaml . Si tratta di un file YAML abbastanza leggibile e ricco di commenti, in cui vengono definiti tutti gli aspetti, dai percorsi dei log e i set di regole alle policy del sistema operativo di destinazione e ai parametri di threading.

Uno dei campi base è `default-log-dir` , che specifica dove verranno memorizzati i file di log (per impostazione predefinita, `/var/log/suricata`). Nella sezione `vars` sono presenti variabili come `HOME_NET`, `EXTERNAL_NET`, `HTTP_PORTS`, `SHELLCODE_PORTS` e `SSH_PORTS`, che fungono da abbreviazioni nelle regole. `HOME_NET` viene solitamente configurato con l'intervallo di rete locale che si desidera proteggere, mentre `EXTERNAL_NET` è in genere definito come `!HOME_NET`.

Un altro elemento importante è la policy host-os-policy , che indica a Suricata quale sistema operativo deve essere utilizzato su determinati intervalli di indirizzi IP. Questo permette di adattare il modo in cui il protocollo TCP viene riassemblato o come vengono interpretati alcuni comportamenti dello stack di rete , rendendo più difficile eludere i protocolli basandosi sulle differenze tra gli stack (Windows vs. Linux, ecc.). È possibile assegnare intervalli specifici a categorie come Windows, Linux, BSD, Vista, Windows 2003, ecc.

Per quanto riguarda il multithreading, la sezione dedicata consente di ottimizzare l'affinità della CPU e il numero di thread di rilevamento. Di default, `set-cpu-affinity` è solitamente disabilitato, consentendo allo scheduler di sistema di distribuire i thread tra i core. Il parametro `detect-thread-ratio` indica quanti thread di rilevamento vengono creati per ogni core disponibile; con `detect-thread-ratio: 1.5` su una macchina a 8 core, Suricata genererà 12 thread di rilevamento, oltre ai thread di acquisizione e gestione.

L'intero modello si riflette poi nell'output all'avvio del demone: sono visibili un thread di acquisizione (ad esempio, pcap) e più thread di rilevamento, oltre ai gestori di flusso e ai gestori di statistiche. Questa architettura multi-processo è ciò che consente a Suricata di scalare molto meglio rispetto ai motori a singolo thread quando si trova di fronte a collegamenti a 10/40 Gbit/s.

Aggiornamenti delle regole e delle firme in Suricata

Suricata si basa su insiemi di regole per rilevare schemi di attacco, comportamenti anomali e abusi di protocollo. Oltre ad accettare regole in formato Snort , l'ecosistema più comune è quello di Emerging Threats: ET Open (gratuito) e ET Pro (commerciale), con regole orientate alle minacce attuali.

Molte distribuzioni moderne includono lo strumento `suricata-update` , che semplifica la gestione delle regole: aggiorna le sorgenti, abilita o disabilita provider specifici e scarica le versioni più recenti dei set di firme. Un flusso di lavoro tipico prevede l'installazione di `suricata-update` (ad esempio, tramite pip), la prima esecuzione di `suricata-update` per scaricare ET Open, l'elenco delle sorgenti con `suricata-update list-sources`, l'abilitazione di sorgenti aggiuntive come `ptresearch/attackdetection`, `oisf/trafficid` o `sslbl/ssl-fp-blacklist` e la successiva esecuzione di `suricata-update` per rigenerare il file delle regole.

Il file suricata.yaml viene modificato per puntare al percorso corretto delle regole e, da lì, Suricata inizierà a generare eventi di allerta che verranno registrati in fast.log (testo veloce e leggibile) e eve.json (JSON strutturato con informazioni molto complete) . Quest'ultimo formato è particolarmente utile per alimentare dashboard, sistemi di correlazione o script personalizzati.

Oltre alle firme, Suricata integra decodificatori e parser per molteplici protocolli , il che le consente di essere meno dipendente dalle porte: può identificare il traffico HTTP anche se passa attraverso porte non standard, rilevare SSH, TLS, DNS, ecc. su diverse porte e livelli di incapsulamento (inclusi tunnel misti IPv4/IPv6).

Utilizzo pratico: dal rilevamento degli exploit web al blocco automatico

Uno dei casi d'uso più richiesti negli ambienti di hosting o nei data center è quello di rilevare in tempo reale i tentativi di sfruttamento delle vulnerabilità nelle applicazioni web (ad esempio, WordPress e i suoi plugin) e reagire automaticamente, solitamente bloccando o inserendo l'indirizzo IP di origine nella blacklist del firewall.

Suricata, grazie a regole aggiornate, è in grado di riconoscere specifici schemi di attacco contro URL, parametri, payload HTTP e persino sequenze di richieste che corrispondono a exploit noti. L'IDS può operare in modalità passiva, ricevendo il traffico tramite mirroring da una porta dello switch (SPAN), ma per fungere da IPS e bloccare gli attacchi, deve essere integrato con il piano di inoltro.

Esistono due approcci comuni: configurare l'IDS come un bridge online, in modo che il traffico passi fisicamente attraverso la macchina (utilizzando iptables, AF_PACKET o PF, a seconda della piattaforma), oppure lasciare la topologia invariata ma combinare il mirroring con azioni sul firewall centrale tramite API, script o NFQUEUE . Il primo approccio minimizza la latenza tra il rilevamento e il blocco, a costo di aggiungere un ulteriore elemento "nel mezzo" della rete; il secondo offre maggiore flessibilità e resilienza, ma introduce maggiore complessità nell'orchestrazione.

È perfettamente possibile per un sistema di rilevamento delle intrusioni (IDS) rilevare un tentativo di sfruttare una vulnerabilità in un plugin di WordPress e quindi, direttamente o tramite un componente associato, aggiungere l'indirizzo IP dell'attaccante a una blacklist di iptables. Ciò può essere fatto tramite l'output JSON di Suricata e script che richiamano iptables/nftables , oppure delegando parte della logica a NFQUEUE, dove il motore stesso o un processo associato prende la decisione al volo senza attendere l'aggiornamento di una lista esterna.

Ciò consente di concentrarsi sulle minacce realmente importanti (exploit, tentativi di escalation, scansioni molto aggressive), ignorando o semplicemente registrando rumori di fondo come le scansioni di porte di base che, in molti contesti, non sono di per sé preoccupanti.

Suricata su Pfsense: firewall open source con IDS/IPS integrati

Non tutti possono o vogliono permettersi un firewall proprietario di fascia alta come Palo Alto. In molti contesti, è più conveniente implementare una soluzione open source con pfSense e Suricata , che copre sia le esigenze avanzate di un firewall (multi-WAN, VLAN, VPN, NAT, ecc.) sia quelle di un sistema IDS/IPS.

PfSense, basato su FreeBSD e Packet Filter, funziona particolarmente bene con ambienti virtualizzati (Proxmox, KVM, ecc.), con l'eccezione che si consiglia di utilizzare schede E1000 anziché Virtio nelle macchine KVM per evitare problemi di prestazioni e crash sotto carico, a meno che non si seguano le raccomandazioni di Netgate (disabilitare l'offload hardware del checksum in Sistema > Avanzate > Rete e riavviare, tenendo presente che questo potrebbe non essere sufficiente con carichi molto elevati).

I requisiti hardware minimi per un laboratorio con Suricata su Pfsense possono essere modesti (1 CPU da 500 MHz, 1 GB di RAM, 4 GB di spazio su disco), ma per un utilizzo professionale si raccomandano almeno 2 CPU, 4 GB di RAM e 16 GB di spazio di archiviazione , senza dimenticare di avere diverse interfacce di rete (una per la WAN, una per la LAN, e di più se si desiderano più WAN o VLAN complesse).

  Cybersecurity 101: proteggi i tuoi dati

L'installazione di pfSense è molto rapida: si avvia dall'ISO, si accetta la licenza, si sceglie di installare, si seleziona la lingua e il layout di tastiera, si lascia il partizionamento automatico (Auto UFS se si intende utilizzare l'intero disco) e in pochi minuti il ​​sistema è pronto per il primo avvio. La console offre un menu per l'assegnazione delle interfacce, il riavvio, l'avvio della shell, ecc.

In laboratorio, ad esempio in VirtualBox, è comune disabilitare temporaneamente il firewall pfsense dalla console con il comando `pfctl -d` per accedere all'interfaccia web tramite la WAN (nome utente admin, password pfsense) e completare la procedura guidata iniziale: dati generali, server NTP, configurazione WAN (in laboratorio di solito è sufficiente il DHCP), LAN, modifica della password di amministratore e applicazione della configurazione.

Una volta stabilizzato l'accesso, è possibile creare una regola nel firewall WAN che consenta HTTPS da qualsiasi origine all'indirizzo IP di pfSense, aggiungendo separatori descrittivi per organizzare visivamente le regole (ad esempio, "Accesso firewall"). Si consiglia inoltre di disabilitare l'opzione per bloccare le reti private sulla WAN se ci si trova in un ambiente di test con indirizzi RFC1918, per evitare di dover utilizzare costantemente `pfctl -d`.

Installazione di Suricata su pfSense e panoramica

Con pfSense di base attivo e funzionante, installare Suricata è semplicissimo: basta andare su Sistema > Gestione pacchetti > Pacchetti disponibili , cercare Suricata e installare il pacchetto. Il processo scarica diversi file e potrebbe richiedere del tempo a seconda dell'hardware, ma è completamente guidato tramite l'interfaccia web.

Una volta installato, nella scheda Servizi compare una voce relativa a Suricata, dove è possibile configurare le istanze per interfaccia (WAN, LAN, VLAN, ecc.), scegliere i set di regole da utilizzare, attivare la modalità IDS o IPS e regolare i parametri di prestazioni e registrazione. La gamma di opzioni è ampia (sufficiente per articoli interi dedicati esclusivamente alla configurazione), ma il vantaggio è che molte operazioni che in Linux richiedono la modifica manuale del file YAML vengono gestite qui tramite moduli e caselle di controllo.

Nota importante: sebbene in un ambiente di test possa essere allettante esporre l'amministrazione di pfSense direttamente a Internet, in produzione è fondamentale limitare l'accesso agli indirizzi IP statici, utilizzare VPN per la gestione remota ed evitare a tutti i costi di lasciare la console web esposta . pfSense è molto flessibile, ma deve essere trattato come l'elemento critico che è.

Con Suricata abilitato su pfSense, si ottiene un ambiente in cui il traffico passa attraverso pfSense per le funzioni di firewall e NAT, e Suricata lo ispeziona in base alle proprie regole e può bloccarlo in modalità IPS . Questa combinazione, gestita da un'unica interfaccia web, semplifica notevolmente l'implementazione della protezione DPI nelle reti di piccole e medie dimensioni.

In molte distribuzioni, questo è completato da una connessione di Pfsense/Suricata a una piattaforma SIEM o di log centralizzata, sfruttando formati di output strutturati per correlare gli eventi e rilevare campagne più ampie.

Monitoraggio degli eventi e registri di esempio in Suricata

Una volta avviato Suricata, gli eventi vengono registrati nel percorso definito da default-log-dir, solitamente /var/log/suricata . Il file fast.log utilizza un formato di testo compatto con timestamp, ID delle regole, classificazioni e priorità, adatto per una rapida consultazione dal terminale (tail -f).

Ad esempio, quando si incontra traffico con checksum TCP errati, potremmo vedere righe come queste: timestamp con data e ora, seguiti dall'identificativo della regola (ad esempio, 1:2200074:1), il messaggio "SURICATA TCPv4 checksum non valido", classificazione, priorità e coppia IP/porta di origine e destinazione. Questi tipi di avvisi consentono l'identificazione rapida di problemi di integrità dei pacchetti o tentativi di elusione.

Il file eve.json contiene gli stessi eventi in formato JSON, con campi quali timestamp, event_type, src_ip, dest_ip, src_port, dest_port, proto e un sottofile di avviso con action, gid, signature_id, rev, signature, category e severity. Questo formato può essere facilmente importato da Logstash, Fluentd, Filebeat o qualsiasi altro agente di log , consentendo analisi molto più approfondite rispetto al semplice utilizzo del testo semplice.

Quando si implementa Suricata su un server multi-core (ad esempio, 8 core), la compressione dei thread è facilmente visibile in strumenti come htop in modalità thread, che mostra uno o più thread di acquisizione (pcap, AF_PACKET o NFQ) e un gran numero di thread di rilevamento distribuiti tra i core. La regolazione del rapporto tra thread di rilevamento e affinità della CPU può avere un impatto significativo sulla velocità di trasmissione e sulla latenza quando il volume di traffico si avvicina ai limiti della piattaforma.

Prima di implementarlo in produzione, è consigliabile dedicare del tempo alla messa a punto dei set di regole attivati ​​per evitare un'ondata di falsi positivi che potrebbero bloccare il traffico legittimo o intasare i log. Suricata-update consente di disabilitare intere categorie o singole regole per trovare un giusto equilibrio tra sensibilità e usabilità.

Applicazioni speciali: VoIP, analisi audio e NFQUEUE creativo

Oltre agli utilizzi classici (protezione dei servizi web, rilevamento di malware, analisi DDoS), la combinazione Netfilter+NFQUEUE consente soluzioni piuttosto creative in ambiti come il VoIP. Ad esempio, è possibile configurare un filtro anti-SPIT (spam su telefonia IP) o un sistema per censurare le parolacce nei flussi RTP.

L'idea sarebbe la seguente: identificare il traffico RTP tramite porte o riconoscimento di protocollo e inviarlo a NFQUEUE; dall'applicazione utente, ricostruire il flusso RTP utilizzando una libreria come librtp , estrarre l'audio in formato WAV e passarlo a un motore di riconoscimento di parole chiave (wordspotting), come ad esempio una libreria di sintesi o riconoscimento offerta da terze parti.

In base alle parole rilevate, il processo NFQUEUE potrebbe decidere di consentire, bloccare o persino modificare la riproduzione inserendo un segnale acustico nel flusso, sebbene quest'ultima opzione richieda un controllo molto preciso di RTCP, sequenze di pacchetti e tempistiche, quasi un approccio man-in-the-middle. Non è banale, ma in teoria è perfettamente realizzabile sfruttando lo stesso sistema di coda e di verdetto.

È vero che parte di questo potrebbe essere fatto con un semplice sniffer che invia i dati a un processore esterno, il quale agisce poi sulla segnalazione SIP o tramite un SBC (Asterisk, Kamailio, ecc.). La differenza con l'utilizzo di NFQUEUE è che l'azione sul flusso RTP può essere immediata e diretta , senza la necessità di coordinare più componenti o di attendere il completamento della chiamata a livello di segnalazione.

Questi scenari illustrano chiaramente il potenziale della combinazione GNU/Linux + Netfilter + Suricata + librerie di terze parti: non si tratta solo di bloccare porte e indirizzi IP, ma di orchestrare decisioni complesse sul traffico in tempo reale utilizzando un ecosistema di software libero al 100%.

Considerando l'intero percorso, dal piccolo programma C che accetta sempre pacchetti a una distribuzione Suricata multiprocesso integrata con NFQUEUE, Pfsense, database e cache, si può apprezzare la flessibilità che questo stack tecnologico offre per realizzare di tutto, dai semplici firewall dinamici alle architetture IDS/IPS su scala di data center, con reali capacità di ispezione approfondita e risposta automatizzata ad attacchi sempre più complessi.