[Precedente: Tabelle] [Indice] [Successivo: Network Address Translation]
Le regole di filtraggio specificano il criterio da utilizzare per analizzare un pacchetto deve essere confrontato e l'azione da intraprendere, blocco o passaggio, quando vi è una corrispondenza. Le regole di filtraggio sono valutate in ordine sequenziale, dalla prima alll'ultima. A meno che non si abbia una corrispondenza con una regola contenente la keyword quick, il pacchetto sarà controllato con tutte le regole di filtraggio prima di intraprendere l'azione finale. L'ultima regola di confronto è la "vincente" e decide quale azione eseguire sul pacchetto. Esiste una regola implicita del pass all all'inizio delle regole di configurazione, questo significa che se non vi dovesse essere alcuna corrispondenza con le regole del filtro, il pacchetto sarà fatto passare.
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]
Per creare un firewall con una policy default deny le prime due regole dovrebbero essere:
block in all
block out all
Queste bloccano tutto il traffico su tutte le interfaccie in ogni direzione da ovunque a ovunque.
Qualche esempio:
# Passaggio del traffico in ingresso alla dc0 dalla rete locale 192.168.0.0/24,
# alla macchina OpenBSD con indirizzo IP 192.168.0.1. Inoltre consentire il traffico
# di ritorno in uscita sulla dc0.
pass in on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24
# Consentire il passaggio del traffico TCP in ingresso all'interfaccia fxp0 al
# web server in esecuzione sulla macchina OpenBSD. Il nome dell'interfaccia, fxp0,
# è usata come indirizzo di destinazione, così i pacchetti soddisferanno solo questa
# regola per essere destinati alla macchina OpenBSD pass in on fxp0 proto tcp from any
# to fxp0 port www
Sbagliato:
block in on fxp0 proto tcp from any to any port ssh
pass in all
In questo caso la regola di blocco viene considerata ma non avrà mai alcun effetto perchè è seguita da una linea che consente il passaggio di tutto il traffico.
Meglio:
block in quick on fxp0 proto tcp from any to any port ssh
pass in all
Queste regole vengono valutate un pò differentemente. Se la regola di blocco ha una corrispondenza, a causa dell'opzione quick, il pacchetto sarà bloccato e le regole successive ignorate.
Keeping state ha molti vantaggi tra i quali regole di configurazione più semplici e migliori performance di packet filtering. PF è in grado di effettuare un confronto con pacchetti che si muovono in entrambe le direzioni rispetto ai dati conservati nella tabella di stato, questo significa che le regole di filtaggio per i pacchetti in risposta su una connessione tracciata non devono essere scritte. E dato che i pacchetti che appartengono a una stateful connection non devono passare attraverso la valutazione delle regole di configurazione, il tempo impiegato da PF per processare questi pacchetti è notevolmente inferiore.
Quando una regola permette di creare uno stato, il primo pacchetto che soddisfa la regola crea uno "stato" tra client e server. Ora, non solo i pacchetti che vanno dal client al server soddisfano l'opzione keep state e attraversano il firewall senza ulteriori controlli ma così fanno anche i pacchetti di risposta tra server e client.
A partire da OpenBSD 4.1, tutte le regole di filtraggio creano automaticamente uno stato nella tabella quando vi è una corrispondenza con una reagola. Nelle precedenti versioni occorreva specificare l'opzione keep state.
Esempio che utilizza OpenBSD 4.1 e successive versioni:
pass out on fxp0 proto tcp from any to any
Esempio che utilizza OpenBSD 4.0 e versioni precedenti:
pass out on fxp0 proto tcp from any to any keep state
Questo consente a tutto il traffico TCP in uscita dall'interfaccia fxp0 e al corrispondente traffico di risposta di oltrepassare le regole del firewall. L'uso del keep state migliora in modo significativo le performance del firewall e i confronti con la tabella di stato sono incredibilmente più veloci rispetto al passaggio attraverso tutte le regole del firewall.
L'opzione modulate state funziona come il keep state ma si applica solo ai pacchetti TCP. Con l'opzione modulate state il numero di sequenza iniziale (Initial Sequence Number - ISN) delle connessioni in uscita è random. Questo è utile per proteggere le connessioni iniziali con alcuni sistemi operativi che hanno un prevedibile ISN. A partire da OpenBSD 3.5, l'opzione modulate state può essere usata in regole che utilizzano altri protocolli oltre il TCP.
Keep state sul traffico in uscita TCP, UDP, ICMP e modulate su TCP ISN:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state
Un altro vantaggio del keeping state è che il corrispondente traffico ICMP oltrepassa il firewall. Per esempio se in una connessione TCP tracciata arriva un messaggio ICMP source-quench riferito a questa connessione, verrà verificata la corrispondenza con la tabella di stato e il messaggio ICMP oltrepasserà le regole del firewall.
Il controllo dei dati della tabella di stato è ottenuta globalmente dalle opzioni runtime state-policy e sulla base di ogni regola dalle opzioni keyword if-bound, group-bound, e floating state. Queste keyword hanno lo stesso significato anche se usate con l'opzione state-policy. Esempio:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state (if-bound)
Questa regola imporrebbe che affinchè i pacchetti abbiano una corrispondenza con la tabella di stato devono transitare attraverso l'interfaccia fxp0.
Da notare che le regole nat, binat, e rdr implicitamente creano stati che restano tali fin quando la connessione attraversa le regole di configurazione.
Le opzioni sono specificate all'interno delle parentesi e immediatamente dopo una delle keyword di stato (keep state, modulate state, o synproxy state). Opzioni multiple sono separate da virgole. In OpenBSD 4.1 e versioni successive l'opzione keep state diviene implicita in tutte le regole. Comunque, quando si specificano le opzioni una delle keyword di stato deve essere specificata prima delle opzioni.
Un esempio di regola:
pass in on $ext_if proto tcp to $web_server \
port www keep state \
(max 200, source-track rule, max-src-nodes 100, max-src-states 3)
La regola precedente si comporta così:
Un set separato di restrizioni può essere usato su connessioni TCP che hanno completato l'handshake a 3 vie.
Entrambe queste opzioni automaticamente invocano l'opzione source-track e sono incompatibili con il source-track global.
Dato che questi limiti sono utilizzati solo su connessioni TCP che hanno completato l'handshake 3-way, possono essere intraprese azioni più tenaci per tutti gli indirizzi IP con comportamenti scorretti.
Un esempio:
table <abusive_hosts> persist
block in quick from <abusive_hosts>
pass in on $ext_if proto tcp to $web_server \
port www flags S/SA keep state \
(max-src-conn 100, max-src-conn-rate 15/5, overload <abusive_hosts> flush)
This does the following:
Per fare in modo che PF controlli i flag TCP in una regola, deve essere usata la keyword flags con la seguente sintassi:
flags check/mask
flags any
La mask dice a PF che ispezioni solo quei flag specifici mentre check specifica quale di quei flag devono essere "on" nell'header affinchè si abbia una corrispondenza. L'utilizzo della keyword any permette di settare nell'header ogni combinazione di flag.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA
La regola precedente consente il passaggio di traffico TCP con il flag SYN settato analizzando i flag SYN e ACK. Un pacchetto con flag SYN e ECE settati soddisferebbe la regola precedente mentre un pacchetto con SYN e ACK o solo ACK no.
In OpenBSD 4.1 e versioni successive, i flag di default applicati alle regole TCP sono flags S/SA. Insieme al keep state di default in OpenBSD 4.1 e versioni successive queste due regole sono equivalenti:
pass out on fxp0 proto tcp all flags S/SA keep state
pass out on fxp0 proto tcp all
Ogni regola avrà corrispondenza con il flag SYN settato e il flag ACK non settato ed ognuna creerà uno stato. I flag di default possono essere sostituiti usando l'opzione flags come visto precedentemente.
In OpenBSD 4.0 e versioni precedenti non vi erano flag di default applicati a nessuna regola. Ogni regola doveva specificare quale flag controllare e specificare l'opzione keep state.
pass out on fxp0 proto tcp all flags S/SA keep state
Si dovrebbe fare attenzione all'uso dei flag, capire quello che si sta facendo e il perchè, fare attenzione ai consigli dati dalle persone perchè la maggior parte sono sbagliati. Alcune persone suggeriscono di creare uno stato solo nel caso in cui il solo flag SYN è settato. Una regola di questo tipo appare così:
. . . flags S/FSRPAUEW bad idea!!
La teoria è di creare stati solo all'inizio di una sessione TCP e la sessione dovrebbe iniziare solo con il flag SYN. Il problema è che alcuni siti stanno iniziando a usare il flag ECN, e con il flag ECN settato ogni tentavivo di connettersi a un host con una regola di firewall come quella precedente sarebbe vano. Una regola migliore sarebbe di non specificare alcun flag e lasciare a PF l'utilizzo dei flag di default. Se si dovesse decidere di utilizzare i flag, questa combinazione dovrebbe essere la più appropriata:
. . . flags S/SAFR
Pur essendo pratico e sicuro non è necessario controllare i flag SYN e RST se il traffico è anche sottoposto allo scrub. Il processo di scrubbing porterà PF a rifiutare ogni pacchetto in arrivo con combinazioni illegali di flag TCP (come SYN e RST) e a normalizzare potenziali combinazioni ambigue (come SYN and FIN).
Di solito quando un client inizia una connessione TCP a un server, PF farà passare i pacchetti dell' handshake così come sono tra i due host. PF è comunque in grado di effettuare il proxy dell'handshake. Con il proxy dell'handshake, PF completa l'handshake con il client, inizia un handshake con il server, e quindi passa i pacchetti tra i due. Il beneficio di questo processo è che nessun pacchetto è inviato al server prima che il client completi l'handshake. Questo elimina la minaccia al server di flood TCP SYN da client scorretti che non desiderano completare l'handshake.
Il TCP SYN proxy viene abilitato usando la keyword synproxy state nelle regole di filtraggio. Esempio:
pass in on $ext_if proto tcp from any to $web_server port www \
flags S/SA synproxy state
Qui la connessione al server web sarà soggetta al TCP proxy di PF.
Per il modo con cui il synproxy state funziona, include anche le funzionalità del keep state e modulate state.
Il SYN proxy non funzionerà se PF è in esecuzione su un bridge(4).
PF offre alcune protezioni contro la contraffazione dell'indirizzo IP attraverso la keyword antispoof:
antispoof [log] [quick] for interface [af]
Esempio:
antispoof for fxp0 inet
Quando vengono caricate le regole di configurazione, ogni corrispondenza con la keyword antispoof viene espansa in due regole di filtraggio. Assumendo che l'interfaccia fxp0 abbia indirizzo IP 10.0.0.1 e una subnet mask di 255.255.255.0 (cioè /24), la regola antispoof si espenderebbe in:
block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any
Queste regole fanno due cose:
NOTA: Le regole di filtraggio che l'antispoof espande bloccheranno anche i pacchetti inviati sull'interfaccia di loopback agli indirizzi locali. E' buona regola non filtrare mai l'interfaccia di loopback e ciò diventa necessario nelle regole anti contraffazione:
set skip on lo0
antispoof for fxp0 inet
L'uso di antispoof dovrebbe essere ristretto alle interfaccie alle quali è assegnato un indirizzo IP. Usare antispoof su un'interfaccia senza un indirizzo IP comporterà avere delle regole del tipo:
block drop in on ! fxp0 inet all
block drop in inet all
Con queste regole c'è il rischio di bloccare tutto il traffico in arrivo su tutte le interfaccie.
A partire da OpenBSD 4.0, PF offre l'Unicast Reverse PAth Forwarding (uRPF). Quando un pacchetto viene controllato da uRPF, l'indirizzo sorgente viene agganciato alla tabella di routing. Se l'interfaccia esterna presente nella tabella di routing è la stessa interfaccia utilizzata come indirizzo sorgente dal pacchetto, il controllo uRPF ha esito positivo. Se non c'è corrispondenza tra gli indirizzi è possibile che l'indirizzo sorgente si contraffatto.
Il controllo uRPF sul pacchetto può essere ottenuto usando la keyword urpf-failed nelle regole di filtraggio:
block in quick from urpf-failed label uRPF
Da notare che il controllo uRPF ha senso in un sistema simmetrico di routing.
uRPF fornisce le stesse funzionalità delle regole antispoof.
Il riconoscimento passivo del sistema operativo (Passive OS Fingerprinting - OSFP) è un metodo utilizzato per riconoscere il sistema operativo di un host remoto in base a determinate caratteristiche dei pacchetti TCP SYN dell'host. Queste informazioni possono essere usate come criterio di confronto nelle regole di filtraggio.
PF determina il sistema operativo remoto comparando le caratteristiche TCP SYN del pacchetto con i dati del file fingerprints file, che per default è /etc/pf.os. Una volta che PF è abilitato, la lista corrente di fingerprint può essere vista con il seguente comando:
# pfctl -s osfp
Con una regola di filtraggio, un fingerprint può essere specificato a livello di classe OS, versione o patch. Ognuno di questi dati è visibile nell'output del comando precedente pfctl. Per specificare un fingerprint in una regola si usa la keyword os:
pass in on $ext_if from any os OpenBSD keep state
block in on $ext_if from any os "Windows 2000"
block in on $ext_if from any os "Linux 2.4 ts"
block in on $ext_if from any os unknown
Tutti i pacchetti con fingerprint OS non noto appartengono alla classe speciale di sistema operativo unknown.
PRENDERE NOTA di ciò che segue:
pass in quick on fxp0 all allow-opts
ext_if = "fxp0"
int_if = "dc0"
lan_net = "192.168.0.0/24"
# tabella contenente tutti gli indirizzi IP assegnati al firewall
table <firewall> const { self }
# non filtrare sull'interfaccia di loopback
set skip on lo0
# funzione di scrub per i pacchetti in arrivo
scrub in all
# setup a default deny policy
block all
# configura una policy deny di default
block in quick from urpf-failed
# consente le connessioni ssh dal computer affidabile 192.168.0.15
# della network locale;
# usa "block return" così che un TCP RST è inviato a chiudere
# connessioni bloccate; usa "quick" per evitare che questa regola sia
# esclusa da eventuali regole "pass" successive
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
to $int_if port ssh
# consente il traffico nella network locale
# queste regole creano stati per la presenza dell'opzione "keep state"
pass in on $int_if from $lan_net to any
pass out on $int_if from any to $lan_net
# passaggio di tcp, udp, e icmp verso Internet sull'interfaccia esterna
# keep state per l'udp e icmp; modulate state su tcp.
pass out on $ext_if proto { tcp udp icmp } all modulate state
# consente le connessioni ssh sull'interfaccia esterna se i pacchetti
# NON sono destinati al firewall (sono destinati ad host sulla rete
# locale); log del pacchetto iniziale per un eventuale riconoscimento
# di tentativi di connessioni; uso di tcp syn proxy per ottenere il
# proxy della connessione. Il flag di default "S/SA" sarà applicato
# automaticamente.
pass in log on $ext_if proto tcp from any to ! <firewall> \
port ssh synproxy state
|
[Precedente: Tabelle] [Indice] [Successivo: Network Address Translation]