Packet Filtering ovvero…Firewall !

Scrivo questo breve articoletto tecnico perchè ho visto che il mondo dei Firewall è spesso invaso di leggende metropolitane che poco hanno a che fare con la realtà dei fatti. Premesso che cercherò di essere il più PRATICO possibile, è indispensabile mettersi di buona volontà a capire come funziona il protocollo IP, il TCP ed (almeno) l’UDP e l’ICMP.

Il sistema operativo GNU/Linux include, tra i vari pacchetti essenziali, il fantastico IPTABLES (nelle distro vecchie era IPCHAINS). Generalmente si trova in /sbin/iptables e, nel caso di dubbi, potete sempre contare su man iptables e su http://www.netfilter.org/.

Detto questo, due paroline sulle reti IP.

Come sapete, Internet è una rete che comunica attraverso il protocollo IP. Incapsulato ai frame IP troviamo il TCP (Transmission Control Protocol), l’UDP (User Datagram Protocol), l’ICMP (Internet Control Message Protocol) e l’IGMP (Internet Group Management Protocol) ed è su questi 4 protocolli che il nostro IPTABLES lavorerà.

Non scenderò nei particolari perchè sarebbe troppo lunga: dico solamente che il TCP è orientato alla connessione (affidabilità, controllo degli errori) mentre l’UDP no (io spedisco: se arriva bene, altrimenti pace). La gestione delle segnalazioni, ovviamente, è affidata al nostro stack TCP/IP ma noi, attraverso IPTABLES abbiamo modo di interagire e modificare alcuni comportamenti.

Andiamo subito alla pratica.

IPTABLES ha un funzionamento basato su liste (“catene”) le cui 3 fondamentali sono: INPUT, OUTPUT, FORWARD. C’è anche la catena nat che useremo per il Network Address Translation.

INPUT regola i pacchetti in ingresso, OUTPUT quelli in uscita, FORWARD quelli che devono essere rispediti. (http://www.netfilter.org/documentation/HOWTO/it/packet-filtering-HOWTO-6.html)

Vediamo ora, attraverso dei semplicissimi bash script, alcuni casi comuni.

Primi passi con il firewall

Iniziamo subito con esempio pratiche che potete copiare:

#!/bin/sh
IPTABLES=/sbin/iptables
# Abilito il forward dei pacchetti
echo 1 > /proc/sys/net/ipv4/ip_forward

# Svuoto tutte le liste delle code (-F = flush)
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F

# Definisco il comportamento di default delle code (DROP=nega ACCEPT=accetta)
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT

Attenzione: bloccando tutti i pacchetti in ingresso, impedisco anche alle risposte dei miei pacchetti in uscita di arrivare: ecco perchè dobbiamo dire al firewall che deve accettare i pacchetti relativi alle connessioni stabilite e richieste da me:

$IPTABLES -A INPUT -m state --state ESTABLISHED, RELATED -j ACCEPT

Questa riga sopra introduce ad un altro argomento: lo stato delle sessioni. In questo caso abilito il modulo “state” e gli ordino di controllare i pacchetti in ingresso (-A INPUT). Nel caso si tratti di risposte (–state ESTABLISHED; RELATED) lecite, falle passare (-j ACCEPT)

Ok, già con queste poche righe abbiamo creato un semplice firewall che ci protegge da qualsiasi tentativo di ingresso al nosto sistema. Questo comporta anche il blocco dei “ping” (ICPM echo-request) che, se vogliamo, possiamo abilitare con la riga:

$IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

Sulla coda di input (-A INPUT), per il protocollo ICMP (-p icmp) ed i pacchetto del tipo echo-request (–icmp-type echo-request), fai passare (-j ACCEPT).

Adesso immaginiamo di avere alcune cartelle condivise sulla nostra macchina. Il protocollo NetBIOS (SMB) lavora sulle porte TCP/UDP 137-138-139 (possiamo vedere tutte le porte dei well-known-services nel file /etc/services) ed è il protocollo che utilizza Windows per la condivisione. Ovviamente se non apriamo queste porte, nessuna macchina potrà mai accedere alle nostre cartelle condivise:

$IPTABLES -A INPUT -p tcp --dport 137 -j ACCEPT
$IPTABLES -A INPUT -p udp --dport 137 -j ACCEPT
$IPTABLES -A INPUT -p tcp --dport 138 -j ACCEPT
$IPTABLES -A INPUT -p udp --dport 138 -j ACCEPT
$IPTABLES -A INPUT -p tcp --dport 139 -j ACCEPT
$IPTABLES -A INPUT -p udp --dport 139 -j ACCEPT

Qualchuno già esperto dirrà che si poteva fare con meno righe: è vero, ma siccome questo è un  tutorial le cose si devono fare in maniera semplice. Praticamente, sempre nella catena di input (-A INPUT), per il protocollo TCP ed UDP (-p tcp e -p udp), nei pacchetti destinati alle porte (–dport 137,138,139) indicate, fai passare (-j ACCEPT).

Il sistema rapido era usare il modulo multiport:

$IPTABLES -A INPUT -p tcp -m multiport --dports 137,138,139 -j ACCEPT
$IPTABLES -A INPUT -p udp -m multiport --dports 137,138,139 -j ACCEPT

Lo stesso sistema si applica per tutti gli altri servizi che abbiamo la necessità di abilitare sulla nostra macchina. Adesso passiamo ad un argomento che sarà molto utile a tutti quelli che devono condividere una connessione ad Internet, ovvero il cosiddetto “NAT” (http://www.netfilter.org/documentation/HOWTO/it/NAT-HOWTO.html)

Esistono due tipi principali di NAT: il Source NAT (SNAT) ed il Destination NAT (DNAT) che si applicano ad ambiti totalmente diversi. Un misto tra questi due NAT è il Masquerading (MASQ)  che utilizzeremo per condividere la nostra connessione alla rete.

Per il nostro esempio immaginiamo che il nostro PC si connette alla rete attraverso un modem (interfaccia ppp0) e la nostra intranet casalinga è sulla scheda di rete. Dobbiamo dire al nostro firewall che tutte le connessioni provenienti da ethX e dirette ad internet devono essere veicolate attraverso l’interfaccia ppp0. Ma, ovviamente, l’interfaccia ppp0 ha un IP pubblico mentre i nostri PC casalinghi hanno IP privati (10.0.0.0/8 192.168.0.0/16 172.16.0.0/16). Ecco a cosa serve il Masquerading: tutte le connessioni originate da IP private vengono “mascherate” e veicolate al destinatario (remoto) con l’IP pubblico della connessione ad internet. Ovviamente, anche se può sembrare banale, il sistema deve anche preoccuparsi del discorso inverso: tutte le risposte in arrivo dal sistema remoto devono essere “smascherate” ed inviate al PC interno giusto.

Configuriamo allora il nostro firewall per il MASQ:

$IPTABLES -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

Semplice, vero ? Questa riga agisce sulla tabella del NAT (-t nat), coda del POSTROUTING (-A POSTROUTING) su tutti i pacchetti in uscita dalla ppp0 (-o ppp0), mascherandoli (-j MASQUERADE). Ovviamente il nostro PC saprà che un certo pacchetto è diretto ad Internet e non alla intranet attraverso le tabelle di routing (comando route) e l’ARP.

ATTENZIONE: le regole del firewall vengono resettate ad ogni reboot. Se volete fare in modo che il firewall si configuri in automatico, scrivete le vostre regole (dopo averle testate !) su un file tipo rc.firewall e configurate gli script di inizializzazione del sistema. Vi dico questo perchè capita che, soprattutto lavorando su macchine remote, a causa di un errore si venga *letteralmente* tagliati fuori dal sistema: fate prima gli esperimenti SENZA salvare. Se funziona tutto e SOLO DOPO AVER VERIFICATO scrivete il vostro bel file da eseguire al boot !

A questo punto dirrei che di ciccia al fuoco ce n’è abbastanza per iniziare…buon divertimento !!!! Magari i più esperti storceranno il naso su alcune esemplificazioni di questo tutorial…beh, ragazzi, ogni contributo è ben accetto.

Strumenti indispensabili

Per poter giocare con il firewall è necessario avere degli strumenti di diagnosi e controllo. Vi segnalo i più comuni:

tcpdump (sniffer di rete)

nmap (scanner di rete molto potente e versatile…il migliore in assoluto !)

wireshark (un vero e proprio protocol analyzer con interfaccia grafica)

iptraf (monitor di rete con interfaccia NCurses)

Per finire, la documentazione completa, esauriente ed in italiano di IPTABLES la trovate quà: http://www.netfilter.org/documentation/