:: SNR - iptables ::
Che cos'è
iptables è l'applicazione che serve per modificare i parametri di netfilter, che a sua volta è il sistema di gestione dei pacchetti integrato nel kernel di Linux.
Nel corso si Sicurezza nelle Reti si impara ad utilizzare iptables per configurare un firewall.
Per la sintassi di iptables, è opportuno consultare la pagina man relativa. Qui si assume che si sappia come scrivere regole, e si cerca di dare risposte agli esercizi visti in classe.
Logging
Le regole di logging vanno messe prima delle corrispondenti regole bloccanti. Le regole di logging non sono bloccanti: quando vengono interpretate, l'esecuzione della chain non si ferma ma prosegue. Così non avviene per le regole "normali": se una di esse viene soddisfatta, non si prosegue alla regola successiva, ma netfilter si ferma. Per questo motivo vanno scritte prima.
Esempio:
iptables -A OUTPUT -o eth0 -p tcp -d 192.168.10.3 --dport 80 -j LOG
--log-prefix "Server HTTP:"
iptables -A OUTPUT -o eth0 -p tcp -d 192.168.10.3 --dport 80 -j ACCEPT
La regola di logging è identica, se non per l'azione, che è LOG invece che ACCEPT.
La direttiva --log-prefix seguita da una stringa compresa tra virgolette scrive, nel log di sistema, quella stringa prima del log effettivo. Questo è utile ad esempio per poter selezionare in modo automatico le righe interessanti dal log. Ad esempio:
dmesg|grep "Server HTTP:"
prenderà dal log di sistema le sole righe che conterranno da qualche parte la scritta "Server HTTP:", che guarda caso è quella che abbiamo inserito noi come prefisso nella regola di logging.
Flags
Per indicare regole relativa ai flag tcp, si usa la seguente sintassi:
--tcp-flags SYN,ACK SYN,ACK
Il significato è il seguente:
- le prime due occorrenze di SYN,ACK dicono a iptables di controllare, nel pacchetto, i flag SYN e ACK
- le seconde due occorrenze di SYN,ACK dicono invece QUALI dei due pacchetti devono essere settati a uno
Per esempio, scrivendo
--tcp-flags SYN,ACK SYN
sto filtrando i pacchetti che hanno SYN a 1 ma ACK a 0. Infatti ACK non compare nella seconda serie di flag. Sembra contorto e probabilmente lo è...:)
Stati
iptables ha nozione delle connessioni: sa identificare un pacchetto come appartenente o meno ad una connessione. In particolare, i pacchetti possono essere in uno dei seguenti stati:
- NEW = è un pacchetto che tenta di iniziare una connessione
- ESTABLISHED = il pacchetto appartiene ad una connessione già esistente
- RELATED = il pacchetto non fa parte di una connessione, ma la riguarda (ICMP)
Gli stati si usano per evitare di scrivere cose strane con i flag. Per fare un esempio, se vogliamo permettere le connessioni in uscita dalla nostra macchina al server del professore, sulla porta TCP 80, scriveremo:
iptables -A OUTPUT -o eth0 -p tcp -d $PROF --dport 80 -m state
--state NEW,ESTABLISHED -j ACCEPT
Questa riga significa che i pacchetti che si trovano nello stato NEW oppure ESTABLISHED andranno accettati. Infatti, se sono io a comunicare con un server, allora farò io i tentativi di connessioni (ecco perché scrivo NEW). Oltre a quelli invierò anche altra roba, legata alla connessione, e questo spiega l'ESTABLISHED.
Lato input, invece, se vogliamo che dalla porta 80 del server arrivino solo risposte a nostre precise interrogazioni, e NON tentativi di nuove connessioni, avremo una regola così:
iptables -A INPUT -i eth0 -p tcp -s $PROF --sport 80 -m state --state ESTABLISHED -j ACCEPT
che dice a Netfilter di accettare solo quei paccheti che provengono da $PROF:80 e che fanno parte di una connessione già esistente. Se avessimo avuto -m state --state NEW,ESTABLISHED nella regola qui sopra, avremmo dato il permesso di connettersi a noi a partire dalla porta 80 della macchina $PROF: grave:)
Ricordiamo che anche per i pacchetti UDP si usano le nozioni di stato: voci divine asseriscono che dimenticare ciò consista in un errore in sede d'esame. E noi che siamo andati avanti per anni a credere che UDP fosse senza connessione...:/
Loggare in modo opportuno le connessioni andate a buon fine e quelle rifiutate
Prendiamo un tentativo di connessione dalla nostra macchina alla porta 666 di un server. Se quella porta è aperta, ci arriveranno pacchetti in risposta. Se quella porta è chiusa, presumibilmente la connessione verrà terminata subito.
Se c'è la necessità di loggare in modo diverso queste due evenienze, occorre fare così:
iptables -A INPUT -p tcp -s $PROF --sport 666 -m state --state ESTABLISHED
-j LOG --log-prefix "CONN OK"
iptables ... --tcp-flags RST,ACK RST,ACK -j LOG --log-prefix "CONN REFUSED"
Queste righe fanno sì che i pacchetti in arrivo da $PROF:80, con i flag RST e ACK a 1, verranno marcati in modo particolare nel log. Infatti, se una porta è chiusa lo stack TCP comunica l'intenzione di terminare la connessione.
Se si tratta di un tentativo di comunicazione UDP, la mancata consegna di un datagram al server verrà notificata tramite la ricezione di un pacchetto ICMP, che possiamo identificare così:
iptables ... -p icmp --icmp-type 3/3 -j LOG --log-prefix "UDP REFUSED"
In questa riga si indica il filtro sui pacchetti appartenenti a icmp (-p icmp), e di questi pacchetti si filtrano quelli il cui tipo è 3/3, che vuol dire port unavailable. Per le associazioni tra tipo e significato, i files sul server del professore in laboratorio saranno d'aiuto.
Ad ogni modo, il comando
iptables -p icmp -h
stamperà una bella lista di tutti i tipi di pacchetti icmp disponibili.
REJECT
L'azione di default che dobbiamo settare di solito è DROP. DROP fa morire silenziosamente il pacchetto, e chi ci ha inviato la richiesta non viene a sapere nulla. Per essere più informativi è possibile anche usare l'azione REJECT, che si preoccupa di inviare un pacchetto icmp, ed eventualmente specificare quale.
Se usiamo REJECT dobbiamo però anche ricordarci di permettere ai pacchetti icmp di uscire dal sistema, altrimenti non saranno mai consegnati.
Ecco un esempio
iptables -A OUTPUT -p icmp -j ACCEPT
iptables -A INPUT -i eth0 --dport 80 -j REJECT --reject-with icmp-host-prohibited
La scelta dei possibili icmp da inviare ci viene data dal man di iptables:
- icmp-net-unreachable
- icmp-host-unreachable
- icmp-port-unreachable
- icmp-proto-unreachable
- icmp-net-prohibited
- icmp-host-prohibited or
- icmp-admin-prohibited (solo se è attivata una certa opzione nel kernel)
Il messaggio di default, se non si specifica il --reject-with, è icmp-port-unreacheable.
Torna alla pagina di SNR