Esempio PF: Firewall per casa o per piccolo ufficio.

PF: Esempio: Firewall per Piccole situazioni.


Contenuti


Lo Scenario

In questo esempio, PF si comporta da firewall e NAT getaway per una rete di casa o di un piccolo ufficio. L'obbiettivo è quello di fornire un accesso internet alla rete, e permettere un limitato accesso al firewall da internet.

La rete

La rete è organizzata in questo modo:
    
  [ COMP1 ]    [ COMP3 ]
      |            |                               ADSL
   ---+------+-----+------- fxp0 [ BSD ] ep0 -------- ( Internet )
             |
         [ COMP2 ]

C'è un numero di computers nella rete interna; il diagramma ne mostra 3, ma il numero effettivo è irrilevante. Questi computers sono normali workstation usate per la navigazione, posta elettronica, chat, ecc, ad eccezione del comp3 su cui gira anche un piccolo web server. La rete interna usa la famiglia di indirizzi 192.168.0.0/255.255.255.0.

Il router BSD è un Pentium 100 con 2 schede di rete 3com 3c509B (ep0) ed una Intel EtherExpress Pro/100 (fxp0). Il router dispone di una connessione internet ADSL ed usa il NAT per condividere questa connessione con la rete interna. L'indirizzo IP dell'interfaccia esterna è assegnato dinamicamente dall Internet Service Provider.

Obbiettivo

Gli obbiettivi sono:

Preparazione

Questo documento assume che la macchina BSD sia stata configurata a dovere per comportarsi come un router, incluso IP networking setup, Internet connectivity, net.inet.ip.forwarding settato ad "1".

Il set di regole

Di seguito verrà elencato e commentato un set di regole atto a raggiungere gli obbiettivi prefissi.

Macro

Le seguenti macro vengono definite per semplificare la lettura del set di regole:
int_if = "fxp0"
ext_if = "ep0"

tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"

priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"

comp3 = "192.168.0.3"

Le prime due righe definiscono le interfacce di rete a cui verrà applicato il filtraggio. La terza e quarta riga definiscono i numeri di porta dei servizi reperibili da internet (SSH e ident/auth) ed i tipi di pacchetti ICMP a cui sarà permesso raggiungere la macchina firewall. La quinta riga definisce il looback e RFC 1918 blocco di indirizzi. In fine, l'ultima riga definisce l'indirizzo ip del COMP3.

Nota: Se la connessione ADSL richiede PPPoE, il filtraggio ed il NAT saranno sull'interfaccia tun0 e non sulla ep0.

Opzioni

Le seguenti due opzioni setteranno il responso al set di regole di block e setteranno "on" le statistiche per l'interfaccia esterna.
set block-policy return
set loginterface $ext_if

Scrub

Non c'è ragione di non usare lo "scrubbing" di tutto il traffico in arrivo:
scrub in all

Network Address Translation

Per l'attuazione del NAT su tutta la rete interna viene utilizzata la seguente regola di nat :
nat on $ext_if from $int_if:network to any -> ($ext_if)

Nel caso di assegnazione di indirizzo IP dinamico, si aggiungano le parentesi attorno al nome di interfaccia, così che PF noti i cambiamenti di indirizzo.

Redirezione

La prima regola di redirezione è necessaria per ftp-proxy(8) cosi che i client FTP della rete interna possano connettersi ai server FTP Internet.
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021

Si noti che questa regola vale per connessioni FTP sulla porta standard 21. Nel caso si utilizzino porte particolari la lista andrà aggiornata, per esempio: from any to any port { 21, 2121 }.

La seconda regola di ridirezionamento riguarda i tentativi di connessione da internet sul firewall alla porta TCP 80, le connessioni a questa porta sono un tentativo di accesso al web server interno. Questi tentativi di connessione andranno redirette a COMP3.

rdr on $ext_if proto tcp from any to any port 80 -> $comp3

Regole di filtraggio

Ora le regole di filtraggio. Per prima cosa default deny:
block all

A questo punto nulla passerà attraverso il firewall, nemmeno dalla rete interna. Le seguenti regole apriranno il firewall coma da obbiettivi preposti aprendo le necessarie interfacce virtuali.

Ogni sistema unix ha una interfaccia di "loopback". Un'interfaccia di rete virtuale usata dalle applicazioni per comunicare fra loro all'interno del sistema. Generalmente tutto il raffico dovrebbe passare dall'interfaccia di loopback. Sui sistemi BSD l'interfaccia di loopback è lo(4).

pass quick on lo0 all

L'address "spoofing" è l'utilizzo di un falso indirizzo IP nei pacchetti trasmessi, atto a falsificare il vero indirizzo o ad impersonare un altro nodo di rete. Un utente con indirizzi ip "spooffato" può lanciare un attacco di rete senza rivelare la vera fonte dell'attacco o accedere a servizi di rete riserveti a determinati indirizzi IP.

antispoof quick for $int_if inet

Successivamente all'indirizzo RFC 1918 verra bloccato l'accesso o l'uscita dall'interfaccia esterna. Questi indirizzi non dovrebbero mai apparire pubblici e filtrarli assicurerà che il router non lasci passare questi indirizzi fuori dalla rete interna e blocchi ogni pacchetto entrante con indirizzo sorgente in una di queste reti.

block drop in  quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets

Si noti che block drop è usato per dire a PF di non rispondere con un TCP RST or ICMP Unreachable packet. Since the RFC 1918 addresses don't exist on the Internet, any packets sent to those addresses will never make it there anyways. L'opzione quick è utilizzata per dire a PF di non valutare il resto del set di regole se una di quelle lette fino ad ora corrisponde; i pacchetti per e da $priv_nets verrano droppati immediatamente.

Ora apriamo le porte di quei servizi di rete che saranno accessibili da Internet:

pass in on $ext_if inet proto tcp from any to ($ext_if) \
   port $tcp_services flags S/SA keep state

Specificare le porte di rete nella macro $tcp_services rende semplice aprire servizi addizionali ad Internet semplicemente editando la macro e ricaricando il set di regole. Anche i servizi UDP possono essere aperti creando una macro $udp_servicese aggiungendo una regola di filtraggio, simile alla precedente,che specifichi proto udp.

Oltre ad avere una regola rdr che passi il il traffico del web server al COMP3, dobbiamo anche far passare questo traffico attraverso il firewall:

pass in on $ext_if proto tcp from any to $comp3 port 80 \
    flags S/SA synproxy state

Per aggiungere un po di sicurezza, faremo uso del TCP SYN Proxy a protezione web server.

Per poter utilizzare connessioni attive FTP dalla rete interna, va aggiunta la seguente regola, che passi le connessioni ftp-data provenienti dal Server FTP e dirette al client. Proxando con ftp-proxy le connessioni FTP, accetterà le connessioni ftp-data per poi passarle ai client della LAN.

pass in on $ext_if inet proto tcp from port 20 to ($ext_if) \
    user proxy flags S/SA keep state

Va ora fatto passare il traffico ICMP:

pass in inet proto icmp all icmp-type $icmp_types keep state

Similmente alla macro $tcp_services , la macro $icmp_types può facilmente essere editata per cambiare tipi di pacchetti ICMP che saranno abilitati a raggiungere il firewall.Si noti che la regola si applica a tutte le interfacce di rete.

Ora deve essere passato il traffico da e per la rete interna. Si assume che gli utenti della rete interna sappiano quello che fanno e non causino danni. Questo non corrisponde sempre a verità; un set di regole più restrittivo, in alcuni casi, potrebbe essere appropriato.

pass in on $int_if from $int_if:network to any keep state

Questa regola permetterà ad ogni macchina interna di spedire pacchetti attraverso il firewall; non permettendo al firewall di iniziare connessioni con le macchine interne. Questa è una buona idea? Questione di setup. Nel caso in cui il firewall sia anche un DHCP server, potrebbe aver bisogno di pingare un indirizzo per verificarne la disponibilità prima di assegnarlo.Permettere al firewall di connettersi alla rete interna consente a chi ha un accesso ssh al firewall da Internet,di accedere a macchine interne alla rete. Si tenga presente che non permettere al firewall di comunicare direttamente con la rete interna non è un così grande beneficio di sicurezza. Nel caso infatti di un accesso al firewall il set di regole potrebbe essere modificato in ogni caso. Aggiungendo la seguente regola, il firewall sarà in grado di iniziare connessioni alla retre interna:

pass out on $int_if from any to $int_if:network keep state

Si noti che elencando queste due linee, l'opzione keep state non è necessaria; tutti i pacchetti saranno abilitati a passare attraverso l'interfaccia interna perchè c'è una regola di passaggio in entrambe le direzioni. Comunque, se la linea pass out non è inclusa, la linea pass in deve includere keep state. C'è anche del beneficio nelle performance nel "keep state": Le tabelle di stato sono controllate prima di valutare le regole e se sussiste un stato il pacchetto passa attraverso il firewall senza valutare il set di regole. Questo offre benefici nelle performance in un firewall pesantemente caricato.

In fine, passiamo il traffico sull'interfaccia esterna:

pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state

Il traffico TCP, UDP, and ICMP ha il permesso di uscita verso Internet. Le informazioni di stato sono mantenute cosi che i pacchetti di ritorno possano passare attraverso il firewall.

Set di regole completo

# macros
int_if = "fxp0"
ext_if = "ep0"

tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"

priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"
	  
comp3 = "192.168.0.3"

# options
set block-policy return
set loginterface $ext_if

# scrub
scrub in all

# nat/rdr
nat on $ext_if from $int_if:network to any -> ($ext_if)
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 \
   port 8021
rdr on $ext_if proto tcp from any to any port 80 -> $comp3

# filter rules
block all

pass quick on lo0 all

antispoof quick for $int_if inet

block drop in  quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets

pass in on $ext_if inet proto tcp from any to ($ext_if) \
   port $tcp_services flags S/SA keep state

pass in on $ext_if proto tcp from any to $comp3 port 80 \
   flags S/SA synproxy state

pass in on $ext_if inet proto tcp from port 20 to ($ext_if) \
   user proxy flags S/SA keep state

pass in inet proto icmp all icmp-type $icmp_types keep state

pass in  on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state

pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state

Volendo tenere sotto controllo eventuali attacchi bruteforce sulle porte aperte limitandone gli accessi e soprattutto gli accessi contemporanei
PF mette a disposizione particolari regole ed entry tables. (valido solo per versioni FreeBSD 6 o superiori)

table <abusive_hosts> persist
block in quick from <abusive_hosts>

pass in on $ext_if proto tcp to ($ext_if) \
     port $tcp_services flags S/SA keep state \
     (max-src-conn 100, max-src-conn-rate 15/5, overload <abusive_hosts> flush)

Questo è cio che accade:


www.openbsd.org www.freebsd.org www.015-bsd.org
$OpenBSD: example1.html,v 1.18 2004/12/22 04:28:16 david Exp IT $ Copyright (c) 2003, 2004 Joel Knight
Italian translation by Matteo Baldi.