Avanti Indietro Indice

7. Usare iptables

Se hai bisogno di maggiori dettagli, iptables ha un completo manuale (man iptables). Tutti coloro che hanno familiarità con ipchains potrebbero aver bisogno di dare giusto un'occhiata a Differenze tra iptables e ipchains, anticipo che sono comunque molto simili.

Ci sono molte cose differenti che si possono fare con iptables. Si parte con tre catene preesistenti INPUT, OUTPUT e FORWARD che non si possono cancellare. Diamo un'occhiata alle operazioni utili per gestire intere catene:

  1. Crea una nuova catena (-N).
  2. Cancella una catena vuota (-X).
  3. Cambia la politica di una delle catene preesistenti. (-P).
  4. Elenca le regole presenti in una catena (-L).
  5. Svuota una catena delle sue regole (-F).
  6. Azzera i contatori dei pacchetti e dei byte di tutte le regole di una catena (-Z).

Ci sono poi diversi modi per manipolare le regole di una catena:

  1. Appendi una nuova regola alla catena (-A).
  2. Inserisci una nuova regola in una determinata posizione della catena (-I).
  3. Sostituisci una regola presente in una certa posizione della catena (-R).
  4. Cancella una regola presente in una certa posizione della catena (-D).
  5. Cancella la prima regola di una catena (-D).

7.1 Cosa vedrai quando avvierai il computer

iptables potrebbe essere un modulo, chiamato (`iptable_filter.o'), in questo caso dovrebbe essere caricato automaticamente la prima volta che eseguirai il comando iptables, oppure potrebbe essere incluso nel kernel.

Prima che qualsiasi comando iptables sia eseguito (presta attenzione, alcune distribuzioni eseguono iptables nei loro script di inizializzazione), nelle catene predefinite (`INPUT', `FORWARD' e `OUTPUT') non sono presenti regole, e tutte hanno una tattica di ACCEPT. Puoi tuttavia modificare la tattica di default della catena FORWARD impostando l'opzione `forward=0' nel modulo iptable_filter.

7.2 Operazioni su una singola regola

Questa è il pane e burro del filtraggio dei pacchetti: manipolare le regole. Nella maggior parte dei casi probabilmente utilizzerai i comandi appendi (-A) e cancella (-D), gli altri comandi (-I inserisci e -R sostituisci) sono delle semplici estensioni di questi concetti.

Ogni regola specifica un insieme di condizioni che il pacchetto deve soddisfare, e che cosa fare se le soddisfa (obiettivo). Per esempio, potresti voler rifiutare tutti i pacchetti ICMP provenienti dall'indirizzo IP 127.0.0.1. In questo caso le tue condizioni dovrebbero essere che il protocollo sia ICMP e che l'indirizzo sorgente sia 127.0.0.1, mentre l'obiettivo dovrebbe essere impostato a `DROP' (scarta).

127.0.0.1 è l'interfaccia di `loopback' che hai sicuramente anche senza possedere alcuna connessione reale ad una rete. Puoi usare il programma `ping' per generare questo tipo di pacchetti (non fa altro che inviare un ICMP di tipo 8 (echo request), tutti gli host raggiunti dovrebbero rispondere con un pacchetto ICMP tipo 0 (echo reply)). Questo è molto utile per fare dei test.

# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#

Come puoi notare il primo ping ha avuto successo (il `-c 1' serve ad indicare al ping di inviare un solo pacchetto).

Ora appendiamo (-A) alla catena `INPUT', una regola che indichi che i pacchetti provenienti dall'indirizzo 127.0.0.1 (`-s 127.0.0.1') con protocollo ICMP (`-p icmp') devono essere scartati (`-j DROP').

Proviamo quindi la nostra regola usando un secondo ping. Dovrebbe esserci una pausa prima che il programma, in attesa di una risposta che non arriverà mai, si arrenda e abbandoni.

Possiamo cancellare la regola in uno, due modi. Innanzi tutto se sappiamo che la catena input ha solo una regola, possiamo usare una `cancellazione numerata', ossia

        # iptables -D INPUT 1
        #

Questo comando rimuove la prima regola della catena INPUT.

Il secondo modo consiste nel ripetere la linea del comando -A, ma sostituendo -A con -D. Molto utile quando hai una catena complessa di regole e non vuoi contarle ad una ad una per scoprire che la regola di cui vuoi sbarazzarti è la 37esima. In questo caso usa:

        # iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
        #

La sintassi di -D deve avere le stesse opzioni dei comandi -A (o -I o -R). Se ci sono regole multiple e identiche nella stessa catena, solo la prima sarà cancellata.

7.3 Specificare cosa filtrare

Abbiamo già visto l'uso dell'opzione `-p' per specificare il protocollo, e di `-s' per specificare l'indirizzo sorgente, esistono però anche altre opzioni per indicare altre caratteristiche dei pacchetti. Ciò che segue è un compendio piuttosto completo.

Specificare gli indirizzi IP sorgente e destinazione

Gli indirizzi IP sorgente (`-s', `--source' o `--src') e destinazione (`-d',`--destination' o `--dst') possono essere specificati in 4 modi diversi. Il più comune è di usare il nome completo, ad esempio `localhost' o `www.linuxhq.com'. Il secondo modo è quello di specificare l'indirizzo IP ad esempio `127.0.0.1'.

La terza e la quarta modalità permettono di specificare un gruppo di indirizzi IP, ad esempio `199.95.207.0/24' oppure `199.95.207.0/255.255.255.0'. Entrambe specificano qualsiasi indirizzo IP a partire da 199.95.207.0 fino a 199.95.207.255. Di default viene usato `/32' o `/255.255.255.255' (tutti gli indirizzi IP). Si può anche usare `/0' per specificare nessun indirizzo IP, come in questo caso:

        [ NOTA: `-s 0/0' qui è ridondante. ]
        # iptables -A INPUT -s 0/0 -j DROP
        #

E' comunque usato raramente visto che ha lo stesso effetto che si ottiene non specificando affatto l'opzione `-s'.

Specificare una negazione

Molte opzioni, incluse `-s' (o `--source') e `-d' (`--destination') possono avere gli argomenti preceduti dal carattere `!' (si pronuncia `not'), usato per indicare gli indirizzi NON (not) uguali a quello indicato. Per esempio `-s ! localhost' indica qualsiasi pacchetto non proveniente da localhost.

Specificare il protocollo

Il protocollo può essere specificato usando l'opzione `-p' (o `--protocol'). Il protocollo può essere un numero (se conosci il valore numerico del protocollo per IP), oppure un nome, per i casi particolari `TCP', `UDP' o `ICMP'. Maiuscolo o minuscolo non fa differenza, `tcp' va bene come anche `TCP'.

Il nome del protocollo può essere preceduto da un `!', per negarlo, ad esempio con `-p ! TCP' si specificano tutti i pacchetti che non sono TCP.

Specificare un'interfaccia

Le opzioni `-i' (o `--in-interface') e `-o' (o `--out-interface') servono a specificare il nome di un'interfaccia. Un'interfaccia è il dispositivo fisico dal quale un pacchetto entra (`-i') o esce (`-o'). Usa il comando ifconfig per ottenere un elenco delle interfacce `attive' (funzionanti in quel momento).

I pacchetti che attraversano la catena INPUT non hanno un'interfaccia di output, perciò qualsiasi regola che usa `-o' in questa catena non troverà mai una corrispondenza. Allo stesso modo i pacchetti che attraversano la catena OUTPUT non hanno un'interfaccia di input, quindi nessuna regola che usi `-i' in questa catena troverà mai una corrispondenza.

Solo i pacchetti che attraversano la catena FORWARD hanno sia un'interfaccia di input che di output.

E' perfettamente legale specificare un'interfaccia che al momento non esiste; la regola non sarà mai soddisfatta fino a quando l'interfaccia non sarà attivata. Ciò è estremamente utile per i collegamenti dial-up PPP (di solito interfaccia ppp0) e simili.

Come caso speciale, un nome di interfaccia che termina con un `+' corrisponderà a tutte le interfacce (esistenti o meno) che cominciano con quella stringa. Per esempio, per specificare una regola che corrisponda a tutte le interfacce PPP si può utilizzare l'opzione -i ppp+.

Il nome dell'interfaccia può essere preceduto da un `!' per far sì che sia soddisfatta da tutte le interfacce che NON corrispondono all'interfaccia (o alle interfacce) specificata.

Specificare i frammenti

Qualche volta un pacchetto è troppo grande per passare tutto in una volta attraverso il cavo. Quando accade, il pacchetto viene suddiviso in frammenti, e spedito sotto forma di pacchetti multipli. L'altro estremo della connessione si occuperà di riassemblare questi frammenti e di ricostruire l'intero pacchetto.

Il problema dei frammenti è che il frammento iniziale contiene i campi completi delle intestazioni (IP + TCP, UDP e ICMP) da esaminare, mentre i pacchetti successivi hanno solo un sottoinsieme delle intestazioni (IP senza i campi dei protocolli addizionali). Ed è proprio per questa ragione che non è possibile sbirciare le intestazioni dei protocolli in questi pacchetti.

Se stai effettuando il tracciamento delle connessioni (connection tracking) o il NAT, tutti i frammenti saranno ricomposti prima che raggiungano il codice che si occupa di filtrare i pacchetti, perciò non c'è motivo di temere i frammenti.

E' importante comunque comprendere come i frammenti vengono considerati dalle regole di filtraggio. Qualsiasi regola di filtraggio che richieda informazioni, che in realtà non sono presenti, non sarà soddisfatta. Quindi il primo frammento sarà trattato come un qualsiasi pacchetto, il secondo e i successivi no. In questo modo una regola -p TCP --sport www che specifica una porta d'origine `www' non sarà mai soddisfatta da un frammento (escluso il primo). E nemmeno la regola opposta -p TCP --sport ! www.

Si può comunque indicare una regola specifica per il secondo e i successivi frammenti usando l'opzione `-f' (o `--fragment'). Inoltre è perfettamente legale specificare una regola con cui si indica, inserendo `!' prima di `-f', che questa non deve essere applicata al secondo e ai successivi frammenti.

Di solito è considerata buona norma lasciar passare il secondo e i successivi frammenti, poiché il filtraggio avrà effetto sul primo frammento, prevenendo la ricostruzione nell'host di destinazione. Sono noti comunque alcuni bug che causano il crash delle macchine semplicemente inviando dei frammenti. Sei avvisato.

Una nota per i capoccioni della rete: i pacchetti malformati (TCP, UDP e i pacchetti ICMP troppo "corti" affinché il codice di firewalling possa leggere le porte o il codice e tipo ICMP) quando sono esaminati sono scartati. Sono considerati insomma frammenti TCP che iniziano alla posizione 8.

Ad esempio, la regola seguente scarterà qualsiasi frammento diretto a 192.168.1.1:

# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
#

Estensioni di iptables: nuovi confronti

iptables è estendibile, ossia sia il kernel che il tool iptables possono essere estesi per fornire nuove caratteristiche.

Alcune di queste estensioni sono standard, altre sono più esotiche. Le estensioni possono essere realizzate da altre persone e distribuite separatamente per nicchie di utenti.

Le estensioni del kernel normalmente si trovano nella sottodirectory dei moduli del kernel, ad esempio /lib/modules/2.3.15/net. Sono poi caricate a richiesta, a meno che il kernel non sia stato compilato con la voce CONFIG_KMOD attivata, in questo caso non sarà necessario caricarli manualmente.

Le estensioni del programma iptables sono delle librerie condivise collocate nella directory /usr/local/lib/iptables/, sebbene una distribuzione potrebbe anche inserirle in /lib/iptables o /usr/lib/iptables.

Le estensioni sono di due tipi: nuovi obiettivi (target) e nuovi confronti. Parleremo dei nuovi obiettivi più avanti. Alcuni protocolli offrono nuovi test, correntemente questi sono TCP, UDP e ICMP come mostrati sotto.

Per questi ultimi puoi specificare i nuovi test sulla linea di comando dopo l'opzione `-p', che provvederà a caricare l'estensione. Nel caso di nuovi test specifici, per caricare l'estensione, si utilizzerà l'opzione `-m', dopo di ché saranno disponibili le opzioni delle estensioni.

Per ottenere aiuti sulle estensioni, usa l'opzione per caricarle (`-p', `-j' o `-m') seguite da `-h' o `--help', ad esempio:

# iptables -p tcp --help
#

Estensioni TCP

Le estensioni riguardanti TCP sono caricate automaticamente se si specifica l'opzione `-p tcp'. Si possono così usare le seguenti opzioni (nessuna di queste viene soddisfatta dai frammenti).

--tcp-flags

Seguita eventualmente da un `!', e da due stringhe di flag, permette di filtrare in base ai flag specifici di TCP. La prima stringa di flag è la maschera: lista di flag che vuoi esaminare. La seconda stringa di flag invece serve ad indicare quale o quali dovrebbero risultare impostati.

Ad esempio:

# iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DENY

Questo comando indica che devono essere esaminati tutti i flag (`ALL' è sinonimo di `SYN,ACK,FIN,RST,URG,PSH'), ma solo i flag SYN e ACK dovrebbero risultare impostati. Esiste anche un argomento `NONE' che indica nessun flag.

--syn

è un'abbreviazione di `--tcp-flags SYN,RST,ACK SYN' e può essere preceduta da `!'.

--source-port

Seguita eventualmente da un `!', e da una porta TCP singola o un intervallo di porte. Le porte possono essere indicate con il nome, come elencate in /etc/services, o con i numeri. Gli intervalli possono essere due porte separate da un `-', o una porta seguita da un `-' (per specificare tutte le porte uguali o maggiori di quella indicata) oppure una porta preceduta da un `-' (per specificare tutte le porte uguali o inferiori di quella indicata).

--sport

è sinonimo di `--source-port'.

--destination-port

e

--dport

sono equivalenti a ciò che abbiamo appena visto, solamente che servono a specificare la porta di destinazione, invece di quella sorgente.

--tcp-option

Seguita eventualmente da `!' e da un numero, un pacchetto la soddisfa se ha un'opzione TCP uguale a questo numero. Un pacchetto che non ha un'intestazione TCP completa viene automaticamente scartato al momento della verifica delle sue opzioni TCP.

Un chiarimento sui flag del TCP

Qualche volta è utile permettere connessioni TCP in una direzione ma non nell'altra. Per esempio, potresti aver voglia di permettere connessioni verso un server WWW esterno, ma non da questo verso di te.

L'approccio più semplice sarebbe quello di bloccare i pacchetti TCP provenienti dal server. Sfortunatamente le connessioni TCP per funzionare correttamente richiedono che i pacchetti viaggino in entrambe le direzioni.

La soluzione consiste nel bloccare solo i pacchetti usati per richiedere una connessione. Questi pacchetti sono detti pacchetti SYN (ok, tecnicamente sono pacchetti con il flag SYN impostato, e i flag FIN ed ACK azzerati, ma per comodità li chiameremo pacchetti SYN). Se non accettiamo solo questi pacchetti allora possiamo impedire i tentativi di connessione.

Il flag `--syn' è usato a questo scopo ed è valido solo per regole che specificano TCP come protocollo. Ad esempio, per specificare un tentativo di connessione TCP da 192.168.1.1 usare:

-p TCP -s 192.168.1.1 --syn

Questo flag può essere negato facendolo precedere da un `!', che sta a significare qualsiasi pacchetto eccetto quello di inizio connessione.

Estensioni UDP

Queste estensioni sono caricate automaticamente se si specifica `-p udp'. Si potranno così utilizzare le opzioni `--source-port', `--sport', `--destination-port' e `--dport' come spiegato prima riguardo al TCP.

Estensioni ICMP

Queste estensioni sono caricate automaticamente se si specifica `-p icmp'. Fornisce solo una nuova opzione:

--icmp-type

seguita eventualmente da un `!', oltre che dal nome di un tipo di icmp (es. `host-unreachable'), o da un tipo numerico (es. `3'), o da un tipo numerico più codice separati da un `/' (es. `3/3'). Si può ottenere un elenco dei tipi di icmp utilizzando `-p icmp --help'.

Altre estensioni

Le altre estensioni presenti nel pacchetto netfilter sono le estensioni dimostrative, che (se installate) possono essere invocate con l'opzione `-m'.

mac

Questo modulo deve essere specificato esplicitamente con `-m mac' o `--match mac'. E' usato per confrontare i pacchetti in arrivo da una sorgente con indirizzo Ethernet (MAC), ed è utile per i pacchetti che attraversano le catene PREROUTING e INPUT. E' presente una sola opzione:

--mac-source

seguita eventualmente da un `!' (opzionale), e da un indirizzo ethernet in notazione hexbyte separata dal simbolo `:', es. `--mac-source 00:60:08:91:CC:B7'.

limit

Questo modulo deve essere specificato esplicitamente con `-m limit' o `--match limit'. E' usato per restringere il numero di confronti, come anche per sopprimere i messaggi di log. Effettuerà confronti solo un certo numero di volte al secondo (per default 3 confronti all'ora, con un burst (raffica) di 5). Richiede due argomenti facoltativi:

--limit

seguita da un numero, specifica la media massima di confronti permessi al secondo. Si può specificare l'unità esplicitamente usando `/second', `/minute', `/hour' o `/day', o parte di essi (quindi `5/second' è equivalente a `5/s').

--limit-burst

seguita da un numero, indica il massimo burst (raffica) prima che il limite visto sopra li respinga.

Queste estensioni possono essere usate spesso con l'obiettivo LOG per limitare il numero di registrazioni. Per comprendere come funzionano, diamo un'occhiata alla seguente regola, che registra i pacchetti usando i parametri di default di limit:

# iptables -A FORWARD -m limit -j LOG

La prima volta che la regola è consultata, il pacchetto sarà registrato, infatti il burst (raffica) per default è impostato a 5, i primi cinque pacchetti saranno perciò registrati. Dopo di ché, dovranno trascorrere venti minuti prima che un pacchetto sia nuovamente registrato da questa regola, senza riguardo al numero dei pacchetti arrivati. Inoltre ogni venti minuti trascorsi senza che siano giunti pacchetti, uno di questi sarà recuperato nel burst; se nessun pacchetto viene sottoposto alla regola per 100 minuti, il burst sarà completamente ricaricato; da dove cominciato.

Attualmente non è possibile creare una regola con un tempo di ricarica maggiore di 59 ore, perciò se imposti un flusso medio di 1 per ogni giorno, allora il burst (raffica) dovrà essere inferiore a 3.

Puoi usare questo modulo anche per evitare i vari attacchi denial of service (DoS) impostando un rate maggiore per incrementare la reattività.

Protezione dal Syn-flood:

# iptables -A FORWARD -p tcp --syn -m limit 1/s -j ACCEPT

Port scanner sospetti:

# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit 1/s -j ACCEPT

Ping della morte (Ping of death):

# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit 1/s -j ACCEPT

Questo modulo funziona come una "porta isterica", come mostrato nel seguente grafico.

       rate (pacchetti/s)  
             ^        .---.
             |       / DoS \
             |      /       \
Limite DoS  -|.....:.........\.......................
 = (limit *  |    /:          \
limit-burst) |   / :           \         .-.
             |  /  :            \       /   \
             | /   :             \     /     \
Fine DoS    -|/....:..............:.../.......\..../.
 = limit     |     :              :`-'         `--'
-------------+-----+--------------+------------------> tempo (s)
  LOGICA =>  Confr.|  Non confr.  |    Confronta

In questo modo diciamo di confrontare un pacchetto al secondo con un burst (raffica) di cinque pacchetti, i pacchetti cominciano ad arrivare quattro volte al secondo, per tre secondi, poi ancora per altri tre secondi.

           <--Flusso 1-->           <---Flusso 2--->

Pacchetti ^                   Line  __--      YNNN
 Totali   |               Rate  __--      YNNN
          |            mum  __--      YNNN
       10 |        Maxi __--         Y
          |         __--            Y
          |     __--               Y
          | __--    YNNN           
          |-    YNNN
        5 |    Y    
          |   Y                             Legenda:  Y -> Regola soddisfatta
          |  Y                                        N -> Regola non soddisfatta
          | Y
          |Y 
        0 +-------------------------------------------------->  Tempo (secondi)
           0   1   2   3   4   5   6   7   8   9  10  11  12

Come puoi vedere è consentito ai primi 5 pacchetti eccedere il pacchetto al secondo, ossia il limite fissato. Se c'è una pausa, è consentito un altro burst (raffica) che però non deve eccedere il rate massimo fissato con la regola (in questo caso 1 pacchetto al secondo dopo che il burst è stato usato).

owner

Questo modulo tenta di confrontare varie caratteristiche del creatore dei pacchetti generati localmente. E' valido solo nella catena OUTPUT, anche nel caso in cui alcuni pacchetti (come ad esempio risposte a ICMP ping) non abbiamo un proprietario, e che quindi non siano confrontabili.

--uid-owner userid

Confronta se il pacchetto è stato creato da un processo con lo user id (numerico) effettivo indicato.

--uid-owner groupid

Confronta se il pacchetto è stato creato da un processo con il group id (numerico) effettivo indicato.

--pid-owner processid

Confronta se il pacchetto è stato creato da un processo con l'id di processo indicato.

--sid-owner processid

Confronta se il pacchetto è stato creato da un processo della sessione di gruppo indicata.

unclean

Questo modulo sperimentale deve essere specificato esplicitamente con `-m unclean' o `--match unclean'. Effettua vari controlli casuali sulla correttezza di un pacchetto. Questo modulo non è stato verificato e non dovrebbe essere usato per la sicurezza (probabilmente può portare a dei peggioramenti in quanto potrebbe contenere dei bug). Non sono disponibili opzioni.

Condizione state

Il criterio di selezione più utile è dato dall'estensione `state', che interpreta le analisi del connection-tracking (tracciamento delle connessioni) del modulo `ip_conntrack'. Questo modulo è assolutamente raccomandato.

Specificando `-m state' si può utilizzare l'opzione addizionale `--state', seguita da una lista di stati, separati da virgole, da confrontare (il flag `!' indica di non confrontare questi stati). Questi stati sono:

NEW

Un pacchetto che crea una nuova connessione.

ESTABLISHED

Un pacchetto che appartiene ad una connessione esistente (ossia una connessione che ha avuto dei pacchetti in risposta).

RELATED

Un pacchetto che è relativo, ma che non fa parte, di una connessione esistente, come ad esempio un errore ICMP, o (con il modulo FTP caricato) un pacchetto che tenta una connessione ftp data.

INVALID

Un pacchetto che non può essere identificato per alcune ragioni, tra cui ad esempio esaurimento della memoria ed errori ICMP che non corrispondono a nessuna connessione conosciuta. Generalmente questi pacchetti dovrebbero essere scartati.

7.4 Specificare gli obiettivi

Ora conosciamo quali controlli possiamo effettuare sui pacchetti, abbiamo quindi bisogno di qualcosa che dica cosa fare dei pacchetti che soddisfano i nostri test. Questo è chiamato obiettivo (target) di una regola.

Ci sono due semplici obiettivi già disponibili: DROP e ACCEPT. Li abbiamo già incontrati. Se un pacchetto soddisfa una regola e l'obiettivo è uno di questi due, nessun'altra regola è consultata: il destino del pacchetto è stato deciso.

Ci sono altri due tipi di obiettivi oltre a quelli già disponibili: le estensioni e le catene create dall'utente.

Catene create dall'utente

Una caratteristica potente che iptables ha ereditato da ipchains è la possibilità per l'utente di creare nuove catene, che si aggiungono alle tre catene già disponibili (INPUT, FORWARD e OUTPUT). Per distinguerle, le catene create dall'utente per convenzione sono in minuscolo (descriveremo come creare una nuova catena successivamente in Operazioni su intere catene).

Quando un pacchetto soddisfa una regola che ha per obiettivo una catena creata dall'utente, il pacchetto comincia ad attraversare le regole di quest'ultima. Se la catena termina e il destino del pacchetto non è stato deciso allora si passa nuovamente alla catena corrente però alla regola successiva.

E ancora tempo di arte ASCII. Considera due (sciocche) catene: INPUT (catena già disponibile) e test (catena creata dall'utente).

         `INPUT'                         `test'
        ----------------------------    ----------------------------
        | Regola1: -p ICMP -j DROP |    | Regola1: -s 192.168.1.1  |
        |--------------------------|    |--------------------------|
        | Regola2: -p TCP -j test  |    | Regola2: -d 192.168.1.1  |
        |--------------------------|    ----------------------------
        | Regola3: -p UDP -j DROP  |
        ----------------------------

Considera un pacchetto TCP proveniente da 192.168.1.1 e diretto a 1.2.3.4. Questo entra nella catena INPUT, viene sottoposto alla Regola1 - non soddisfatta. Regola2 invece è soddisfatta, e il suo obiettivo è test, perciò la regola successiva a cui sottoporre il pacchetto è la prima di test. La Regola1 di test è soddisfatta, ma non specifica un obiettivo, quindi viene esaminata la regola successiva, Regola2. Questa non è soddisfatta, e inoltre abbiamo raggiunto la fine della catena. Torniamo alla catena INPUT, dove abbiamo già esaminato Regola2, perciò passiamo a Regola3, che non è soddisfatta.

Quindi il percorso del pacchetto è:

                                v    __________________________
         `INPUT'                |   /    `test'                v
        ------------------------|--/    -----------------------|----
        | Regola1               | /|    | Regola1              |   |
        |-----------------------|/-|    |----------------------|---|
        | Regola2               /  |    | Regola2              |   |
        |--------------------------|    -----------------------v----
        | Regola3               /--+___________________________/
        ------------------------|---
                                v

Le catene definite dall'utente possono saltare in altre catene sempre definite dall'utente (ma non creare dei cicli: i pacchetti appartenenti ad un ciclo saranno scartati).

Estensioni a iptables: nuovi obiettivi

Un altro tipo di obiettivo può essere un'estensione. Un obiettivo estensione, per provvedere nuove opzioni per la linea di comando, deve consistere in un modulo per il kernel, e in un'estensione opzionale per iptables. Ci sono molte estensioni incluse nella distribuzione di netfilter:

LOG

Questo modulo permette la registrazioni da parte del kernel dei pacchetti specificati. Ha le seguenti opzioni:

--log-level

seguito da un numero o nome di livello. Nomi validi sono (minuscoli o maiuscoli) `debug', `info', `notice', `warning', `err', `crit', `alert' e `emerg', che corrispondono in ordine ai numeri dal 7 allo 0. Leggi le pagine del manuale di syslog.conf per una spiegazione di questi livelli.

--log-prefix

seguito da una stringa di max. 30 caratteri, questo messaggio è collocato all'inizio del messaggio registrato, per permettere di poterlo identificare immediatamente.

Questo modulo è molto utile dopo un obiettivo limit, in quanto evita un numero esagerato di registrazioni.

REJECT

Questo modulo ha lo stesso effetto di `DROP', però in più viene inviato in risposta un messaggio di errore ICMP di tipo `port unreachable'. Nota che il messaggio di errore non è inviato se (vedi RFC 1122):

REJECT ha inoltre un `--reject-with' opzionale che altera il pacchetto inviato in risposta: leggi le pagine del manuale.

Obiettivi speciali già disponibili

Ci sono due obiettivi speciali già disponibili: : RETURN e QUEUE.

RETURN ha lo stesso effetto di quando si arriva alla fine di una catena: se l'ultima regola appartiene a una catena predefinita, allora viene eseguita la tattica della catena. Altrimenti se appartiene ad una catena definita dall'utente, si prosegue con la catena precedente, con la regola successiva a quella che aveva causato il salto nella catena dell'utente.

QUEUE è un obiettivo speciale, che accoda i pacchetti per elaborazioni userspace. Perché possa essere utile sono necessari ulteriori componenti:

Il gestore standard della coda, per IPV4 e iptables, è il modulo ip_queue, distribuito con il kernel ancora come sperimentale.

Il seguente è un esempio veloce di come si possa usare iptables per accodare i pacchetti per elaborazioni userspace:

# modprobe iptable_filter
# modprobe ip_queue
# iptables -A OUTPUT -p icmp -j QUEUE
Con questa regola i pacchetti ICMP generati localmente (creati diciamo con ping) sono passati al modulo ip_queue che tenta di consegnarli all'applicazione userspace. Se non c'è in attesa un'applicazione userspace i pacchetti saranno scartati.

Per scrivere un'applicazione userspace, usa le API della libipq, distribuita con iptables. Sorgenti di esempio si possono trovare nella suite di tool di test (es. redirect.c) nella CVS.

Lo stato della ip_queue può essere verificato attraverso:

/proc/net/ip_queue
La lunghezza massima della coda (ossia il numero di pacchetti consegnati allo userspace senza emissione di verdetto) può essere controllata attraverso:

/proc/sys/net/ipv4/ip_queue_maxlen
Il valore di default della lunghezza massima della coda è fissata a 1024. Quando questo limite è raggiunto, i nuovi pacchetti saranno scartati finché la lunghezza della coda non tornerà nuovamente sotto il limite. Protocolli buoni come TCP interpretano i pacchetti scartati come congestione, e speranzosi rinunciano quando la coda è piena. Comunque può fare alcuni esperimenti per determinare una lunghezza massima ideale della coda per una certa situazione se il valore di default è troppo piccolo.

7.5 Operazioni su intere catene.

Una caratteristica veramente utile di iptables è l'abilità di raggruppare regole correlate in catene. Puoi chiamare una catena come vuoi, ma raccomando di usare lettere minuscole per evitare confusioni con le catene predefinite e con gli obiettivi. I nomi delle catene possono arrivare ad una lunghezza di 31 lettere.

Creare una nuova catena

Creiamo una nuova catena. Visto che sono una persona di grande immaginazione, chiamiamola test. Usiamo l'opzione `-N' oppure `--new-chain':

# iptables -N test
#

Questa è semplice. Ora possiamo aggiungervi le regole come spiegato precedentemente.

Cancellare una catena

Cancellare una catena è ugualmente semplice, basta usare l'opzione `-X' o `--delete-chain'. Perché `-X'? Beh, le altre lettere buone erano già state assegnate.

# iptables -X test
#

Ci sono un paio di restrizioni che riguardano la cancellazione delle catene: devono essere vuote (vedi Svuotare una catena sotto) e non devono essere l'obiettivo di nessuna regola. Non puoi inoltre cancellare nessuna delle tre catene predefinite.

Se non si specifica una catena, allora tutte le catene definite dall'utente saranno cancellate, se possibile.

Svuotare una catena

C'è un modo semplice per svuotare una catena di tutte le sue regole, ossia usare il comando `-F' (o `--flush').

# iptables -F forward
#

Se non si specifica una catena, allora tutte le catene saranno svuotate.

Consultare una catena

Puoi ottenere una lista delle regole di una catena usando il comando `-L' (o `--list').

Il valore `refcnt' mostrato per ogni catena definita dall'utente rappresenta il numero delle regole che hanno questa catena come loro obiettivo. Deve essere a zero (catena vuota) prima di poter cancellare una catena.

Se il nome della catena è omesso, saranno elencate tutte le catene, anche quelle vuote.

Ci sono tre opzioni che possono accompagnare `-L'. L'opzione `-n' (numeric) è davvero utile in quanto previene che iptables cerchi di capire a quale nome corrisponde l'indirizzo IP, che (se stai utilizzando il DNS come fanno molte persone) causa lunghe attese se il DNS non è impostato correttamente, o se le richieste DNS sono respinte dal filtraggio. Inoltre visualizza le porte TCP e UDP con i rispettivi numeri invece che con i nomi.

L'opzione `-v' mostra tutti i dettagli delle regole, come i contatori dei pacchetti e dei byte, le comparazioni TOS, e le interfacce. Se non la si specifica queste informazioni sono omesse.

Nota che i contatori dei pacchetti e dei byte sono visualizzati usando il suffisso `K', `M' o `G' che significano rispettivamente 1000, 1000000 e 1000000000. Usando l'opzione `-x' (expand numbers) verranno visualizzati i numeri completi, senza preoccuparsi di quanto siano grandi.

Resettare (azzerare) i contatori

E' utile resettare i contatori. Ciò può essere ottenuto con l'opzione `-Z' (o `--zero').

Il problema con questo approccio è che talvolta si ha bisogno di conoscere i valori dei contatori immediatamente prima che vengano azzerati. Nell'esempio suddetto, alcuni pacchetti potrebbero passare tra i comandi `-L' e `-Z'. Per questa ragione, per resettarli mentre li si sta leggendo, è possibile usare `-L' e `-Z' assieme.

Impostare la tattica

Abbiamo visto cosa succede quando un pacchetto raggiunge la fine della catena predefinita precedentemente, quando abbiamo parlato di come i pacchetti attraversano le catene. In questo caso, la tattica della catena determina il destino del pacchetto. Solo le catene predefinite (INPUT, OUTPUT e FORWARD) hanno delle tattiche, in quanto se un pacchetto raggiunge la fine di una catena definita dall'utente, proseguirà riprendendo il percorso della catena precedente.

La tattica può essere ACCEPT o DROP.


Avanti Indietro Indice