[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico] [volume] [parte]
Il kernel Linux può gestire direttamente il filtro dei pacchetti IP, cosa che quindi rappresenta la scelta più semplice per la realizzazione di un firewall con questo sistema operativo. A parte le limitazioni che può avere un tale tipo di firewall, il suo inserimento nella rete non genera effetti collaterali particolari, dal momento che poi non c'è bisogno di utilizzare software speciale per gli elaboratori che lo devono attraversare, come avviene invece nel caso di un firewall di tipo proxy.
Trattandosi di un'attività del kernel, è necessario che questo sia stato predisposto in fase di compilazione, oppure sia accompagnato dai moduli necessari (sezione 49.2.14). Inoltre, è opportuno aggiungere anche le funzionalità di ricomposizione dei pacchetti frammentati, oltre che le funzionalità relative al NAT (Network address translation).
L'attraversamento dei pacchetti tra un'interfaccia e l'altra è controllato dalla funzionalità di forwarding-gatewaying, che in passato andava inserita esplicitamente nel kernel. In generale, il kernel non permette questo attraversamento, che deve essere abilitato attraverso un comando particolare. Per IPv4:
#
echo 1 > /proc/sys/net/ipv4/ip_forward
[Invio]
Per IPv6:
#
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
[Invio]
Il kernel Linux 2.4.* suddivide le funzionalità di trattamento dei pacchetti IP in «tabelle». Nell'ambito di ogni tabella ci possono essere diversi punti di controllo, denominati chain, che possono essere programmati per catturare i pacchetti IP e deciderne la loro sorte. A seconda delle circostanze, un pacchetto IP può essere sottoposto alla verifica di uno o più di questi punti di controllo, che vengono programmati in base a delle regole. Quando un pacchetto sottoposto a controllo corrisponde a una regola, la sua sorte viene definita dall'obiettivo di questa (ammesso che sia stato definito).
La tabella relativa alla gestione del firewall è denominata filter e si compone di tre punti di controllo: INPUT, FORWARD e OUTPUT, che indicano rispettivamente i pacchetti in ingresso, quelli in transito e quelli in uscita. Gli obiettivi più frequenti sono due, ACCEPT e DROP, che rispettivamente si riferiscono al permesso di attraversamento del punto di controllo, oppure al blocco ed eliminazione del pacchetto intercettato.
|
Un pacchetto proveniente da un'interfaccia qualunque, diretto allo stesso firewall, è soggetto al controllo di ingresso;(1) un pacchetto passante viene sottoposto al controllo di inoltro; un pacchetto che deve uscire attraverso un'interfaccia del firewall, perché generato da un processo locale, è sottoposto al controllo di uscita.(2)
Quando un pacchetto IP viene analizzato in un punto di controllo e all'interno di questo non c'è alcuna regola che lo prenda in considerazione, la sua sorte è stabilita dalla politica predefinita (policy) per quel contesto. Generalmente, questa politica è tale per cui gli viene concesso il transito.
La gestione del filtro di pacchetto IP del kernel 2.4.* avviene per mezzo di IPTables, (3) ovvero l'eseguibile iptables per il controllo di IPv4 e ip6tables per il controllo di IPv6. Dal momento che le funzionalità di firewall del kernel sono piuttosto estese, la sintassi di questo programma è molto articolata, per cui se ne può apprendere l'utilizzo solo gradualmente.
Inoltre, è bene chiarire subito che le funzionalità di firewall del kernel non possono essere definite attraverso un file di configurazione; quindi, al massimo, tutto quello che si può fare è la realizzazione di uno script contenente una serie di comandi con IPTables.
IPTables interviene su un elenco di regole riferite alle funzionalità di controllo dei pacchetti IP del kernel, dove la gestione particolare riferita alle funzionalità di firewall riguarda la tabella filter. Il meccanismo è comunque simile a quello della gestione della tabella degli instradamenti di un router. L'ordine in cui sono elencate tali regole è importante, quindi si deve poter distinguere tra l'inserimento di una regola all'inizio, alla fine o in un'altra posizione dell'elenco esistente (elenco riferito sempre a un certo punto di controllo).
Salvo eccezioni particolari, descritte nel contesto appropriato, la sintassi di massima per l'utilizzo di IPTables è quella seguente:
iptables [-t tabella] opzione_di_comando punto_di_controllo [regola] [obiettivo] |
ip6tables [-t tabella] opzione_di_comando punto_di_controllo [regola] [obiettivo] |
La tabella serve a stabilire il contesto di intervento; il nome dell'eseguibile (iptables o ip6tables) definisce il tipo di protocolli di competenza (IPv4 o IPv6). La tabella predefinita è proprio quella riferita alle funzionalità di firewall, ovvero filter.
In generale, l'utilizzo di iptables o di ip6tables è uguale, salvo le differenze che riguardano il modo di rappresentare gli indirizzi e salvo piccole eccezioni. Nel capitolo si accenna alle differenze solo quando necessario, tenendo conto che di solito basta sostituire il nome dell'eseguibile per cambiare il contesto. |
L'opzione di comando serve a stabilire il tipo di intervento nel sistema di gestione del firewall. L'elenco seguente si riferisce alle opzioni che permettono la cancellazione o l'inserimento delle regole in un punto di controllo:
Altre opzioni non modificano le regole; in particolare:
Altre opzioni vengono mostrate quando più opportuno.
Come già accennato, il punto di controllo viene indicato attraverso un nome. Si tratta di INPUT, FORWARD e OUTPUT, che intuitivamente fanno riferimento all'ingresso, al transito e all'uscita.
Si osservi che questi nomi sono scritti utilizzando lettere maiuscole, a differenza di quanto accadeva con la gestione del kernel 2.2.*, per sottolineare la loro differenza nel funzionamento, per cui i pacchetti in transito non sono più presi in considerazione dai punti di controllo di ingresso e di uscita. |
IPTables permette di gestire delle regole all'interno di contenitori aggiuntivi a cui si fa riferimento a partire da regole inserite nei punti di controllo normali. Nella terminologia di IPTables si parla sempre di chain, sia per indicare i punti di controllo standard, sia per indicare questi elenchi di regole aggiuntive. |
Infine, una regola comune è conclusa con l'indicazione di un obiettivo. L'obiettivo è la definizione della sorte da dare al pacchetto intercettato, indicata attraverso una parola chiave. Le più importanti per iniziare ad apprendere la configurazione del firewall sono: ACCEPT, DROP e REJECT.
|
Segue la descrizione di alcuni esempi.
iptables [-t filter] -A INPUT regola -j DROP |
Lo schema mostra l'aggiunta di una regola di ingresso, non meglio definita, per la quale viene applicato l'obiettivo DROP.
iptables [-t filter] -R INPUT 1 regola -j DROP |
Lo schema mostra la sostituzione della prima regola di ingresso con un'altra regola non meglio definita, per la quale viene applicato l'obiettivo DROP.
iptables [-t filter] -I INPUT 1 regola -j ACCEPT |
Lo schema mostra l'inserimento nella prima posizione di una regola di ingresso per la quale viene consentito il transito dei pacchetti (ACCEPT).
iptables [-t filter] -D INPUT 2 |
Questo schema mostra l'eliminazione della seconda regola di ingresso.
iptables [-t filter] -F INPUT |
Questo schema mostra l'eliminazione di tutte le regole di ingresso.
iptables [-t filter] -F |
Questo schema mostra l'eliminazione di tutte le regole di tutti i punti di controllo.
iptables [-t filter] -P INPUT DROP |
Cambia la politica predefinita di ingresso specificando che, in mancanza di regole, i pacchetti devono essere bloccati.
Negli esempi è stato sottolineato l'uso facoltativo dell'opzione -t per identificare precisamente la tabella su cui intervenire. Dal momento che la tabella filter è quella predefinita, nel capitolo non viene più utilizzata tale opzione. |
Data la complessità delle funzionalità di filtro di pacchetto del kernel, anche l'uso di IPTables è piuttosto articolato. Prima di iniziare a vedere come si possono definire le regole, conviene fare qualche esperimento che serva a introdurre l'uso di questo programma.
Gli esempi fanno riferimento a IPv4, ma dovrebbero andare bene anche per IPv6, salva la sostituzione degli indirizzi. |
La prima cosa da sapere è in che modo si ottiene la visualizzazione della situazione dei punti di controllo che compongono la tabella.
#
iptables -L
[Invio]
In questo modo si ottiene la situazione di tutti i punti di controllo (ed eventualmente anche dei raggruppamenti di regole aggiuntivi). Inizialmente si dovrebbe osservare la situazione seguente:
|
Quello che si vede è la situazione normale del sistema prima di iniziare a inserire delle regole; tutto quello che c'è sono le politiche predefinite per ogni punto di controllo.
Se si è interessati a conoscere solo la situazione di un punto di controllo particolare, basta aggiungere il nome di questo. Per esempio, per limitare il risultato al solo punto di controllo di ingresso si può usare il comando seguente:
#
iptables -L INPUT
[Invio]
Chain INPUT (policy ACCEPT) target prot opt source destination |
Per verificare l'effetto del blocco del traffico attraverso uno dei punti di controllo si può agire sommariamente sulla politica predefinita; per esempio si può bloccare il transito dei pacchetti in ingresso con il comando seguente:
#
iptables -P INPUT DROP
[Invio]
Questo tipo di blocco è totale e interviene anche nell'interfaccia virtuale che identifica il sistema locale: lo. Basta provare a fare un ping verso il nodo locale per accorgersi che non si ottiene più alcuna risposta.(4)
$
ping localhost
[Invio]
Un risultato simile si potrebbe ottenere utilizzando l'obiettivo REJECT. In alternativa si può intervenire nel punto di controllo di uscita; nell'esempio seguente si ripristina prima la politica di ACCEPT per i pacchetti in ingresso.
#
iptables -P INPUT ACCEPT
[Invio]
#
iptables -P OUTPUT DROP
[Invio]
Con il ping si ottiene in pratica lo stesso risultato, con la differenza che i pacchetti trasmessi vengono bloccati prima di poter uscire dal processo che li genera.
Se invece si interviene nel punto di controllo di inoltro (o di transito), si avverte l'effetto solo nei pacchetti che devono attraversare il firewall da un'interfaccia a un'altra. Prima di tutto è bene ricordare che questi possono transitare solo se la cosa viene abilitata attraverso il comando:
#
echo 1 > /proc/sys/net/ipv4/ip_forward
[Invio]
oppure, per IPv6:
#
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
[Invio]
Il comando seguente, per quanto inutile, impedisce il transito dei pacchetti tra le interfacce, attraverso la gestione del firewall, con la modifica della politica predefinita del punto di controllo relativo:
#
iptables -P FORWARD DROP
[Invio]
Prima di proseguire è bene rimettere a posto le politiche predefinite dei tre punti di controllo:
#
iptables -P INPUT ACCEPT
[Invio]
#
iptables -P OUTPUT ACCEPT
[Invio]
#
iptables -P FORWARD ACCEPT
[Invio]
Prima di affrontare l'analisi delle regole che possono essere inserite nei punti di controllo riferiti alla gestione del firewall, è meglio descrivere subito l'utilizzo di alcune opzioni di contorno che hanno un'importanza minore, oppure che si possono utilizzare indipendentemente dal tipo di protocollo a cui si fa riferimento con una regola.
|
Segue la descrizione di alcuni esempi.
#
iptables -L INPUT -v
[Invio]
Elenca le regole di ingresso in modo dettagliato.
#
iptables -L OUTPUT -n
[Invio]
Elenca le regole di uscita senza tradurre informazioni numeriche nei nomi corrispondenti.
iptables -A punto_di_controllo regola -i eth0 -j DROP |
Lo schema mostra l'aggiunta in coda di una regola non meglio identificata, nella quale viene specificato in particolare che deve riferirsi al traffico entrante dall'interfaccia eth0. Per i pacchetti che vengono intercettati dalla regola, viene applicato l'obiettivo DROP.
iptables -A punto_di_controllo -p tcp regola -i eth0 -j DROP |
Lo schema mostra l'aggiunta in coda di una regola non meglio identificata, nella quale viene specificato in particolare che deve riferirsi al traffico TCP entrante dall'interfaccia eth0. Per i pacchetti che vengono intercettati dalla regola, viene applicato l'obiettivo DROP.
iptables -A punto_di_controllo -p ! tcp regola -i ! eth0 -j DROP |
Lo schema mostra l'aggiunta in coda di una regola non meglio identificata, nella quale viene specificato in particolare che deve riferirsi a tutto il traffico che non sia TCP, entrante da un'interfaccia qualunque purché non sia eth0. Per i pacchetti che vengono intercettati dalla regola, viene applicato l'obiettivo DROP.
Le regole che non indicano un protocollo particolare possono servire esclusivamente a individuare il traffico riferito a un'origine e a una destinazione, con l'indicazione eventuale dell'interfaccia di ingresso e di uscita:
[-p all] [-s [!] origine] [-i interfaccia] [-d [!] destinazione] [-o interfaccia] |
Come si vede dallo schema, si possono utilizzare le opzioni -s e -d per indicare rispettivamente l'origine e la destinazione di un pacchetto. In aggiunta, si potrebbe inserire l'indicazione di una certa interfaccia attraverso cui i pacchetti vengono ricevuti o trasmessi; inoltre, volendo indicare espressamente che non si fa riferimento a un protocollo particolare, si può aggiungere l'opzione -p con l'argomento all.
La definizione di un gruppo di indirizzi IP può essere fatta attraverso l'indicazione di una coppia numero_ip/maschera, con una barra obliqua di separazione tra i due. La maschera può essere indicata nel modo consueto, oppure con un numero che esprime la quantità di bit iniziali da porre al valore uno. A titolo di esempio, la tabella 252.8 mostra l'equivalenza tra alcune maschere di rete tipiche e questo numero di abbreviazione.
Quando si vuole fare riferimento a indirizzi imprecisati, si utilizza solitamente l'indirizzo 0.0.0.0, che può essere indicato anche con un solo zero; questo si abbina di solito alla maschera nulla: 0.0.0.0/0 o 0/0. Tuttavia, per fare riferimento a qualunque indirizzo, è sufficiente omettere la sua indicazione, in pratica basta fare a meno di indicare l'opzione -s o -d.
L'indicazione di un indirizzo può essere fatta utilizzando direttamente il nome di dominio corrispondente, ma questo richiede la disponibilità di un servizio DNS; ciò può essere conveniente quando si tratta di un firewall connesso stabilmente con la rete esterna, altrimenti si creerebbero delle attese inutili e fastidiose, nel tentativo di risolvere dei nomi che non sono di competenza delle zone locali. Pertanto, in generale è preferibile indicare indirizzi in forma numerica.
Il punto esclamativo che può essere inserito facoltativamente di fronte all'indicazione di un indirizzo IP, o di un gruppo di indirizzi, rappresenta la negazione logica e serve a fare riferimento al gruppo di indirizzi complementare.
|
Segue la descrizione di alcuni esempi.
#
iptables -A INPUT -s 192.168.100.0/24 -j DROP
[Invio]
Blocca tutto il traffico in ingresso, destinato all'elaboratore locale, proveniente dalla rete 192.168.100.*.
#
iptables -A INPUT -s 192.168.100.0/24 -d 0/0 -j DROP
[Invio]
Esattamente come nell'esempio precedente.
#
iptables -A INPUT -s 192.168.100.0/24 -d 0/0 -i eth0 -j DROP
[Invio]
Come nell'esempio precedente, specificando però che questo traffico in ingresso deve provenire dall'interfaccia eth0 (se provenisse da un'altra interfaccia, non verrebbe intercettato da questa regola).
#
iptables -A FORWARD -d 192.168.100.0/24 -j DROP
[Invio]
Blocca tutto il traffico in transito, che risulta destinato alla rete 192.168.100.*.
#
iptables -A FORWARD -s 0/0 -d 192.168.100.0/24 -j DROP
[Invio]
Esattamente come nell'esempio precedente.
#
iptables -A FORWARD -s 0/0 -d ! 192.168.100.0/24 -j DROP
[Invio]
Blocca tutto il traffico in transito che risulta destinato a indirizzi diversi dalla rete 192.168.100.*.
#
iptables -A OUTPUT -d 192.168.100.0/24 -j DROP
[Invio]
Blocca tutto il traffico in uscita, generato nell'elaboratore locale, che risulta destinato alla rete 192.168.100.*.
Come negli esempi mostrati in precedenza, in cui si agiva soltanto sulla politica predefinita, con la stessa semplicità si può sperimentare l'uso delle regole. Per cominciare, quando il comando iptables -L genera il risultato
Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination |
significa che non ci sono regole per alcun punto di controllo e le politiche predefinite non oppongono resistenza al transito dei pacchetti. Con una regola molto semplice è possibile bloccare qualunque ingresso attraverso l'interfaccia virtuale corrispondente a localhost
, cioè all'indirizzo 127.0.0.1:
#
iptables -A INPUT -s 127.0.0.1 -j DROP
[Invio]
Se si tenta di fare il ping verso il nodo locale, questo non genera alcuna risposta, dal momento che tutti i pacchetti in ingresso vengono eliminati. Anticipando un po' quello che viene descritto in seguito, se lo scopo fosse esclusivamente quello di impedire l'ingresso dei pacchetti del protocollo ICMP (cosa che tra l'altro impedisce il ping), si potrebbe usare un comando più specifico:
#
iptables -A INPUT -p icmp -s 127.0.0.1 -j DROP
[Invio]
Se sono stati eseguiti gli esempi, il comando iptables -L INPUT dovrebbe generare il risultato seguente:
Chain INPUT (policy ACCEPT) target prot opt source destination DROP all -- localhost anywhere DROP icmp -- localhost anywhere |
Prima di fare altre considerazioni, conviene osservare la simbologia usata nel rapporto che è stato ottenuto: la colonna prot rappresenta il protocollo di riferimento; la colonna opt rappresenta delle specificazioni opzionali delle regole che in questo caso non sono mai state utilizzate; le colonna source e destination rappresentano l'origine e la destinazione dei pacchetti, dove in particolare la parola chiave anywhere esprime in pratica ciò che altrimenti si indicherebbe con la notazione 0.0.0.0/0. Si osservi la differenza nel risultato nel caso si utilizzi l'opzione -n, ovvero il comando iptables -L INPUT -n, allo scopo di eliminare le rappresentazioni simboliche degli indirizzi.
Chain INPUT (policy ACCEPT) target prot opt source destination DROP all -- 127.0.0.1 0.0.0.0/0 DROP icmp -- 127.0.0.1 0.0.0.0/0 |
Le regole hanno una sequenza precisa; avendo utilizzato sempre l'opzione di comando -A, queste sono state aggiunte di seguito. Come si può intuire, la seconda regola è inutile, dal momento che i pacchetti che potrebbero riguardarla vengono già presi in considerazione da quella precedente che li blocca completamente per conto proprio.
Le regole possono essere eliminate in modo selettivo attraverso l'opzione di comando -D, oppure in modo complessivo attraverso l'opzione -F. Per eliminare la prima regola, si potrebbe utilizzare uno dei due comandi seguenti:
#
iptables -D INPUT -s 127.0.0.1 -j DROP
[Invio]
#
iptables -D INPUT 1
[Invio]
Nel primo caso viene eliminata la prima regola che corrisponde al modello, cioè la prima in assoluto, mentre il secondo comando fa riferimento direttamente al numero della regola. Naturalmente, dopo l'eliminazione della prima regola, quella che inizialmente era la seconda diventa la prima:
Chain INPUT (policy ACCEPT) target prot opt source destination DROP icmp -- localhost anywhere |
Come accennato, per eliminare tutte le regole di un punto di controllo si può usare l'opzione di comando -F:
#
iptables -F INPUT
[Invio]
L'esempio elimina tutte le regole di ingresso.
Se l'elaboratore con il quale si fanno questi esperimenti ospita un servizio si può fare qualche esperimento più interessante. Supponendo di disporre di un servente HTTP che riceve richieste attraverso la porta 80 del protocollo TCP, si potrebbe impedirne l'accesso da parte dell'utente che accede dallo stesso sistema locale attraverso il comando seguente:
#
iptables -A INPUT -p tcp -s 127.0.0.1 -d 127.0.0.1
\
\--dport 80 -j REJECT
[Invio]
Quando si avvia un programma di navigazione per accedere al servizio HTTP locale, questo cerca di instaurare una connessione TCP utilizzando la porta 80 nella destinazione; se il firewall dispone della regola inserita con il comando appena mostrato, intercetta il tentativo di connessione e restituisce un messaggio di rifiuto attraverso il protocollo ICMP. La scelta di utilizzare l'obiettivo REJECT è motivata da questa esigenza: evitare di fare perdere tempo a chi tenta di accedere, perché diversamente l'obiettivo DROP renderebbe la cosa più subdola. Si osservi cosa si ottiene con l'opzione -L:
#
iptables -L INPUT
[Invio]
Chain INPUT (policy ACCEPT) target prot opt source destination REJECT tcp -- localhost localhost tcp \ |
La sigla dpt sta per Destination port; www è evidentemente il nome della porta 80. Dal momento che è stata richiesto l'obiettivo REJECT, viene mostrato esplicitamente il tipo di messaggio ICMP che viene restituito a seguito di un tentativo di accesso: port-unreachable.
Per definire delle regole corrette per i fini che ci si prefigge, occorre conoscere bene il comportamento del protocollo che si utilizza. Tornando all'esempio appena fatto, in cui lo scopo è quello di impedire all'utente del sistema locale di accedere al servizio HTTP locale, si potrebbe ottenere un risultato equivalente agendo sul punto di controllo di uscita. Per farlo occorre sapere che la connessione TCP è simmetrica e che nel flusso di ritorno il servizio HTTP utilizza ancora la stessa porta 80, già impiegata per ricevere la richiesta di connessione.
#
iptables -F INPUT
[Invio]
#
iptables -A OUTPUT -p tcp -s 127.0.0.1 --sport 80
\
\-d 127.0.0.1 -j REJECT
[Invio]
In questo caso si deve osservare comunque una cosa: il messaggio ICMP, con cui si notifica il blocco del transito del pacchetto in uscita, è diretto all'applicazione che tenta di rispondere alla richiesta del cliente, di conseguenza il cliente ne resta all'oscuro.
Il modo con cui si possono definire le regole necessarie a individuare i pacchetti, dipendono dal tipo di protocollo utilizzato. Generalmente si è interessati maggiormente a controllare i protocolli TCP e UDP, che hanno in comune l'utilizzo delle porte.
Dovendo fare riferimento a un protocollo TCP o UDP si utilizza l'opzione -p, seguita dalla parola chiave tcp o udp. Dal momento che i protocolli TCP e UDP utilizzano le porte, l'origine e la destinazione possono includere questa informazione, con l'uso delle opzioni --sport e --dport rispettivamente.
Le porte possono essere indicate in modo preciso (una soltanto), oppure attraverso un intervallo. Queste porte possono essere espresse attraverso un nome, come definito nel file /etc/services
, oppure per numero, cosa che di solito si preferisce per evitare ambiguità o malintesi. Gli intervalli di porte, in particolare, vengono espressi nella forma seguente:
porta_iniziale:porta_finale |
Se si indica un intervallo, cosa che si determina per la presenza dei due punti, se manca l'indicazione della porta iniziale si intende in modo predefinito la numero zero, se invece manca quella finale si intende la porta 65 535. Come nel caso degli indirizzi IP, l'indicazione della porta o dell'intervallo di queste può essere preceduta dal punto esclamativo in qualità di negazione logica.
|
Nel caso di protocolli TCP, è possibile analizzare i bit che qualificano lo stato della connessione. Questi bit hanno un nome simbolico, corrispondente a: SYN, ACK, FIN, RST, URG e PSH. Si può controllare lo stato di questi bit con l'opzione --tcp-flags. Dal momento che è comune la richiesta di individuare i pacchetti con il bit SYN attivo e i bit RST e ACK disattivati, si può usare per questo l'opzione --syn.
|
Segue la descrizione di alcuni esempi.
#
iptables -A INPUT -p tcp -s ! 192.168.0.0/16
\
\-d 192.168.0.0/16 --dport 80 -j REJECT
[Invio]
Impedisce l'accesso ai servizi HTTP (protocollo TCP, porta 80) della rete 192.168.*.* a tutti gli indirizzi estranei alla rete stessa.
#
iptables -A INPUT -p tcp -s ! 192.168.0.0/16
\
\-d 192.168.0.0/16 --dport 80 --syn -j REJECT
[Invio]
Come nell'esempio precedente, limitandosi a intervenire nei pacchetti di inizializzazione delle connessioni.
Il protocollo ICMP è molto importante per il controllo del funzionamento della rete, in questo senso è rara la possibilità che sia il caso di bloccarne il transito attraverso il firewall. Tuttavia, dal momento che i fini del firewall non si limitano al blocco del traffico, è comunque importante poter indicare una regola che sappia selezionare un tipo particolare di pacchetto ICMP. La tabella 251.4 elenca i tipi di pacchetto ICMP e il loro utilizzo.
Per indicare una regola che faccia riferimento a un tipo particolare di pacchetto ICMP, si sfruttano le opzioni che servono a specificare l'origine o la destinazione, aggiungendo il numero o il nome del tipo ICMP (il numero può essere composto da una seconda parte, denominato codice). In pratica, questa informazione va a sostituire il numero di porta nel caso dei protocolli TCP e UDP.
È estremamente importante che non vengano bloccati i messaggi ICMP di tipo 3. |
Il protocollo ICMP è differente tra IPv4 e IPv6, pertanto la sigla usata per farvi riferimento cambia. |
Il comando iptables -p icmp -h genera l'elenco di tutti i messaggi ICMP gestibili con IPv4:
#
iptables -p icmp -h
[Invio]
Valid ICMP Types: echo-reply (pong) destination-unreachable network-unreachable host-unreachable protocol-unreachable port-unreachable fragmentation-needed source-route-failed network-unknown host-unknown network-prohibited host-prohibited TOS-network-unreachable TOS-host-unreachable communication-prohibited host-precedence-violation precedence-cutoff source-quench redirect network-redirect host-redirect TOS-network-redirect TOS-host-redirect echo-request (ping) router-advertisement router-solicitation time-exceeded (ttl-exceeded) ttl-zero-during-transit ttl-zero-during-reassembly parameter-problem ip-header-bad required-option-missing timestamp-request timestamp-reply address-mask-request address-mask-reply |
Si può osservare che i nomi rientrati, fanno riferimento a un tipo ICMP formato anche attraverso l'indicazione di un codice. Per esempio, network-unreachable corrisponde a 3/0.
|
Segue la descrizione di alcuni esempi.
#
iptables -A INPUT -p icmp -s ! 192.168.0.0/16
\
\--icmp-type 8 -d 192.168.0.0/16 -j DROP
[Invio]
Blocca e ignora i pacchetti ICMPv4 che contengono un messaggio di tipo 8, cioè echo-request, proveniente da un indirizzo estraneo alla rete 192.168.*.* e destinato alla rete stessa.
#
iptables -A INPUT -p icmp -s ! 192.168.0.0/16
\
\--icmp-type echo-request -d 192.168.0.0/16 -j DROP
[Invio]
Esattamente come nell'esempio precedente, indicando per nome il tipo ICMPv4.
#
ip6tables -A INPUT -p icmpv6 -s ! fec0::/16
\
\--icmpv6-type echo-request -d fec0::/16 -j DROP
[Invio]
Blocca e ignora i pacchetti ICMPv6 che contengono un messaggio di tipo echo-request, proveniente da un indirizzo estraneo alla rete fec0:* e destinato alla rete stessa.
I pacchetti frammentati costituiscono un problema per la gestione del firewall. In generale ci si limita a intervenire sul primo frammento, perché questo dovrebbe contenere le informazioni necessarie a identificarlo correttamente.
Se il firewall rappresenta un passaggio obbligato per il traffico che lo attraversa, è molto importante che sia abilitata la ricomposizione dei pacchetti frammentati. Questo risolve tanti problemi e soprattutto quello del controllo dei frammenti. |
Per identificare un frammento di pacchetto successivo al primo, si utilizza l'opzione -f nel modo seguente:
[!] -f | [!] --fragment |
Il punto esclamativo permette di ottenere l'effetto contrario, cioè di fare riferimento a tutti i pacchetti che non sono frammenti. Utilizzando questa opzione non è possibile indicare delle porte TCP o UDP, né specificare il tipo di messaggio per il protocollo ICMP.
L'esempio seguente blocca l'attraversamento di frammenti dei pacchetti ICMP provenienti da un indirizzo estraneo alla rete 192.168.*.* e destinati alla rete stessa.
#
iptables -A FORWARD -p icmp -s ! 192.168.0.0/16
\
\-d 192.168.0.0/16 -f -j DROP
[Invio]
Le funzionalità di filtro del kernel sono suddivise in segmenti differenti che possono essere incluse o meno, in fase di compilazione, oppure possono essere caricate attraverso moduli esterni. Queste funzionalità particolari sono definite moduli, senza per questo voler confondere il concetto con i moduli del kernel. Per utilizzare queste funzionalità si deve indicare prima il modulo, attraverso l'opzione -m:
-m modulo |
--match modulo |
Nel seguito vengono presentati solo alcuni dei moduli disponibili.
È molto probabile che tali estensioni non siano tutte disponibili per IPv6; ma di questo ci si accorge facilmente dalle segnalazioni di errore generate da ip6tables. |
È possibile definire una regola che scatti fino al raggiungimento di un certo limite per un certo tipo di pacchetto. Si tratta del modulo limit:
-m limit |
Si distinguono due informazioni in questo contesto: la quantità di pacchetti per unità di tempo e il margine di sicurezza prima che venga preso in considerazione il raggiungimento del limite.
|
Vengono riproposti gli esempi che appaiono già nel Linux 2.4 packet filtering HOWTO di Rusty Russell. Ovviamente, perché questi limiti abbiano un senso, dopo le regole che consentono il transito entro una certa frequenza, occorre aggiungere delle regole che blocchino lo stesso tipo di pacchetti, senza più l'indicazione di un limite.
Protezione contro un attacco da inondazione di pacchetti «SYN»:
#
iptables -A FORWARD -p tcp --syn -m limit
\
\--limit 1/s -j ACCEPT
[Invio]
Consente il transito di un solo pacchetto di inizializzazione delle connessioni TCP al secondo. Per bloccare i pacchetti successivi si aggiunge il blocco degli stessi pacchetti:
#
iptables -A FORWARD -p tcp --syn -j DROP
[Invio]
Protezione contro un tentativo di scansione delle porte TCP:
#
iptables -A FORWARD -p tcp
\
\--tcp-flags SYN,ACK,FIN,RST RST -m limit
\
\--limit 1/s -j ACCEPT
[Invio]
Consente il transito di un pacchetto TCP al secondo con il solo bit RST attivo, nell'ambito del gruppo di bit composto da SYN, ACK, FIN e RST. Per bloccare i pacchetti successivi si aggiunge il blocco degli stessi pacchetti:
#
iptables -A FORWARD -p tcp
\
\--tcp-flags SYN,ACK,FIN,RST RST -j DROP
[Invio]
Protezione contro un'inondazione di richieste di eco ICMP (ping):
#
iptables -A FORWARD -p icmp --icmp-type echo-request
\
\-m limit --limit 1/s -j ACCEPT
[Invio]
Consente il transito di un pacchetto ICMP di tipo 8 (richiesta di eco) al secondo. Per bloccare i pacchetti successivi si aggiunge il blocco degli stessi pacchetti:
#
iptables -A FORWARD -p icmp --icmp-type echo-request -j DROP
[Invio]
Gli esempi mostrano tutti un controllo applicato ai pacchetti in transito. Per proteggere anche il firewall occorre intervenire nello stesso modo sui pacchetti in ingresso. |
Un modulo speciale, denominato state, consente di analizzare le connessioni e di individuarle in base a uno status semplice da definire.
-m state |
Questo modulo consente semplicemente di utilizzare l'opzione --state, con cui si specifica lo stato di una connessione:
--state {NEW|ESTABLISHED|RELATED|INVALID}[,...] |
Le varie parole chiave utilizzate per definire lo stato di una connessione hanno il significato descritto nell'elenco seguente.
|
Segue la descrizione di alcuni esempi.
#
iptables -A FORWARD -d 192.168.0.0/16 -m state
\
\--state ESTABLISHED,RELATED -j ACCEPT
[Invio]
Consente il transito verso gli indirizzi 192.168.*.* quando si tratta di connessioni già realizzate o si tratta di pacchetti correlati a connessioni preesistenti.
#
iptables -A FORWARD -d 192.168.0.0/16 -m state
\
\--state INVALID -j DROP
[Invio]
Elimina i pacchetti destinati agli indirizzi 192.168.*.* quando questi non sono identificabili in qualche modo, nel senso che non sembrano avere motivo di esistere.
#
iptables -A FORWARD -m state --state NEW -i ! ppp0 -j ACCEPT
[Invio]
Consente l'instaurarsi di una connessione che attraversi il nodo, purché ciò non avvenga a cominciare da un pacchetto che entri dall'interfaccia ppp0 (PPP).
In generale, quando si predispone uno script con tutte le regole di firewall che si vogliono applicare ai pacchetti in ingresso, in uscita e in transito, si inizia dall'azzeramento di quelle eventualmente esistenti, esattamente nel modo seguente:
|
Dal momento che le funzionalità di filtro del kernel Linux non devono interferire con quelle di instradamento (routing), nel caso le prime non siano state definite, è necessario che la politica predefinita sia sempre ACCEPT. In generale, se si vuole configurare il proprio elaboratore come firewall la situazione cambia e dovrebbe essere conveniente il contrario, in modo da poter controllare la situazione. In pratica, ancora prima dell'azzeramento delle regole delle varie categorie, è solitamente opportuno modificare le politiche predefinite, in modo da bloccare gli accessi e il transito dei pacchetti.
|
La definizione delle regole di firewall deve tenere conto dell'ordine in cui appaiono nell'elenco gestito all'interno del kernel, quindi, la scelta tra le opzioni di comando -A (aggiunta in coda) e -I (inserimento all'inizio o in un'altra posizione) deve essere fatta in modo consapevole. A seconda della propria filosofia personale, si potrebbe scegliere di utilizzare sempre solo un tipo, oppure l'altro.
Se si sceglie di «aggiungere» le regole, dovrebbe essere conveniente iniziare da quelle di eliminazione o rifiuto (DROP o REJECT), per finire con quelle di accettazione (ACCEPT).
Se si preferisce lasciare che la politica predefinita sia ACCEPT, è importante ricordare di aggiungere una regola che impedisca l'accesso in modo generalizzato alla fine di tutte le regole di un punto di controllo, come mostrato nell'esempio seguente:
|
Nell'esempio, non avendo fatto riferimento ad alcun protocollo, né ad alcun indirizzo sorgente o di destinazione, si intendono implicitamente tutti i tipi di pacchetto. Questo tipo di strategia è comunque applicabile con qualunque tipo di politica predefinita, dal momento che con questa regola si catturano tutti i pacchetti rimanenti.
Quando lo scopo di un firewall è solo quello di proteggere una rete interna da quella esterna, si potrebbe pensare che l'uso di regole per il solo attraversamento dovrebbe bastare. In effetti, dal momento che i pacchetti devono attraversare il firewall per raggiungere la rete interna, il ragionamento è corretto; tuttavia, bisogna pensare anche a proteggere il firewall e in tal senso si comprende l'utilità di disporre di un punto di controllo in ingresso. Infatti, se un aggressore riesce a ottenere accesso nel firewall, da lì può entrare nella rete interna che invece si considera protetta. Il punto di controllo in uscita è una possibilità in più per completare le cose ed è un bene che ci siano tante possibilità.
Naturalmente, le funzionalità di filtro dei pacchetti sono utili anche per gli elaboratori che devono difendersi da soli, perché si trovano in un ambiente ostile, o perché semplicemente non ci si può fidare. È evidente in questi casi che diventa importantissima la possibilità di intervenire nelle regole del punto di controllo di ingresso ed eventualmente anche in quelle del punto di controllo in uscita, mentre il controllo dell'attraversamento dovrebbe risultare semplicemente inutile.
Una delle politiche normali nella configurazione di un firewall che deve proteggere una rete interna è quella di non lasciare che i pacchetti del protocollo UDP possano attraversarlo. In linea di principio questo atteggiamento è ragionevole, dal momento che con il protocollo UDP si gestiscono spesso informazioni delicate e aggredibili con facilità (NFS e NIS sono gli esempi più importanti).
#
iptables -A FORWARD -p udp -j DROP
[Invio]
Quello che si vede è il comando molto semplice che permette di ottenere questo risultato, intervenendo necessariamente in fase di attraversamento.
Il sistema DNS utilizza prevalentemente il protocollo UDP e a volte il protocollo TCP. In questo senso, un servizio DNS collocato all'interno di una rete protetta che abbia bisogno di risolvere nomi della rete esterna, deve necessariamente avvalersi di un altro servizio DNS posto nel firewall o anche al di fuori di questo.
|
L'esempio che si vede rappresenta una parte del file /etc/named.conf
(o /etc/bind/named.conf
) dove si indica l'indirizzo 123.123.123.123 da utilizzare per inoltrare le richieste che non possono essere risolte in base alla definizione delle zone locali. La comunicazione con il servizio presso 123.123.123.123 avviene con il protocollo TCP, permettendo di superare il problema del blocco al transito dei pacchetti UDP.
Il fatto che il sistema DNS utilizzi a volte il protocollo TCP per le comunicazioni normali deve servire a capire che un blocco del protocollo UDP può creare problemi intermittenti alla risoluzione dei nomi e degli indirizzi IP. |
Uno dei riferimenti importanti su cui si basa il controllo da parte del firewall è l'indirizzo di origine dei pacchetti. Spesso, chi attacca un sistema altera i pacchetti che invia modificando l'origine, per non essere individuato. Il firewall non è in grado di sapere se l'origine è veritiera o contraffatta.
Per risolvere questo problema con IPv4 si utilizza la gestione dell'instradamento attraverso la procedura denominata «Source Address Verification». Per prima cosa si deve verificare che esista il file virtuale /proc/sys/net/ipv4/conf/all/rp_filter
, quindi si possono sovrascrivere tutti i file /proc/sys/net/ipv4/conf/*/rp_filter
con il valore uno. In pratica:
|
In modo più grossolano è possibile eliminare i pacchetti che sono «evidentemente» contraffatti. Per esempio, se l'interfaccia di rete ppp0 è quella che si rivolge verso la rete esterna, si possono bloccare tranquillamente i pacchetti che provengono da questa con l'indicazione di un'origine appartenente a uno degli indirizzi riservati per le reti private.
|
Nel fare questo, tuttavia, bisogna tenere in considerazione che a volte, alcuni fornitori di accesso a Internet utilizzano degli indirizzi riservati alle reti private per le connessioni PPP; generalmente si tratta del gruppo 10.*.*.*. |
Di seguito vengono mostrati altri esempi che dovrebbero aiutare a comprendere ancora meglio il funzionamento di un firewall realizzato con un sistema GNU/Linux.
|
Questa regola impedisce il transito di tutti quei pacchetti che provengono da un'origine in cui l'indirizzo IP sia composto in modo da avere i primi tre bit a uno. Infatti, 22410 si traduce nel numero binario 111000002, che esclude tutta la classe D e la classe E degli indirizzi IPv4. Segue la visualizzazione della regola attraverso iptables -L FORWARD -n.
|
|
Questo esempio è esattamente identico a quello precedente, perché la destinazione predefinita è proprio quella riferita a qualunque indirizzo.
|
Consente ai pacchetti TCP provenienti dalla rete 192.168.1.* di attraversare il firewall per raggiungere qualunque indirizzo, ma solo alla porta 23. In pratica concede di raggiungere un servizio TELNET. Segue la visualizzazione della regola attraverso iptables -L FORWARD -n.
|
|
Blocca il transito delle comunicazioni riferite alla gestione remota di applicazioni per X. In questo caso, si presume di poter avere a che fare con sistemi che gestiscono fino a 10 serventi grafici contemporaneamente.
|
Blocca l'ingresso e l'uscita di comunicazioni riferite alla gestione remota di applicazioni per X. Questo potrebbe essere utile per proteggere un sistema che non si avvale di un firewall o che semplicemente non si fida della rete circostante.
|
Si consente l'ingresso e il transito di pacchetti relativi a connessioni già esistenti e di pacchetti correlati a connessioni già esistenti; si consente l'instaurazione di connessioni nuove, purché non provengano dall'interfaccia ppp0; si bloccano tutti gli altri pacchetti.
Con i kernel Linux 2.4.*, la contabilizzazione del traffico è implicita nel sistema di filtro del firewall: ogni regola che venga inserita in un punto di controllo accumula i propri contatori. In questo senso possono essere opportune anche regole che non hanno l'indicazione di alcun obiettivo, in quanto utili solo per selezionare una parte del traffico ai fini contabili.
Con l'opzione -v si può osservare il valore raggiunto dai vari contatori. Per esempio, disponendo di un'unica regola che cattura tutto il traffico in ingresso,
#
iptables -F INPUT
[Invio]
#
iptables -A INPUT
[Invio]
il comando
#
iptables -L INPUT -v -n
[Invio]
potrebbe generare un rapporto simile a quello seguente:
|
Si possono notare in particolare le colonne pkts e bytes che si riferiscono rispettivamente al numero di pacchetti IP e alla loro dimensione complessiva in byte. A fianco dei numeri che esprimono queste quantità potrebbero essere aggiunte delle lettere che rappresentano dei multipli: K, M e G. È importante osservare che questi esprimono multipli del sistema di numerazione decimale: 1 000, 1 000 000 e 1 000 000 000.(5)
L'azzeramento dei conteggi si ottiene con l'opzione di comando -Z (--zero), che interviene in tutte le regole dei punti di controllo indicati. Questa può essere utilizzata anche assieme all'opzione -L, in modo da non perdere informazioni.
Segue la descrizione di alcuni esempi.
#
iptables -L INPUT -v -n
[Invio]
Mostra tutte le informazioni disponibili sulle regole di ingresso, senza tradurre i dati numerici in nome. Tra le altre cose mostra anche i contatori del traffico.
#
iptables -Z INPUT
[Invio]
Azzera i conteggi riferiti alle regole di ingresso.
#
iptables -L -Z -v -n
[Invio]
Mostra tutte le informazioni disponibili di tutti i punti di controllo (ed eventualmente anche di altri raggruppamenti di regole), compresi i conteggi che vengono azzerati immediatamente dopo.
Esiste un obiettivo speciale, denominato LOG, con il quale si ottiene l'annotazione nel registro del sistema sull'intestazione del pacchetto, ogni volta che la regola ne intercetta uno. Tuttavia, in questo caso, quando un pacchetto viene intercettato da una regola del genere, questo continua poi a essere analizzato dalle regole successive, per poterlo utilizzare anche in modo differente.
|
L'esempio che si vede è abbastanza articolato, per farne comprendere il senso. Lo scopo è quello di annotare nel registro le connessioni in ingresso, attraverso l'interfaccia ppp0, che non siano autorizzabili a seguito di qualche correlazione con connessioni preesistenti.
La registrazione può avvenire anche indicando una sigla come prefisso, attraverso l'opzione --log-prefix, per distinguere facilmente le annotazioni. L'esempio seguente ripete quanto già mostrato in precedenza, con l'aggiunta del prefisso XXX iniziale:
|
Per controllare le segnalazioni che si ottengono in questo modo nel registro del sistema, si può fare riferimento alla voce kern.info. Per esempio, se nel file /etc/syslog.conf
si inserisce la direttiva seguente, si ottiene una copia di questi messaggi nella console /dev/tty11
:
|
Si osservi che in condizioni normali, tutti i messaggi di tipo *.info vengono inviati anche alla console attiva, contribuendo a disturbare il lavoro che lì vi viene svolto.
Oltre ai punti di controllo normali, è possibile definire delle raccolte di regole aggiuntive, a cui si può fare riferimento quasi come se fossero delle subroutine di un linguaggio di programmazione. Queste raccolte vengono identificate da un nome, al quale si può fare riferimento attraverso altre regole in qualità di obiettivo. In pratica, una regola posta in un punto di controllo può indicare un obiettivo corrispondente al nome di un altro raggruppamento di regole, che viene così a essere incorporato idealmente in quella posizione.
Per comprendere il meccanismo, si supponga di avere creato la raccolta di regole (chain) denominata prova, con una regola all'interno del punto di controllo di ingresso che vi faccia riferimento. Per cominciare, le regole contenute all'interno di prova potrebbero essere:
|
Come si può osservare in questo caso, si tratta di regole che servono solo alla contabilizzazione del traffico, dal momento che non sono stati indicati degli obiettivi.
Le regole di ingresso potrebbero essere quelle seguenti:
|
Si può osservare una regola il cui scopo è quello di individuare tutto il traffico TCP. Dal momento che l'obiettivo di questa è il raggruppamento prova, i pacchetti che rientrano nella selezione di questa regola vengono scomposti ulteriormente attraverso le regole del raggruppamento prova. I pacchetti che non vengono «catturati» da alcuna regola del raggruppamento prova tornano a essere presi in considerazione dalle regole successive nel punto di controllo di ingresso.
La creazione di un raggruppamento di regole si ottiene con l'opzione di comando -N (--new-chain) e la sua eliminazione con -X (--delete-chain). Per esempio, il comando
#
iptables -N prova
[Invio]
serve a creare il raggruppamento prova a cui si accennava in precedenza. L'inserimento di regole avviene nel modo normale; per continuare a seguire gli esempi fatti, i comandi dovrebbero essere i seguenti:
#
iptables -A prova -s 192.168.1.0/24
[Invio]
#
iptables -A prova -d 192.168.1.0/24
[Invio]
#
iptables -A prova -s 127.0.0.1
[Invio]
Così, l'inserimento della regola nel punto di controllo di ingresso che fa riferimento a questo raggruppamento, come mostrato dagli esempi in precedenza, si indica semplicemente con il comando seguente:
#
iptables -A INPUT -p tcp -j prova
[Invio]
L'eliminazione di un raggruppamento di regole è ammissibile solo quando questo è vuoto e quando non esistono più riferimenti da parte di altre regole nei punti di controllo normali.
#
iptables -D INPUT -p tcp -j prova
[Invio]
#
iptables -F prova
[Invio]
#
iptables -X prova
[Invio]
I comandi mostrati sopra servono rispettivamente a eliminare la regola di ingresso che faceva riferimento al raggruppamento prova, a svuotare il raggruppamento e infine a eliminarlo.
Quando si realizza un tunnel IPv6, come nel caso di 6to4, è necessario abilitare il traffico di questi pacchetti, che sono di tipo IPv4. Per la precisione, questi pacchetti vengono individuati da iptables come appartenenti al protocollo ipv6. Per esempio, per consentire l'ingresso e l'uscita di questi pacchetti, si possono usare i due comandi seguenti:
#
iptables -t filter -A INPUT -p ipv6 -s 0/0 -d 0/0 -j ACCEPT
[Invio]
#
iptables -t filter -A OUTPUT -p ipv6 -s 0/0 -d 0/0 -j ACCEPT
[Invio]
Naturalmente, volendo essere più precisi si può aggiungere l'indicazione dell'interfaccia coinvolta.
Rusty Russell, Linux 2.4 packet filtering HOWTO
<http://www.linux.org/docs/ldp/howto/HOWTO-INDEX/howtos.html>
Oskar Andreasson, IPTables Tutorial
<http://iptables-tutorial.frozentux.net/iptables-tutorial.html>
Terry Dawson, Linux NET-3-HOWTO, Linux Networking
<http://www.linux.org/docs/ldp/howto/HOWTO-INDEX/howtos.html>
Mark Grennan, Firewalling and Proxy Server HOWTO
<http://www.linux.org/docs/ldp/howto/HOWTO-INDEX/howtos.html>
Peter Bieringer, Linux IPv6 HOWTO
<http://www.linux.org/docs/ldp/howto/HOWTO-INDEX/howtos.html>
Appunti di informatica libera 2006.07.01 --- Copyright © 2000-2006 Daniele Giacomini -- <daniele (ad) swlibero·org>
1) Con un kernel 2.2.*, è soggetto a questo controllo anche se si tratta solo di un pacchetto in transito.
2) Con un kernel 2.2.* è soggetto a questo controllo anche se si tratta solo di un pacchetto in transito.
4) In questo caso, viene bloccato il pacchetto ICMP di richiesta di eco, quando tenta di «entrare» attraverso l'interfaccia lo.
5) Bisogna ricordare comunque che il SI specifica la lettera «k» minuscola come prefisso moltiplicatore che esprime il valore 103.
Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome kernel_linux_2_4_e_2_6_firewall.htm
[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico]