In questa lezione impareremo a conoscere Iptables e alcuni concetti che stanno alla base della gestione del firewall su un sistema operativo Linux, dal momento che è questo che abbiamo installato sulla nostra macchina virtuale.
Cos’è Iptables?
Iptables è l’applicazione a livello dello user space che si interfaccia con il componente netfilter nel kernel space di Linux, definendo il funzionamento di quest'ultimo. Solitamente, anche se in maniera impropria, ci si riferisce all'intero set di applicazioni e moduli con il nome dell'applicazione.
Netflilter consente il filtraggio stateful dei pacchetti di rete. Adoperandolo, è possibile sia implementare un sistema concepito per svolgere le funzioni di router a vantaggio di un insieme di dispositivi ad esso connessi (qualora il sistema su cui è alloggiato disponga di più interfacce di rete), sia filtrare il traffico in ingresso verso un sistema con una sola interfaccia di rete intercettando ciò che non desideriamo far transitare verso lo stesso.
Come funziona?
Un firewall è un’entità che svolge la funzione di controllo del traffico proveniente dalla rete, che raggiunge un segmento del nostro network. Tutto ciò che viaggia sulla rete è suddiviso in pacchetti, ovvero unità di dati che, oltre al payload (ovvero il carico utile), veicolano informazioni necessarie al loro instradamento.
Netfilter è quindi un firewall, più precisamente di tipo stateful. Il filtraggio stateful tiene conto delle relazioni fra i pacchetti di rete, quelli più vecchi e quelli in arrivo, in modo da identificare pacchetti che non rispondono a logiche prevedibili. Volendo semplificare al massimo, facciamo un esempio: se desideriamo visionare un video in streaming, avremo la necessità di avviare una serie di chiamate dal nostro sistema, ed un servizio esterno risponderà con un flusso di dati indirizzati verso il sistema che lo ha interrogato. Questo, generalmente, avviene in modi precisi e prevedibili a priori. Se accade qualcosa di differente, in modalità difformi o con tempistiche incongruenti, il flusso di dati in entrata sarà ritenuto sospetto perché potrebbe rappresentare una possibile minaccia.
Lo stesso ragionamento può essere allargato e generalizzato per un server protetto da firewall. Più in dettaglio, attraverso l'uso di iptables creeremo delle tabelle di regole (tables), concatenate in modo da essere eseguite in sequenza (chains). Ciò ci permetterà di definire una ACL (Access Control List), la lista per il controllo accessi, processata da netfilter. Nelle chains specificheremo le caratteristiche dei pacchetti che vogliamo siano sottoposti al controllo da parte del firewall. Tali caratteristiche rappresentano il cosiddetto match, che attiverà uno specifico automatismo chiamato target. Se un pacchetto passerà indenne oltre le catene, potrà dirsi autorizzato a proseguire senza modifiche sino a che non incapperà nella politica di default che sarà adottata per tutti i pacchetti non intercettati da alcun match.
Le tabelle più utilizzate sono essenzialmente due: nat e filter. Per questo motivo, nel seguito approfondiremo il funzionamento generale di queste ultime.
Componenti di base e installazione
Di norma, dopo l’installazione di un sistema operativo Linux, esso dispone già di tutto quello che occorre per utilizzare iptables. Ovviamente dovremo verificare che sia così. Il modo più semplice per farlo è aprire una console sul sistema che dovrà svolgere le funzioni di firewall, e digitare il comando:
iptables –list
Se la risposta che otterremo consisterà in una tabella, eventualmente anche vuota, allora vorrà dire che iptables è pronto ed in esecuzione sul sistema. Se così non fosse, sarà sufficiente installarlo tramite il package manager del nostro sistema operativo (che, nel caso di Ubuntu, è apt). Quant’altro dovesse servire giungerà a corredo con le dipendenze. L’installazione comporta di norma l’avvio automatico del servizio.
Vediamo ora come verificare che le catene siano vuote e, sempre se necessario, facciamo il reset di esse che eventualmente troviamo già in parte “configurate”. Per farlo, è sufficiente il comando seguente:
iptables –F
Cosa occorre per farlo funzionare?
A questo punto, è bene comprendere come istruire regole per la definizione del comportamento del firewall, dipendentemente dalle varie tipologie di pacchetti.
Da console, è possibile ottenere l’elenco delle regole inserite in una tabella:
iptables -L -t <nome_tabella>
Chiediamoci quindi quale comportamento di default desideriamo adottare nel caso in cui nessuna regola venga attivata dalle “condizioni” che abbiamo previsto.
Facendo attenzione al modo in cui scriviamo (argomenti e target sono case sensistive), con l’opzione -P
specifichiamo la policy di default di una catena. Ad esempio, possiamo stabilire di scartare ogni pacchetto non intercettato con la seguente regola:
iptables -P INPUT DROP
È bene tener presente che quando usiamo un’istruzione senza specificare la tabella in cui intendiamo eseguirla, questa viene indirizzata verso la catena di default, ovvero la catena FILTER. Con la regola appena citata inibiamo, quindi, l’ingresso a tutto quello che non viene intercettato da una regola nella catena INPUT della tabella FILTER. Ovviamente possiamo fare lo stesso anche per un’altra catena di una specifica tabella, ad esempio utilizzando il comando:
iptables -P PREROUTING ACCEPT -t mangle
Quest’ultimo imposta il comando ACCEPT quale predefinito sulla catena di prerouting di mangle.
Configurazione iniziale
Al primo utilizzo, Netfilter avrà alcune tabelle preimpostate:
- La tabella filter è deputata a fungere da argine per inibire l’accesso ai pacchetti indesiderati.
- La tabella nat consente di tradurre un flusso di dati che vogliamo indirizzare ad un nostro server. È quindi possibile impostare il NAT per modificare gli indirizzi dei pacchetti in modo da indirizzarli verso specifici server.
- La tabella mangle è adoperata per modificare i pacchetti.
- La tabella raw è utilizzata per agire su pacchetti che non vogliamo porre in relazione con gli altri pacchetti.
- La tabella security è adoperata per il controllo degli accessi di tipo discrezionale (DAC), in cui cioè si mettono in relazione gli utilizzatori con i creatori delle risorse che decidono autonomamente le regole per l’accesso a queste ultime.
Match e Target
Gli argomenti (o flag) dei match specificano i criteri che attivano una regola. Ogni flag può essere negato adoperando il punto esclamativo subito dopo la sua invocazione. Ad esempio, la stringa seguente intercetta tutti i pacchetti che non sono tcp:
-p ! tcp
Possiamo usare -p
per il protocollo, -s
per un indirizzo sorgente, -o
per specificare l’interfaccia in uscita, -d
per indirizzo IP destinazione, -i
per specificare l’interfaccia di rete in entrata. Per indicare porta sorgente e porta destinazione di un pacchetto, potremo utilizzare rispettivamente i flag --sport
e --dport
.
I Target
Quando un pacchetto attiva una condizione di match, esso viene intercettato da una regola e sarà attivata la relativa funzione di target. Esistono diverse funzioni di quest’ultima categoria; le principali sono riportate nella tabella seguente:
Funzione | Descrizione |
---|---|
ACCEPT |
Accetta il pacchetto che prosegue la sua corsa |
DNAT |
Equivalente di SNAT ma agisce sull’IP destinazione |
DROP |
Elimina il pacchetto in maniera silenziosa senza fornire alcun tipo di segnalazione alla fonte |
QUEUE |
Dispone i pacchetti in coda per specifici utilizzi |
REJECT |
Come DROP , ma spedisce un messaggio di errore alla fonte |
RETURN |
Interrompe il controllo del pacchetto nella catena in questione pertanto, se è una sottocatena, il pacchetto continua il proprio viaggio nella catena superiore altrimenti, se è in una catena principale, viene gestito dalla politica di default |
SNAT |
Altera il primo pacchetto ovvero quello che apre la connessione (per quanto concerne l’informazione relativa all’IP sorgente) |
Log
È bene stabilire sin da subito il livello di dettaglio del log. Log troppo verbosi esauriranno rapidamente il disco, troppo stringati non consentiranno di fare diagnostica in modo opportuno.
Il comando seguente imposta un livello di log con un massimo di 10 report al minuto, ed una ripetizione della stessa entry consentita per non più di tre volte.
iptables -A INPUT -m limit --limit 10/minute --limit-burst 3 -j LOG
Alcuni esempi
Agire sulle regole che disciplinano ICMP (Internet Control Message Protocol) è auspicabile. Questo protocollo, usato per la diagnostica delle connessioni, va limitato per arginare gli attacchi DOS
Possiamo inibire ICMP con il comando seguente:
iptables -p icmp –h
Inibire ICMP in toto è un approccio semplice ma sconsigliabile; in questa sede ci siamo limitati a questa possibilità solo al fine di esemplificare la trattazione.
Come ulteriore esempio, analizziamo il comando seguente:
iptables -A INPUT -p tcp -m tcp --dport 23 -s 10.0.0.1 -j REJECT --reject-with icmp-port-unreachable
Esso farà sì che le connessioni sulla porta standard di Telnet saranno precluse per l’IP 10.0.0.1, mentre saranno permesse a tutti gli altri IP.
Prima del riavvio del server
Quando inseriamo un comando su iptables, lo facciamo durante l’esecuzione del sistema. È però buona norma fare in modo da rendere permanenti le modifiche apportate sulle tabelle, rendendole disponibili anche al prossimo riavvio.
Ci sono molti modi di farlo, e uno di questi consiste nel reindirizzare l’output del comando iptables-save
nella nostra sequenza di boot. Per farlo, procediamo come segue:
iptables-save > /root/rules
iptables-restore < /root/rules
Virtual Switch e test Iptables
Il modo più semplice per testare iptables su Aruba Cloud consiste nel creare una o più macchine di test interconnesse attraverso una LAN dedicata, sfruttando un Virtual Swich. Esso ci permette di connetterle direttamente fra loro.
Per configurare un scheda di rete su Linux in modo non permanente, suggeriamo un apposito approfondimento disponibile su HTML.it. Se vogliamo, invece, configurarla in modo permanente, rimandiamo a questa lezione per i sistemi Ubuntu, e a quest’altra per sistemi derivati da Red Hat come Fedora.