"Se ci sono due o più modi di fare una cosa,
e uno di questi modi può condurre a una catastrofe,
allora qualcuno la farà in quel modo.

(Edward Murphy)

Come realizzare un Firewall su Debian e Shorewall con LAN e DMZ

Sab, 01/02/2014 - 14:28 -- arturu

Oggi parliamo di un argomento che sicuramente ogni amministratore di rete avrà affrontato almeno una volta nella vita: il firewall. L'obiettivo di questo articolo è illustrare come realizzare un firewall che protegga due reti: una LAN ed una DMZ. La realizzazione non è difficile e non richiede neanche tanto tempo, per l'obiettivo che ci siamo preposti una delle tante soluzioni è Shorewall su Debian. In questo articolo faremo una brevissima introduzione di come funziona il firewalling su linux, poi passeremo alla realizzazione del firewall e alla fine faremo alcune considerazioni finali.

Firewall su Linux - Introduzione rapidissima

Il sistema di firewalling su Linux è basato su iptables e netfilter (iproute sui sistemi RedHat, pf su BSD Like). Netfilter è un componente del kernel che permette di intercettare e manipolare i pacchetti in transito sul sistema. iptables è un programma che permette la gestione di netfilter attraverso l'inserimento di regole, iptables sostituisce i vecchi ipfwadm e di ipchains. Per fortuna con la soluzione che abbiamo scelto non dobbiamo scrivere regole, ma giusto per conoscenza facciamo un piccolo esempio di come funziona iptables. Per esempio, vogliamo far in modo che sull'indirizzo 127.0.0.1 non sia possibile fare il ping.

Prima

# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms

Settiamo la regola

# iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP

Risultato

# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

Le regole iptables vengono concatenate l'una dopo l'altra dentro dei "contenitori" detti catene ed essi sono: INPUT, FORWARD e OUTPUT. Le catene come impostazione di default sono impostate su ACCEPT. Nel nostro esempio, la regola che abbiamo appena scritto appende (-A) alla catena 'INPUT', una regola che indichi che i pacchetti provenienti dall'indirizzo 127.0.0.1 (-s 127.0.0.1) con protocollo ICMP (-p icmp) devono essere ignorati (-j DROP).
Per ora, può bastare. Questo è un sunto del riassunto, detto in maniera rapida, per quello che dobbiamo fare ci può bastare. Invece, chi volesse approfondire può leggere la documentazione di netfilter su www.netfilter.org.

I tool per iptables/netfilter su debian

Le operazioni più comuni con iptables sono la gestione delle catene creando nuove regole (-N), cancellare una catena vuota (-X), cambiare le policy di una catena esistente (-P), elencare le regole di una catena (-L), svuotare una catena (-F), azzerare i contatori (-Z), appendere una nuova regola ad una catena (-A), e tante altre operazioni. Gestire un firewall in questo modo richiede un lavoro continuo e a tempo inderminato, per fortuna estistono numerosi script e tools che inseriscono e "modificano" le regole al posto nostro. Possiamo fare una metafora, se assumiamo che le regole iptables sono simile all'assembly, invece il tool permette di utilizzare funzioni simile C. Di seguito i tools disponibili su Debian

Package and Upstream URL

Interface

Programming Language

Size of Source (as of 2005-10)

Releases (as of 2005-10)

arno-iptables-firewall

edit (debconf)

sh

60K

< 2003-08 - 2005-09

ferm (wiki page)

edit

perl

80K

< 2001-04 - 2005-06

fiaif

edit

bash

320K

< 2003-01 - 2004-02

filtergen

edit

C

150K

< 2002-10 - 2004-08

fireflier

gui

C

230K

2002-02 - 2005-09

firehol

edit

bash

210K

< 2003-05 - 2005-01

firestarter

gui (gnome)

C

1170K

< 2003-01 - 2005-01

fwbuilder

gui (kde)

C++

1190K

< 2003-12 - 2005-09

guarddog

gui (kde)

C++

960K

2000-06 - 2005-08

guidedog

gui (kde)

C++

590K

2001-11 - 2003-11

hlfl

edit

C

100K

< 2000-07 - 2003-10

ipkungfu

edit

sh

40K

2002-09 - 2003-10

kmyfirewall

gui (kde)

C++

1060K

2002-08 - 2005-03

knetfilter

gui (kde)

C++

960K

< 2001-01 - 2005-04

mason

shell (autolearning)

bash

500K

< 1999-03 - 2002-05

netscript-2.4

edit, iptables

sh

70K

< 2000-11 - 2004-10

shorewall

edit, webmin

sh

130K

< 2001-12 - 2005-09

uif

edit (debconf)

perl

34K

2002-02 - 2005-04

uruk

edit

sh

80K

2003-03 - 2005-07

Vuurmuur

curses

C

1877K

2004-07 - 2005-11

ufw

edit

python

247K

2009-5 - (NEW)

Tra tutti questi tools, il più usato dalla comunità Debian è Shoreline Firewall (detto Shorewall) ed è il tool che useremo per realizzare il nostro firewall.

Scenario

Abbiamo il seguente scenario, una linea ADSL, una LAN interna e una DMZ con servizi esposti sulla rete. Dall'esterno verso la LAN non deve passare alcun pacchetto, dall'esterno verso la DMZ passano i pacchetti solo per le porte che noi lasciamo libere, dalla LAN verso la DMZ e dalla LAN verso internet non esiste alcun filtro, infine, dalla DMZ verso la LAN l'accesso è impedito.

Impostiamo la classe del router su 100, la DMZ sulla classe 2 e la LAN sulla 1.

Installare e configurare Shorewall

Naturalmente dobbiamo aver una versione di Debian installata, dobbiamo avere 3 schede di rete ed impostare eth0 come scheda predefinita, un router ADSL collegato ad eth0, uno switch collegato a eth1 e un'altro switch collegato a eth2. Si potrebbe usare una sola scheda impostando più IP su una scheda, e un solo switch utilizzando in modo opportuno la maschera di rete, ma è meglio non percorrere questa soluzione se non vogliamo uscire pazzi con la configurazione ed avere problemi di sicurezza, anche se si sta usando uno switch moderno che invia i pacchetti in base all'accoppiata IP/MAC address.

Successivamente installiamo shorewall con:

# apt-get install shorewall
# apt-get install shorewall-doc

Successivamente copiamo dalla documentazione l'esempio a tre schede di rete (facile :D ) :

# cp -R /usr/share/doc/shorewall/examples/three-interfaces/* /etc/shorewall/

Logicamente dobbiamo configurare eth0 con un indirizzo statico, e non dhcp, in quanto dobbiamo reindirizzare tutto il traffico proveniente dal router verso eth0. Il file di configurazione come al solito si trova a "/etc/network/interfaces", la configurazione sarà simile a:

iface eth0 inet static
        address 192.168.100.2
        netmask 255.255.255.0
        gateway 192.168.100.254

# se vogliamo possiamo impostare un indirizzo ipv6
iface eth0 inet6 static
        address fe80::192.168.100.2
        netmask 64
        gateway fe80::c0a8:64fe

# inoltre se per caso ci ritroviamo improvvisamete a corto di schede di rete
# possiamo impostare più indirizzi IP su una scheda (sconsigliatissimo)
iface eth0 inet static
        address 192.168.1.254
        netmask 255.255.255.0
        gateway 192.168.1.254

iface eth0 inet static
        address 192.168.2.254
        netmask 255.255.255.0
        gateway 192.168.2.254

e per impostare i nameserver modifichiamo "/etc/resolv.conf"

nameserver 208.67.222.222
nameserver 208.67.220.220

ordinaria amministrazione fino ad ora. Successivamente dobbiamo editare "/etc/default/shorewall" e impostare la prima linea in:

# prevent startup with default configuration
# set the below varible to 1 in order to allow shorewall to start
startup=1

e avviare il firewall con

/etc/init.d/shorewall start

Ora dobbiamo associare le nostre zone (vedi figura precedente) alle interfaccie di rete, lo facciamo editando "/etc/shorewall/interface", in realtà il file è già impostato preché abbiamo copiato i file di esempio:

#ZONE	INTERFACE	OPTIONS
net		eth0		tcpflags,nosmurfs,routefilter,logmartians,sourceroute=0
loc		eth1		tcpflags,nosmurfs,routefilter,logmartians
dmz		eth2		tcpflags,nosmurfs,routefilter,logmartians

Ogni volta che salviamo un file di configurazione di Shorewall accertiamoci che ci sia una riga vuota alla fine. Nel file di configurazione abbiamo impostato le interfaccie di rete alle seguenti zone: "net" la zona dell'interfaccia esposta; "loc" la zona della LAN privata; la "dmz" la zona con i server esposti. Per chi vuole approfondire questo aspetto più informazioni li può reperire su questa pagina. D'ora in poi, alcune volte chiamerò interfaccia/rete Red l'interfaccia/zona esposta su internet (net, eth0); interfaccia/zona Green la LAN (loc, eth1) ed Orange l'interfaccia/zona della zona demilitarizzata (dmz, eth2).

Il prossimo passo è la configurazione delle zone "/etc/shorewall/zones", anche questo file è già configurato

#############################################################
#ZONE   TYPE    OPTIONS     IN                      OUT
#                           OPTIONS                 OPTIONS
fw      firewall
net     ipv4
loc     ipv4
dmz     ipv4

La prima zona è obbligatoria "fw" e rappresenta il firewall, le altre zone vanno inserite nello stesso ordine del precedente file di configurazione specificado il tipo di zona. Questo aspetto si può approfondire consultando la questa pagina

Il prossimo passo sarà quello di impostare le "policy" di sicurezza per ogni zona, quindi per ogni zona che abbiamo dichiarato dobbiamo impostare una "policy" di sicurezza, lo facciamo editando il file "/etc/shorewall/policy":

#SOURCE   DEST   POLICY     LOG           BURST:LIMIT
#                           LEVEL
loc       net    ACCEPT     info
net       all    DROP       info
# THE FOLLOWING POLICY MUST BE LAST
all       all    REJECT     info

Le policy che abbiamo impostato permettono alla zona Green di poter accedere all'esterno (loc -> net), di ignorare tutto quello che proviene dall'esterno su tutte le zone ed infine di respingere tutto ciò che resta verso tutto. Per approfondire questo aspetto si può consultare questa pagina.

Arrivati a questo punto abbiamo dato un'impostazione grossolana al nostro firewall, ora possiamo andare a definire le regole con più precisione andando ad editare il file "/etc/shorewall/rules" subito dopo di "SECTION NEW":

#ACTION     SOURCE	DEST				PROTO	DEST PORT(S)
SECTION NEW

Web(DNAT)	net		dmz:192.168.2.2		-		80
Web(ACCEPT)	loc		dmz:192.168.2.2		-		80

abbiamo fatto un port forwarding (DNAT) in modo che per la porta 80 fosse raggiungibile sia dall'esterno e dalla rete Green. Per far funzionare questa opzione dobbiamo controllare che in "/etc/shorewall/shorewall.conf" l'opzione "IP_FORWARDING" sia impostata su "On". Per le porte più usate, shorewall mette a disposizione delle macro già pronte, esse sono disponibili in "/usr/share/shorewall" senza doverle specificare dentro rules.

Siamo quasi alla fine, arrivati a questo punto dobbiamo soltanto far "comunicare" le diverse interfaccie, questo lo facciamo con l'IP Masquerading, è una forma di NAT che ci permette di condividere la connessione di una rete con un'altra (o di una scheda di rete con un'altra), è semplice, ci basta editare il file "/etc/shorewall/masq" nel seguente modo:

#INTERFACE		SOURCE					ADDRESS 	PROTO	
eth0			192.168.100.0/24 \
				192.168.1.0/24 \
				192.168.2.0/24

a questo punto abbiamo finito.

Conclusioni

Come abbiamo visto, la configurazione di un firewall su linux non è complicata, basta editare un po' di file. Questo tipo di soluzione è buona per lo scenario che abbiamo proposto, se invece si sta pensando ad altri scenari, come un server di hosting, con molti servizi esposti, questa non è la soluzione da seguire. Per un server di hosting serve qualcosa di molto più complesso e reattivo, serve un firewall che in base agli eventi (login falliti, ddos, spamlist ecc) modifichi le regole in maniera dinamica, magari ne parlerò prossimamente.

Oltre a shorewall, per lo stesso scenario, esistono numerose soluzioni "chiavi in mano", che sinceramente sono molto più flessibili del firewall "fai da te". Le distribuzioni più usate sono IPCop e pfSense, ma esse lasciano meno spazio alla personalizzazione e alla fantasia.

Ciao :)