Premier Training & Business Partner Red Hat

Sicurezza Firewall: Progettazione di Iptables Seconda Parte

Michele Milaneschi
Ti piacerebbe diventare anche tu uno di noi e
pubblicare i tuoi articoli nel blog degli RHCE italiani?

Nell’articolo precedente abbiamo visto come con una politica di DROP in INPUT e la regola sugli stati delle connessioni ESTABLISHED e RELATED siano un buon punto di partenza per la configurazione di iptables. Successivamente abbiamo inserito la regola per garantire l’accesso SSH che eventualmente potrebbe essere una porta filtrata se decidiamo nella regola l’ip sorgente da cui poter accedere.   Cosa importante che non abbiamo detto, è che una volta che abbiamo messo la politica di DROP in INPUT dobbiamo garantire il traffico per l’interfaccia di loopback sia in ingresso che in uscita ( se la politica in uscita è su ACCEPT non ci vuole altrimenti lo dobbiamo inserire anche nella catena di OUTPUT ) per il corretto funzionamento di alcuni software che usano questa interfaccia per lo scambio di dati. Ciò lo facciamo tramite il seguente comando:

iptables -I INPUT 1 -i lo -j ACCEPT

Fatta questa breve introduzione parliamo della tabella nat ossia delle catene PREROUTING e POSTROUTING. Adiamo a inserire delle regole in queste tabelle quando vogliamo alterare l’ip sorgente o destinazione di un pacchetto. Vediamo meglio di cosa stiamo parlando: Il POSTROUTING lo usiamo ad esempio se vogliamo nascondere all’esterno l’esistenza di una rete LAN interna, facendo finta che il pacchetto che arriva a destinazione non venga visto come proveniente ad esempio da 192.168.XXX.XXX ma sia visto come un normale IP di classe A e questo lo facciamo mascherando l’IP sorgente con l’IP pubblico che ad esempio il nostro ISP ci fornisce. Applichiamo questa regola tramite il seguente comando:

iptables -t nat -A POSTROUTING -j MASQUERADE

Il PREROUTING invece lo usiamo quando ad esempio su una o più macchine che fanno parte della nostra rete interna vengono forniti dei servizi ( http,ftp,… ) e vogliamo che quando dall’esterno arriva una richiesta che risponde ai quesiti di un servizio, essa venga indirizzata verso quella determinata macchina interna, quindi verso quello specifico IP. Per capirsi è come quando si apre delle porte su un router: Si indica che per quelle determinate porte, quando arriva una richiesta, venga indirizzata a quel preciso computer con quello specifico ip di modo che si possa comunicare senza problemi. Vediamo la struttura di alcune regole:

iptables -t nat -A PREROUTING -p tcp –i ppp0 --dport 80 -j DNAT –-to-destination 192.168.0.2:443

Si fa uso dell’opzione –-to-destination per instradare le richieste che arrivano sulla interfaccia ppp0 della porta 80 verso il server 192.168.0.2 sulla porta 443 Abbiamo detto in precedenza che una macchina con il firewall potrebbe avere il ruolo anche di un router ossia dover smistare delle richieste da un interfaccia interna verso una esterna e in quel caso al posto degli indirizzi ip potrebbe essere richiesto l’uso delle interfacce nelle regole che si andranno a creare, ma cosa fondamentale in questi casi è abilitare l’ip forwarding.

echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf

Riavviamo la macchina e dando il comando:

sysctl -a | grep ip_forward

Troveremo il valore a 1 ipt12 Soffermiamoci meglio sulle catene PREROUTING E POSTROUTING e come entra in gioco la catena FORWARD. Facciamo un esempio: Abbiamo un server web sull’indirizzo ip 192.168.0.100 ( ma non sappiamo l’esistenza di questo indirizzo interno.... serve per aiutare a capire il concetto ) Per contattarlo dobbiamo passare obbligatoriamente da un altra macchina che fa da tramite che ha ip 192.168.0.34. Ammettiamo che 192.168.0.34 sia la macchina posta tra la rete interna ed internet. L’host da cui verrà fatta la richiesta del web server ha ip 192.168.0.2. Non possiamo fare questo esempio con degli ip pubblici a causa di alcuni problemi ma dovete vedere 192.168.0.2 e 192.168.0.34 come degli ip pubblici di classe A mentre 192.168.0.100 come la macchina che sta dietro a 192.168.0.34 ( che fa parte di una LAN INTERNA ) Come impostiamo questa cosa a livello teorico?? Noi Client ( 192.168.0.2 ) facciamo richiesta all’ip 192.168.0.34 sulla porta 80 di fornirci l’accesso al web server visto che non possiamo accederci direttamente. Quando a 192.168.0.34 arriva la richiesta sulla porta 80 sarà lui a instradare la nostra richiesta verso l’ip 192.168.0.100 sulla porta 80.

Attenzione alla parola instradare:

Non significa che la richiesta quando arriva all’ip 192.168.0.34 in qualche modo se ne esce e contatta l’ip 192.168.0.100 ma la richiesta deve passare attraverso l’ip 192.168.0.34 per arrivare al 192.168.0.100. Procediamo con la prima regola:

iptables -t nat -A PREROUTING -p tcp -–dport 80 -j DNAT –-to-destination 192.168.0.100:80

ipt13

A questo punto a 192.168.0.34 gli si dice di andare a contattare 192.168.0.100 ma la richiesta deve passare attraverso di lui quindi la catena FORWARD deve avere la politica di ACCEPT ( come nel nostro caso ) oppure creare la regola che le richieste sulla porta 80 devono semplicemente passare e basta ( sanno gia dove devono andare ) o piuttosto indirizzarle sulla interfaccia interna. E quindi sembrerebbe che la richiesta arrivi al 192.168.0.100 senza nessun problema E INVECE NO!!!!!!!!!!!! PERCHE????? Guardate i Log!!! ipt14 Sui log abbiamo come ip sorgente 192.168.0.2, è giusto??? NO Infatti la nostra richiesta non viene soddisfatta: ipt15   La richiesta gli deve arrivare da 192.168.0.34 perchè è la macchina che instrada le richieste alla rete locale interna che ha dietro di se.   Ed ecco che entra in gioco la catena POSTROUTING che anche se è su ACCEPT dobbiamo inserire una regola. Dobbiamo eseguire il MASQUERADE, cioè alterare l’ip sorgente perchè è da 192.168.0.34 che arriva la richiesta a 192.168.0.100. Il client da cui effettuiamo la richiesta non sa dell’esistenza di 192.168.0.100 ma conosce solamente 192.168.0.34 che rappresenta la macchina che si espone tra la rete interna ed esterna ed agendo come un router deve smistare le richieste alle altre macchine interne. Attualmente abbiamo indirizzi IP di classe uguale ( Classe C ) ma è come se 192.168.0.34 fosse un IP di classe A o meglio un ip pubblico, noi che siamo il client ( 192.168.0.2 ) siamo un host della rete a cui l’ip ci viene fornito dal un ISP ( telecom, teletu… ) e la macchina che eroga il servizio http sta dietro a 192.168.0.34, ed è proprio questa macchina ( 192.168.0.34 ) che deve smistare le richieste alla LAN INTERNA che ha dietro di se. Non è nel nostro caso ma questa macchina potrebbe avere piu interfacce ( almeno 2: una interna e una esterna ) quindi oltre che smistare le richieste deve passarle da un interfaccia ad un altra e ciò vuol dire che deve avere l’ip forward abilitato. Comunque sia ciò che dobbiamo effettuare è il MASQUERADE:

iptables -t nat -A POSTROUTING -p tcp --dport 80 -j MASQUERADE

ipt16 A questo punto la richiesta del web server viene soddisfatta e anche dai log vediamo come l’ip sorgente sia cambiato. ipt17 Andiamo a chiarire il discorso del funzionamento dei pacchetti nelle catene:   Quando facciamo una richiesta diretta ad esempio ad un web server dove quindi abbiamo un Client che fa una richiesta e un Server che la soddisfa abbiamo un pacchetto che entra nella catena di INPUT, un processo che elabora la richiesta e un pacchetto che usa la catena di OUTPUT per soddisfare la richiesta.

INPUT ———> PROCESSO DI ELABORAZIONE ———-> OUTPUT

Quando invece dobbiamo far passare la richiesta attraverso un server che a sua volta instrada la richiesta a un host della sua rete interna abbiamo un pacchetto che arriva in PREROUTING e che gli viene detto fin da subito dove deve andare ancor prima che entri. Una volta stabilito ciò entra e usa la catena FORWARD per attraversare l’host dopo di che va nella catena POSTROUTING per incapsulare questa richiesta alterando l’ip sorgente con quello dell’host da cui è passato in questo momento.

PREROUTING ——–> FORWARD———–> POSTROUTING

Arriva al server della LAN interna che esegue la richiesta e invia la risposta tramite la catena OUTPUT verso il server 192.168.0.34 che ne aveva fatto richiesta

INPUT —> PROCESSO DI ELABORAZIONE —> OUTPUT VERSO IL SERVER 192.168.0.34

Il Server 192.168.0.34 si vede cosi arrivare la risposta sulla catena FORWARD e la invia a chi ne aveva fatto richiesta.

—-> FORWARD —–> VERSO 192.168.0.2

Questo ultimo passaggio non è completo a livello di concetto generale. Praticamente la risposta che riceve 192.168.0.34 la riceve da un IP LOCALE e quindi per forwardarla a chi ne ha fatto richiesta deve prima cambiare ip piuttosto che inviare la richiesta in un altra inferfaccia ma in tutti e 2 i casi deve essere mascherata.
Per concludere parleremo di log e di come è possibile inserire le regole da un file. Iniziamo con i log: Come abbiamo potuto vedere nel precedente articolo oltre che a progettare il nostro firewall con regole, politiche e stati di connessione è possibile anche vedere in tempo reale cosa sta accadendo tramite i log. Avere cioè un file dove possiamo monitorare e tenere traccia delle connessioni che ci serve sapere o piuttosto vedere cosa sta accadendo in una certa catena per capire dove possono risiedere dei problemi di configurazione piuttosto che vedere se il nostro firewall risulta essere sotto attacco. Per fare questo inizieremo con andare a scrivere una regola in cui diciamo di loggare tutto ciò che sta accadendo: La nostra configurazione del firewall è la seguente: ipt29 Andiamo a scrivere la regola per monitorare tutto ciò che accade nella catena di INPUT:

iptables -I INPUT -j LOG

Con questa semplice regola tutto ciò che arriva in input verrà loggato nel file /var/log/messages Daremo il seuente comando:

tail -f /var/log/messages

Utilizzeremo il comando tail -f per rimanere in ascolto su quel file e avere in tempo reale lo stato attuale dei log. ipt18 Come vediamo abbiamo dei log da parte del client 192.168.0.2 sulla porta 22 visto che siamo connessi in SSH. Questa cosa magari potrebbe darci fastidio visto che difficilmente ci interessa i log di SSH e magari questi continui log si sovrappongono ad altri che magari effettivamente ci servono. Per fare ciò usiamo l’operatore ! Serve per negare, cioè nel caso della regola che andiamo a scrivere sotto fa si che venga loggato tutto il traffico tranne quello sulla porta 22. Eliminiamo la regola sopra citata e inseriamo quella sotto:

iptables -D INPUT 1
 
iptables -A INPUT -p tcp ! --dport 22 -j LOG

E come vediamo i log sulla porta 22 si sono fermati. ipt19 Potremmo avere bisogno magari di avere più tipologie di log ( sia in INPUT che in OUTPUT per esempio ) e per differenziarle una tipologia dall’altra ci potrebbe tornare comodo inserire una voce accanto al log per esempio: Connessione Ingresso http Per fare ciò dopo il taget -j LOG usiamo l’opzione –log-prefix “frase da inserire”

iptables -A INPUT -p tcp –-dport 80 -j LOG --log-prefix “CONNESSIONE INGRESSO HTTP”

 

iptables -A OUTPUT -p tcp --sport 80 -j LOG --log-prefix “CONNESSIONE USCITA HTTP”

ipt20 E in tal caso non dimentichiamoci di aprire la porta 80 sul firewall:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

Appena facciamo una richiesta al web server vediamo infatti nei log la risposta con accanto la voce che abbiamo inserito per una maggior chiarezza. ipt21 Cosa importante è dove andiamo a inserire la regola, cioè in che posizione, prima di quale altre regole?? Facciamo degli esempi:   Se ad esempio vogliamo garantire l’accesso al web server, monitorando nei log le connessioni, inserendo il prefisso “CONNESSIONE HTTP”, (-j log –log-prefix “ ….” ) se inseriamo la regola dei LOG dopo la regola che garantisce l’accesso alla porta 80 non vedremo nessuna tipologia di LOG. ipt22 Questo perchè iptables trova prima la regola che soddisfa la richiesta che gli arriva e quindi la esegue senza andare a scandagliare le altre. Invece dobbiamo mettere prima la regola per i LOG e successivamente la regola che garantisce l’accesso. Cioè cosi: ipt23 Inoltre se vogliamo che vengano loggate solamente le connessioni proveniente da un certo ip come nel nostro esempio inseriremo l’ip sorgente: ipt24 Se dovete eliminare delle regole per inserirne di nuove invece che stare a contare una ad una la posizione in cui si trova la regola da eliminare potete dare il seguente comando e vi farà vedere a che posizione è la regola da eliminare

iptables -L --line-number

ipt25 Detto ciò abbiamo parlato precedentemente dell’inserimento delle regole del firewall in un file; Stiamo parlando praticamente di scrivere le regole che compongono il nostro firewall non come abbiamo fatto fino adesso ma scrivendole in un file per poi darlo in pasto ad iptables e avere cosi tutte le regole pronte in un attimo. Abbiamo detto che le regole vengono salvate nel file iptables che si trova in /etc/sysconfig e vengono caricare all’avvio del sistema. L’operazione di salvataggio la facciamo tramite il comando iptables-save > percorso del file. Una volta capito la struttura delle regole scritte nel file è possibile crearne uno o più file per avere magari diverse configurazioni gia pronte e una volta che si vuole attuare una diversa configurazione utilizzeremo il comando iptables-restore < percorso del file. E tutte le regole precedenti che c’èrano verranno eliminate e il firewall si configurerà con la nuova struttura di regole. Per esempio abbiamo salvato e rimanipolato con nuove regole un file di nome iptables2 in /etc/sysconfig, questa è la seguente struttura: ipt26 Il firewall ha attualmente la seguente configurazione: ipt27 Eliminiamo queste regole e carichiamo la configurazione presente nel file iptables2:

iptables-restore &lt; /etc/sysconfig/iptables2

E vediamo che iptables ha la nuova configurazione: ipt28

Info about author

Michele Milaneschi

RHCE Consultant