Firewall
In questo capitolo verrà spiegato come configurare PacketFilter
- Introduzione a PacketFilter
- Macro
- Opzioni
- Scrub
- Nat e riindirizzamento
- Regole
- Regole: piccolo ufficio
- Regole: casa senza blocchi
---------------------------------------
1) Introduzione a PacketFilter
PF salva le varie configurazioni nel file pf.conf che si trova in etc; questo file è suddiviso in 7 parti:
- Macro: Variabili definite dall'utente che possono essere costituite da indirizzi IP, nomi di interfacce, ecc.
- Tabelle: Una struttura usata per conservare liste di indirizzi IP.
- Opzioni: Varie opzioni per controllare come lavora PF.
- Scrub: Fase di riprocesso dei pacchetti per normalizzarli e deframmentarli.
- Queueing: Fornisce un controllo sulla banda passante e sulla priorità di traffico dei pacchetti.
- Translation: Controlla la Network Address Translation (NAT) e la packet redirection.
- Filter Rules: Permette il selettivo filtraggio o blocco dei pacchetti nel passaggio attraverso ogni interfaccia di rete.
Alcuni comandi che potrebbero servirci
- Abilita PacketFilter
- Disabilita PacketFilter
- Carica il file pf.conf
Codice:
# pfctl -f /etc/pf.conf
- Analizza il file, ma non lo carica
Codice:
# pfctl -nf /etc/pf.conf
- Carica solo le regole della NAT dal file
Codice:
# pfctl -Nf /etc/pf.conf
- Carica solo le regole di filtraggio dal file
Codice:
# pfctl -Rf /etc/pf.conf
- Mostra le attuali regole di NAT
- Mostra le attuali regole di filtraggio
- Mostra la tabella di stato attuale
- Mostra i contatori e le statistiche di filtraggio
- Mostra tutto ciò che si può mostrare
---------------------------------------
2) Macro
Per iniziare dovremo impostare delle macro che ci permetteranno da un lato di scrivere le regole in modo più pratico e veloce e dall'altro di riuscire ad avere un'interpretazione delle regole scritte migliore alla lettura
- Andiamo ad editare il file di configurazione di PF; per fare questo dobbiamo digitare:
Codice:
# vi /etc/pf.conf
Una volta aperto il file eliminiamo tutte le varie righe già presenti (questo serve per evitare di fare confusione con gli esempi già scritti nel file in precedenza). - Questo è un esempio di macro molto semplice ma allo stesso tempo utile:
Codice:
ext_if = “rl0”
int_if = “rl1”
priv_nets = "{ 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4 }"
Il significato di queste scritte è semplicissimo. Spiegano a PF che quando quest'ultimo trova una regola con ad esempio: $ext_if deve creare delle regole in memoria, automaticamente, sostituendo la parola $ext_if con ciò che è scritto all'interno delle virgolette dopo l'uguale.
La macro priv_nets corrisponde a tutte le reti private non routabili e la useremo solo se collegati direttamente a internet come ad esempio Fastweb. Ovviamente le desinenze delle schede di rete cambiano a seconda del chip esattamente come i file hostname.* che abbiamo utilizzato per configurare gli ip in precedenza
---------------------------------------
3) Opzioni
Ora setteremo le opzioni; quindi scriviamo queste righe come segue:
Codice:
set block-policy drop
set loginterface $ext_if
set skip on lo
set optimization conservative
set state-policy if-bound
Le scritte sovrastanti servono a OpenBSD per diverse funzioni; La prima riga ordina che quando un pacchetto viene bloccato deve essere semplicemente scartato; la seconda riga abilita le statistiche sulla interfaccia esterna (la rl0); la terza istruisce PF a non filtrare le comunicazioni sulle interfacce di loopback (tali interfacce servono ad alcuni programmi per comunicare tra loro); la quarta riga può essere utile per connessioni che ogni tanto hanno delle latenze; la quinta riga ordina al firewall di lasciar filtrare solo i pacchetti che sono stati generati dall'interno dell'interfaccia.
---------------------------------------
4) Scrub
Lo scrub serve ad evitare che ci siano pacchetti malformati per il ricevente e a proteggere da eventuali attacchi i sistemi operativi che soffrono di vulnerabilità riguardo a flag malformati nel pacchetto tcp.
Codice:
scrub in all fragment reassemble
---------------------------------------
5) Nat e riindirizzamento
Settiamo il nat ed eventuali port forwarding per la nostra rete. Per fare questo, sempre all'interno del solito file pf.conf , dobbiamo aggiungere le seguenti righe:
Codice:
nat on $ext_if from ! ($ext_if) to any > ($ext_if)
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr on $int_if proto tcp from $int_if:network to any port ftp > 127.0.0.1 port 8021
La prima riga spiega a PF che deve “nattare” le connessioni che vanno dalla rl1 verso la rete esterna (rl0); la seconda, la terza e la quarta riga sono delle regole che permettono a PF di utilizzare ftp-proxy cioè un sistema che permette a i client di collegarsi ad eventuali ftp server su rete esterna anche in modalità attiva oltre che passiva. Da notare che se un ftp usa una porta diversa dalla 21 (che è la standard) andrà aggiunta a mano usando una dicitura tipo questa: port { 21, 7849, o_altra_porta }
---------------------------------------
6) Regole
Eccoci arrivati finalmente alla scrittura delle regole del firewall; per fare questo dobbiamo distinguere 2 tipi di utilizzo dello stesso.
Prima di tutto analizzerò una tipica configurazione da ufficio molto restrittiva; secondariamente analizzerò un'altra configurazione a uso casalingo cercando di evitare i classici problemi delle porte in uscita.
Prima di tutto ecco la sintassi semplificata delle regole:
action [direction] [log] [quick] [on interface] [af] [proto protocol] [from src_addr [port src_port]] [to dst_addr [port dst_port]] [flags tcp_flags] [state] - action = L'azione da intraprendere per i pacchetti per i quali c'è una corrispondenza sarà pass o block. L'azione di pass porta il pacchetto al kernel per processarlo ulteriormente mentre l'azione di block sarà dettata dalle opzioni stabilite nella block-policy. L'azione di default può essere esclusa specificando block drop o block return.
- direction = La direzione con la quale il pacchetto si muove attraverso l'interfaccia, in oppure out.
- [b]logSpecifica che il pacchetto dovrebbe essere loggato con pflogd. Se la regola crea uno stato solo il pacchetto che stabilisce lo stato viene loggato. Per effettuare il log di tutti i pacchetti usare log-all.
- quick = Se un pacchetto ha una corrispondenza con una regola che specifica quick, quella regola viene considerata l'ultima regola di confronto e viene intrapresa quella specifica azione.
- interface = Il nome o il gruppo di interfaccia di rete attraverso la quale il pacchetto si sta muovendo. Le interfacce possono essere aggiunte a gruppi arbitrari usando il comando: ifconfig. Alcuni gruppi vengono creati automaticamente anche dal kernel:
- Il gruppo egress, che ospita le interfaccie che contengono le rotte di default.
- Il gruppo di famiglia di interfaccia per le copie di interfaccie. Per esempio: ppp o carp.
Questo permetterebbe di avere regole con corrispondenza a ogni pacchetto che attraversa qualsiasi interfaccia ppp o carp. - af = La famiglia di indirizzi del pacchetto, inet per IPv4 oppure inet6 per IPv6. Di solito PF è in grado di determinare questo parametro basandosi sull'indirizzo sorgente e/o destinazione.
- protocol = Il protocollo del Layer 4 del pacchetto:
- tcp
- udp
- icmp
- icmp6
- Un nome di protocollo valido da /etc/protocols
- Un numero di protocollo compreso tra 0 e 255
- Un insieme di protocolli usando una lista.
- src_addr, dst_addr = L'indirizzo sorgente/destinazione dell'header IP. Gli indirizzi possono essere specificati come:
- In singolo indirizzo IPv4 e IPv6.
- Un blocco di CIDR network.
- Un nome di dominio assegnato che viene risolto via DNS quando vengono caricate le regole di configurazione. Tutti gli indirizzi IP corrispondenti saranno sostituiti nelle regole.
- Il nome di un'interfaccia di rete o di un gruppo di interfaccie. Ogni indirizzo IP assegnato all'interfaccia sarà sostituito nella regola.
- Il nome di un'interfaccia di rete seguita da /netmask (per esempio, /24). Ogni indirizzo IP di un'interfaccia è associata con la netmask per formare un blocco CIDR network sostituito nelle regole.
- Il nome di un'interfaccia di rete tra parentesi ( ). Questo suggerisce a PF di aggiornare le regole se dovessero cambiare gli indirizzi dell'interfaccia. E' utile per un'interfaccia che ottiene il suo indirizzo IP via DHCP o in dial-up così da evitare di ricaricare le regole di configurazione ogni volta che cambia l'indirizzo.
- Il nome di un'interfaccia di rete seguita da uno di questi parametri:
- :network - sostituisce il blocco di CIDR network (per esempio, 192.168.0.0/24)
- :broadcast - sostituisce l'indirizzo di broadcast (per esempio, 192.168.0.255)
eer - sostituisce l'indirizzo peer IP in un collegamento point-to-point Inoltre il parametro :0 può seguire sia il nome di un'interfaccia oppure ognuno dei parametri visti precedentemente e indica che PF non dovrebbe includere indirizzi IP alias nella sostituzione. Questi parametri possono anche essere usati quando l'interfaccia è contenuta tra parentesi. Esempio: fxp0:network:0
- Una tabella.
- La keyword urpf-failed può essere usata per un indirizzo sorgente ad indicare che dovrebbe essere eseguita attraverso il controllo uRPF.
- Ognuno dei parametri precedenti ma negati usando il parametro ! ("not").
- Un set di indirizzi usando una lista.
- La keyword any ad indicare tutti gli indirizzi
- La keyword all che indica from any to any cioè da ovunque a ovunque.
- src_port, dst_port = La porta sorgente/destinazione nell'header dell'Layer 4. Le porte possono essere specificate come:
- Un numero tra 1 e 65535
- Un nome di servizio valido da /etc/services
- Un set di porte usando una lista
- Un range:
- != (diverso)
- < (minore)
- > (maggiore)
- <= (minore o uguale)
- >= (maggiore o uguale)
- >< (range)
- <> (range inverso) Gli ultimi due operatori sono binari (prendono due argomenti) e non includono gli argomenti nel range.
- : (range inclusivo) Anche l'operatore di range inclusivo è un operatore binario e include gli argomenti nel range.
- tcp_flags = Specifica i flag che devono essere settati nel TCP header quando si usa un protocollo tcp. I flag sono definiti come flags check/mask. Per esempio:flags S/SA - questo istruisce PF a cercare solo pacchetti con flag S e A (SYN e ACK) e a considerare una corrispondenza solo quando il flag SYN è "on". In OpenBSD 4.1 e successivi, i flag di default S/SA sono applicati a tutte le regole di filtraggio.
- state = Specifica se informazioni di stato sono conservate per pacchetti che hanno corrispondenza con questa regola.
- keep state - funziona con TCP, UDP, e ICMP. In OpenBSD 4.1 e successivi, questa opzione è di default per tutte le regole di filtraggio.
- modulate state - funziona solo con TCP. PF genera un numero di sequenza iniziale (ISNs) non facilmente prevedibile per pacchetti che hanno una corrispondenza con questa regola.
- synproxy state - connessioni proxy TCP in ingresso per proteggere il server da flood TCP SYN contraffatti. Questa opzione include la funzionalità keep state e modulate state.
---------------------------------------
7) Regole: piccolo ufficio
Ecco come si presenteranno le regole più restrittive per il piccolo ufficio.
Codice:
block log all
block log inet6 all
La regola sovrastante blocca tutto il traffico per e da il firewall sia nel protocollo ipv4 che ipv6.
Codice:
antispoof log quick for { $int_if, $ext_if }
Con questa regola diciamo a PF di abilitare l'antispoof sulle interfacce scritte tra le graffe; l'antispoof non
è altro che un sistema per bloccare pacchetti mascherati che altrimenti passerebbero
Codice:
#block in quick on $ext_if from $priv_nets to any
#block out quick on $ext_if from any to $priv_nets
Queste regole spiegano a PF di bloccare direttamente i pacchetti che hanno ip sorgente e di destinazione
privata. Tali regole non vanno usate se la configurazione è come quella nello schema. Sostanzialmente
evita l'entrata e l'uscita di pacchetti non “routabili”. Come detto in precedenza queste regole vanno
inserite solo nel caso si fosse collegati a una rete diretta su internet (ad esempio Fastweb) togliendo il
carattere # a ogni inizio riga.
Codice:
pass out on $ext_if proto tcp from any to any modulate state flags S/SA
pass out on $ext_if proto udp from any to any keep state
pass out on $ext_if proto icmp from any to any keep state
Questa regola permette al firewall di comunicare verso l'esterno;
Codice:
anchor "ftp-proxy/*"
Questa regola permette di utilizzare ftp-proxy;
Codice:
pass in on $int_if proto tcp from any to any port { 80, 443 } modulate state flags S/SA
Questa serie di regole permette il traffico web;
Codice:
pass in on $int_if proto tcp from any to any port { 110, 25 } modulate state flags S/SA
Queste regole permettono di utilizzare i protocolli di posta pop3 e smtp;
Codice:
pass in on $int_if proto tcp from any to any port { 20, 21, 8021 } modulate state flags S/SA
Queste regole permettono l'utilizzo del ftp;
Codice:
pass in on $int_if proto tcp from any to any port 22 modulate state flags S/SA
Queste regola permettono l'utilizzo di ssh per settare il firewall da remoto nella rete locale;
Codice:
pass in on $int_if proto udp from any to any port 53 keep state
Queste regole permettono la risoluzione nomi (DNS);
Codice:
pass in on $int_if proto udp from any to any port 123 keep state
Queste regole servono per permettere la sincronizzazione dell'orario tramite internet;
Codice:
pass in on $int_if proto icmp from any to any keep state
Queste regole servono per poter utilizzare gli icmp ad esempio come ad esempio il ping;
Ecco il listato completo di ciò che troveremo scritto nel file pf.conf per il piccolo ufficio
Codice:
ext_if = "rl0"
int_if = "rl1"
priv_nets = "{ 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4 }"
set block-policy drop
set loginterface $ext_if
set skip on lo
set optimization conservative
set state-policy if-bound
scrub in all fragment reassemble
nat on $ext_if from ! ($ext_if) to any > ($ext_if)
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr on $int_if proto tcp from any to any port 21 > 127.0.0.1 port 8021
block log all
block log inet6 all
antispoof log quick for { $int_if, $ext_if }
#block in quick on $ext_if from $priv_nets to any
#block out quick on $ext_if from any to $priv_nets
pass out on $ext_if proto tcp from any to any modulate state flags S/SA
pass out on $ext_if proto udp from any to any keep state
pass out on $ext_if proto icmp from any to any keep state
anchor "ftp-proxy/*"
pass in on $int_if proto tcp from any to any port { 80, 443 } modulate state flags S/SA
pass in on $int_if proto tcp from any to any port { 20, 21, 8021 } modulate state flags S/SA
pass in on $int_if proto tcp from any to any port 22 modulate state flags S/SA
pass in on $int_if proto udp from any to any port 53 keep state
pass in on $int_if proto udp from any to any port 123 keep state
pass in on $int_if proto icmp from any to any keep state
---------------------------------------
8) Regole: casa senza blocchi
L'ultima serie di regole sono quelle relative a un utilizzo casalingo senza problemi di porte:
Codice:
block log all
block log inet6 all
La regola sovrastante blocca tutto il traffico per e da il firewall sia nel protocollo ipv4 che ipv6.
Codice:
antispoof log quick for { $int_if, $ext_if }
Con questa regola diciamo a PF di abilitare l'antispoof sulle interfacce scritte tra le graffe; l'antispoof non
è altro che un sistema per bloccare pacchetti mascherati che altrimenti passerebbero
Codice:
#block in quick on $ext_if from $priv_nets to any
#block out quick on $ext_if from any to $priv_nets
Queste regole spiegano a PF di bloccare direttamente i pacchetti che hanno ip sorgente e di destinazione
privata. Tali regole non vanno usate se la configurazione è come quella nello schema. Sostanzialmente
evita l'entrata e l'uscita di pacchetti non “routabili”. Come detto in precedenza queste regole vanno
inserite solo nel caso si fosse collegati a una rete diretta su internet (ad esempio Fastweb) togliendo il
carattere # a ogni inizio riga.
Codice:
pass out on $ext_if proto tcp from any to any modulate state flags S/SA
pass out on $ext_if proto udp from any to any keep state
pass out on $ext_if proto icmp from any to any keep state
Questa regola permette al firewall di comunicare verso l'esterno;
Codice:
anchor "ftp-proxy/*"
Questa regola permette di utilizzare ftp-proxy;
Codice:
pass in on $int_if proto udp from $int_if:network to any keep state
Questa regola permette a tutti i pc collegati all'interfaccia interna (appartenenti alla stessa rete) di comunicare col protocollo UDP verso l'esterno;
Codice:
pass in on $int_if proto tcp from $int_if:network to any modulate state flags S/SA
Questa regola permette a tutti i pc collegati all'interfaccia interna (appartenenti alla stessa rete) di comunicare col protocollo TCP verso l'esterno;
Codice:
pass in on $int_if proto icmp from $int_if:network to any keep state
Questa regola permette a tutti i pc collegati all'interfaccia interna (appartenenti alla stessa rete) di comunicare col protocollo ICMP verso l'esterno;
Ecco il listato completo di quello che dovrà essere scritto nel file pf.conf
Codice:
ext_if = "rl0"
int_if = "rl1"
priv_nets = "{ 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4 }"
set block-policy drop
set loginterface $ext_if
set skip on lo
set optimization conservative
set state-policy if-bound
scrub in all fragment reassemble
nat on $ext_if from ! ($ext_if) to any > ($ext_if)
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr on $int_if proto tcp from any to any port 21 > 127.0.0.1 port 8021
block log all
block log inet6 all
antispoof log quick for { $int_if, $ext_if }
#block in quick on $ext_if from $priv_nets to any
#block out quick on $ext_if from any to $priv_netqs
pass out on $ext_if proto tcp from any to any modulate state flags S/SA
pass out on $ext_if proto udp from any to any keep state
pass out on $ext_if proto icmp from any to any keep state
anchor "ftp-proxy/*"
pass in on $int_if proto udp from $int_if:network to any keep state
pass in on $int_if proto tcp from $int_if:network to any modulate state flags S/SA
pass in on $int_if proto icmp from $int_if:network to any keep state
AVVISO: LA SEGUENTE GUIDA È RILASCIATA SOTTO LICENZA CREATIVE COMMONS E SENZA ALCUNA GARANZIA! L'AUTORE NON SI ASSUME NESSUNA RESPONSABILITÀ PER L'USO PROPRIO O IMPROPRIO DI QUEST'ULTIMA