Firewall con iptables in Katharà
In questa pagina 6
Il laboratorio 6 (LAB6) mostra come si realizza concretamente un firewall a filtro di pacchetti su Linux. La teoria dei firewall (tipologie, politiche, architetture) è nella nota FirewallUn firewall è un componente (hardware, software o entrambi) che blocca il traffico non autorizzato da una rete verso un'altra: filtra i dati, reindirizza il traffico, protegge dagli attacchi. Requisiti: tutto il traffico tra due zone di fiducia deve passare dal firewall, passa solo il traffico autorizzato, il firewall stesso deve essere immune alle intrusioni. L'amministratore configura le politiche (controllo di utente, di servizio, di direzione); un pacchetto può essere accettato, negato o rifiutato (negato più messaggio ICMP alla sorgente). Il firewall decide con le informazioni di intestazione dei livelli 2-4 (indirizzi, protocollo, porte, flag SYN/ACK/FIN). Packet filter: senza stato, filtra in ingresso e in uscita con regole su indirizzi, protocollo, porte, flag (esempi SMTP, Telnet, X11 e correzioni con porte sorgente e flag ACK). Stateful firewall: tiene traccia delle connessioni (NEW, ESTABLISHED, RELATED, INVALID), limita connessioni al secondo, timeout. Firewall applicativo/proxy: ispeziona il livello applicazione, apre una connessione separata verso la destinazione; sicuro ma lento. Linux: netfilter con 5 hook IPv4 e 5 verdetti, iptables (tabelle e catene), connection tracking nf_conntrack.Firewall →; la traduzione di indirizzi nella nota NAT e indirizzi privatiUna rete privata (intranet) usa il protocollo TCP/IP con indirizzi privati ($10.0.0.0/8$, $172.16.0.0/12$, $192.168.0.0/16$), riutilizzabili da intranet diverse ma da non instradare in Internet: i router di bordo scartano i pacchetti con indirizzi privati. Per accedere a Internet servono un proxy applicativo (uno per applicazione) o il NAT (Network Address Translation): un router che traduce indirizzi privati in indirizzi pubblici di un pool, con una tabella NAT e un'associazione dinamica per sessione. Il NAT tradizionale è outbound: Basic NAT traduce solo l'IP (uno a uno, quindi servono tanti indirizzi pubblici quante le sessioni contemporanee), NAPT traduce anche la porta ([IP privato, porta] $\to$ [IP pubblico, porta del NAT]) e permette a molte sessioni di condividere un solo IP pubblico. Il Twice NAT permette sessioni anche dall'esterno, con un DNS interno e associazioni statiche.NAT e indirizzi privati →. Come si avvia un laboratorio è in Katharà - emulare una reteKatharà è un emulatore di rete: ogni dispositivo (host, router, server) è un container Docker, e i container sono collegati da "domini di collisione" virtuali (reti locali). Un laboratorio è una cartella con lab.conf (topologia), un file <dispositivo>.startup per ogni macchina (comandi eseguiti all'avvio) e, se serve, una cartella per dispositivo con i file da copiare nel suo filesystem. Si avvia con lstart, si ferma con lclean; le macchine si configurano con ifconfig, si provano con ping e si osservano con tcpdump (file .pcap da aprire con Wireshark).Katharà - emulare una rete →. Per le porte e i protocolli usati nelle regole vedi Livello di trasporto - porte e multiplexingIl livello di trasporto (transport layer) offre la comunicazione logica end-to-end tra processi applicativi di host diversi, ed è realizzato solo negli host finali, non nei router. Il livello di rete consegna al computer giusto (indirizzo IP), il trasporto consegna al processo giusto (numero di porta di 16 bit, 0-65535). Una porta più un indirizzo IP formano un socket; la quaterna (IP sorgente, porta sorgente, IP destinazione, porta destinazione) identifica una connessione. I servizi sono: comunicazione processo-processo, indirizzamento, incapsulamento/decapsulamento, multiplexing/demultiplexing e, se il protocollo è affidabile, controllo di errore, di flusso e di congestione. I protocolli sono UDP (senza connessione, inaffidabile), TCP (con connessione, affidabile) e SCTP (combina i due).Livello di trasporto - porte e multiplexing →.
Firewall e filtri di pacchetti
Un firewall è un dispositivo (una scatola dedicata ai confini della rete, oppure un processo su una macchina) che realizza il controllo degli accessi tra reti. Tipicamente protegge le informazioni di una rete locale fidata (Intranet) da Internet, e consente accessi limitati solo a host e applicazioni autorizzate. Il termine comprende dispositivi molto diversi, dai proxy e firewall a livello applicazione ai filtri di pacchetti (packet filter), che controllano i pacchetti in entrata e in uscita contro criteri prefissati e lasciano passare solo quelli che li soddisfano.
- Filtro senza stato (stateless): esamina ogni pacchetto da solo, non come parte di una connessione; controlla di solito il tipo di protocollo e gli indirizzi e le porte di origine e destinazione. I pacchetti che non soddisfano la lista consentita vengono scartati (drop: in silenzio) o rifiutati (reject: con un messaggio d'errore).
- Filtro con stato (stateful): arriva fino al livello trasporto e può ricordare i pacchetti già visti, riconoscere se un pacchetto fa parte di una «conversazione» in corso o ne inizia una nuova, e decidere a livello di connessione senza esaminare ogni pacchetto da capo. Una «conversazione» non richiede un protocollo orientato alla connessione: per UDP si riconosce un flusso, per esempio dal tempo tra un pacchetto e la risposta. Protocolli come FTP usano più flussi e hanno informazioni sul flusso nel contenuto del livello trasporto: serve l'ispezione profonda dei pacchetti (deep packet inspection).
Il NAT (nel caso di più host con un solo indirizzo pubblico, NAPT) è utile anche al filtraggio: gli indirizzi privati non sono instradabili da fuori, e cambiare indirizzo e porta serve a tenere lo stato della conversazione.
NetFilter e iptables
iptables è un programma in spazio utente che comanda la sua controparte nel kernel, NetFilter, e realizza un filtro con stato più NAPT. Nelle distribuzioni più recenti lo sostituisce nftables, con funzioni aggiuntive; nel laboratorio si usa iptables.
NetFilter ha due livelli: tabelle, che contengono catene, che contengono regole.
| Tabella | Scopo | Catene predefinite |
|---|---|---|
filter |
filtraggio base | INPUT, OUTPUT, FORWARD |
nat |
traduzione di indirizzi e porte (NAPT) | PREROUTING, OUTPUT, POSTROUTING |
mangle |
modifica dei pacchetti (per esempio il TTL) | PREROUTING, INPUT, OUTPUT, FORWARD, POSTROUTING |
raw |
eccezioni al tracciamento delle conversazioni | PREROUTING, OUTPUT |
Mangle e raw non si usano nel corso. Ogni catena è una lista di regole, ognuna con un criterio di corrispondenza e un'azione (target). Il pacchetto è trattato secondo la prima regola che lo riconosce; se nessuna lo riconosce, vale la politica predefinita (default policy) della catena.
Definizione (target). Azione di una regola. Nella tabella
filter:ACCEPT(accetta),DROP(scarta in silenzio),REJECT(scarta e invia un errore al mittente, con--reject-with icmp-host-unreachable,icmp-net-unreachable,icmp-port-unreachable, ...), una catena definita dall'utente,RETURN(torna dalla catena utente),LOG(registra il pacchetto, non termina la catena, con--log-levele--log-prefix). Nella tabellanat:DNAT(cambia destinazione),SNAT(cambia sorgente),MASQUERADE(come SNAT, ma per indirizzo pubblico dinamico),REDIRECT(porta il pacchetto sul firewall).
Esempio. Con DROP un client che prova a collegarsi a una porta chiusa aspetta invano e va in timeout; con REJECT riceve subito un errore ICMP.
Il percorso di un pacchetto
Il percorso dipende da chi è il destinatario e chi il mittente:
Pacchetto in ENTRATA (per la macchina):
interfaccia -> nat PREROUTING (DNAT) -> instradamento -> filter INPUT -> processo locale
Pacchetto in USCITA (generato dalla macchina):
processo locale -> filter OUTPUT -> instradamento -> nat POSTROUTING (SNAT) -> interfaccia
Pacchetto INOLTRATO (la macchina è un router):
interfaccia -> nat PREROUTING (DNAT) -> instradamento -> filter FORWARD -> nat POSTROUTING (SNAT) -> interfacciaConseguenze, spiegate dalla guida del laboratorio:
- il DNAT avviene prima dell'instradamento: INPUT e FORWARD vedono già la destinazione «vera» e possono filtrare su quella;
- il SNAT avviene dopo il filtro: INPUT, OUTPUT e FORWARD vedono l'indirizzo sorgente «vero» (dopo SNAT tutti i pacchetti avrebbero lo stesso indirizzo pubblico e filtrare sulla sorgente non avrebbe senso);
- i pacchetti inoltrati seguono un cammino diverso da quelli per la macchina stessa: così un router può essere isolato dall'ambiente e continuare a fare il suo lavoro. Proteggere la macchina si fa in
INPUT, proteggere ciò che sta dietro il router inFORWARD.
I comandi
iptables [--table nome-tabella] --append catena criteri --jump target # aggiunge una regola in fondo
iptables [--table nome-tabella] --delete catena criteri --jump target # cancella una regola
iptables [--table nome-tabella] --insert catena [n] criteri --jump target # inserisce in posizione n
iptables [--table nome-tabella] --replace catena n criteri --jump target # sostituisce la regola n
iptables [--table nome-tabella] --list [catena] # mostra le regole
iptables [--table nome-tabella] --flush [catena] # svuota una catena (o tutte)
iptables [--table nome-tabella] --new-chain nome # crea una catena utente
iptables [--table nome-tabella] --delete-chain [nome] # cancella una catena utente vuota
iptables [--table nome-tabella] --policy catena target # cambia la politica predefinita
iptables [--table nome-tabella] --rename-chain vecchio nuovoSe --table manca, la tabella è filter. Le opzioni lunghe hanno forme brevi: -t (tabella), -A (append), -I (insert), -D (delete), -L (list), -F (flush), -P (policy), -j (jump), -i e -o (interfaccia di ingresso e uscita), -s e -d (sorgente e destinazione), -p (protocollo).
Criteri di corrispondenza, combinabili:
| Criterio | Opzione |
|---|---|
interfaccia di ingresso (eth0, lo per la loopback) |
--in-interface nome |
| interfaccia di uscita | --out-interface nome |
| indirizzo o rete sorgente | --source indirizzo oppure --source rete/maschera |
| indirizzo o rete destinazione | --destination indirizzo o --destination rete/maschera |
protocollo (tcp, udp, icmp, ...) |
--protocol nome |
tipo di messaggio ICMP (echo-request, echo-reply, ...) |
--protocol icmp --icmp-type tipo |
| porte TCP/UDP | --protocol tcp --source-port n e --protocol tcp --destination-port n |
| flag TCP | --protocol tcp --tcp-flags SYN,ACK,FIN,RST SYN |
| stato della conversazione | --match state --state NEW / ESTABLISHED / RELATED |
Come si legge rete/maschera (--source e --destination). Un indirizzo IPv4 ha 32 bit; /24 vuol dire che i primi bit identificano la rete e gli ultimi bit l'host (Subnetting e supernettingIl subnetting divide un blocco di indirizzi in sottoblocchi più piccoli allungando la maschera ($n_{\text{sub}}=n_{\text{rete}}+s$, con $2^s$ sottoreti); il supernetting (aggregazione CIDR) fa l'opposto, accorciando il prefisso per unire blocchi contigui in uno più grande. Regole di progetto: ogni sottorete ha un numero di indirizzi potenza di 2 ($M=2^k\ge$ host richiesti $+2$), prefisso $n=32-k$, indirizzo iniziale multiplo di $M$; si assegnano prima le sottoreti più grandi. Per aggregare $2^j$ blocchi di prefisso $n$ servono blocchi contigui il cui primo indirizzo sia multiplo della dimensione dell'aggregato, e il nuovo prefisso è $n-j$.Subnetting e supernetting →, Livello di rete e indirizzamento IPIl livello di rete (network layer) porta i datagrammi da host a host attraverso i router: incapsula (framing), sceglie il percorso (routing) e sposta il pacchetto da un ingresso a un'uscita del router (forwarding); in Internet lascia ai livelli superiori controllo d'errore, di flusso e di congestione. Un indirizzo IPv4 è di 32 bit, diviso in prefisso (rete, $n$ bit) e suffisso (host, $32-n$ bit). L'indirizzamento a classi (A, B, C, D, E) è obsoleto; oggi si usa quello senza classi (CIDR): data una notazione $a.b.c.d/n$ si ricavano $N=2^{32-n}$ indirizzi, indirizzo di rete (suffisso tutto 0) e di broadcast (suffisso tutto 1), oppure con la netmask: rete $=$ indirizzo AND maschera, broadcast $=$ indirizzo OR (NOT maschera).Livello di rete e indirizzamento IP →). Un pacchetto soddisfa il criterio se, azzerando i bit dell'host, si ottiene l'indirizzo di rete scritto nella regola, cioè se
(AND bit a bit: , , Algebra di Boole e porte logicheVariabili booleane, operatori AND, OR, NOT e derivati (NAND, NOR, XOR, XNOR) con tabelle di verità; assiomi e teoremi dell'algebra di Boole, De Morgan; porte logiche e completezza di NAND e NOR; semplificazione algebrica con esempio.Algebra di Boole e porte logiche →). La maschera /16 è (Basi di numerazione e conversioni - binario, ottale ed esadecimaleUn numero in base $r$ vale $\sum a_i r^i$ (cifre $a_i\in{0,\dots,r-1}$). Conversioni: base $r\to$ decimale con la somma pesata; decimale $\to$ base $r$ per divisioni successive (parte intera, resti letti dal basso) e moltiplicazioni successive (parte frazionaria, parti intere lette dall'alto); binario $\leftrightarrow$ ottale/esadecimale a gruppi di 3/4 bit. Somma, differenza e prodotto binari seguono le regole decimali con cifre 0 e 1; la differenza ha prestiti, il prodotto somma prodotti parziali traslati.Basi di numerazione e conversioni - binario, ottale ed esadecimale →): il primo e il secondo ottetto restano, gli altri diventano . Esempio: 192.168.10.111 AND 255.255.0.0 192.168.0.0, quindi l'host rientra in 192.168.0.0/16 (e con /24, 255.255.255.0, si avrebbe 192.168.10.0, rete della LAN). Un indirizzo pubblico come 203.0.113.9 dà 203.0.0.0 e non corrisponde. Un indirizzo senza maschera, come --source 147.162.13.111, equivale a /32 (tutti i 32 bit devono coincidere: un solo host). Quanti indirizzi copre una rete? : /24 ne copre , /16 ne copre , /30 ne copre .
Stati: NEW per i pacchetti che aprono una conversazione, ESTABLISHED per quelli che appartengono a una conversazione esistente, RELATED per quelli che aprono una conversazione collegata a una esistente (per esempio il canale dati di FTP). Lo stato della conversazione non coincide con lo stato della connessione TCP, e lo stato RELATED non esiste per i normali pacchetti TCP.
Formula (regola di filtro).
iptables --table filter --append CATENA [criteri] --jump TARGET: aggiunge in coda alla catena una regola che applica il target ai pacchetti che soddisfano tutti i criteri.
Esempio. iptables --table filter --append INPUT --protocol tcp --destination-port 22 --jump ACCEPT accetta in ingresso i pacchetti TCP diretti alla porta (SSH).
Le regole di nat hanno target che modificano il pacchetto: --jump DNAT --to-destination indirizzo[:porta], --jump SNAT --to-source indirizzo[:porta], --jump MASQUERADE.
Esempio 1: il firewall sulla macchina da proteggere
Obiettivo. Il computer può accedere a qualsiasi servizio Internet, ma da fuori nessuno può raggiungerlo, tranne ping e ssh.
Topologia. vpc e r1 nel dominio MYNET; ws e r2 nel dominio REMOTENET; r1 e r2 collegati dal dominio INTERNET (la «Internet» tra i due router).
lab.conf:
vpc[0]=MYNET ws[0]=REMOTENET
r1[0]=MYNET r1[1]=INTERNET
r2[0]=REMOTENET r2[1]=INTERNET vpc 147.162.13.111/24 --- 147.162.13.254 [r1] 159.173.25.254/30 === 159.173.25.253/30 [r2] 148.163.14.254 --- 148.163.14.240 ws| Dispositivo | Interfaccia | Indirizzo |
|---|---|---|
| vpc | eth0 | 147.162.13.111/24 (gateway 147.162.13.254) |
| r1 | eth0 / eth1 | 147.162.13.254/24 / 159.173.25.254/30 |
| r2 | eth0 / eth1 | 148.163.14.254/24 / 159.173.25.253/30 |
| ws | eth0 | 148.163.14.240/24 (gateway 148.163.14.254) |
(indirizzi verificati con Python: 159.173.25.252/30 ha i due host .253 e .254). Il collegamento tra i due router è una rete /30: indirizzi, di cui .252 è l'indirizzo di rete (host tutto a ) e .255 il broadcast (host tutto a ); restano indirizzi utilizzabili, esattamente quelli dei due router. È la rete più piccola che serve per un collegamento punto-punto.
I file di avvio impostano gli indirizzi e le rotte:
# vpc.startup
/sbin/ifconfig eth0 147.162.13.111 netmask 255.255.255.0 up # indirizzo
/sbin/route add default gw 147.162.13.254 # uscita: r1
/etc/init.d/apache2 start # web server
/etc/init.d/ssh start # server SSH
# r1.startup
ifconfig eth0 147.162.13.254 netmask 255.255.255.0 up
ifconfig eth1 159.173.25.254 netmask 255.255.255.252 up
route add -net 148.163.14.0/24 gw 159.173.25.253 # la rete di ws è dietro r2r2 e ws sono speculari (r2 ha la rotta route add -net 147.162.13.0/24 gw 159.173.25.254; ws avvia solo Apache). Le pagine web sono in vpc/var/www/index.html e ws/var/www/index.html.
SSH. Sulla vpc occorre abilitare l'accesso di root: nel file /etc/ssh/sshd_config si imposta PermitRootLogin yes, si riavvia con /etc/init.d/ssh restart e si imposta la password con passwd (nel laboratorio è rootpwd).
Esercizio 1. links 127.0.0.1 su vpc apre la pagina vpc web server works!. Da ws il comando links 147.162.13.111 mostra la stessa pagina, perché senza regole la politica è ACCEPT. ssh root@147.162.13.111 da ws chiede la password rootpwd; si esce con Ctrl+D; q e y chiudono links.
Per cancellare una tabella: iptables --table filter --flush e iptables --table filter --delete-chain (si può sostituire filter con un'altra tabella). Le regole, sulla vpc, in ordine:
iptables --table filter --policy INPUT DROP # 1. tutto ciò che entra viene scartato...
iptables --table filter --policy OUTPUT ACCEPT # ...tutto ciò che esce è permesso
iptables --table filter --append INPUT --in-interface lo --jump ACCEPT # 2. eccezione per la loopback
iptables --table filter --append INPUT --protocol icmp --icmp-type echo-request --jump ACCEPT # 3. si può fare ping a vpc
iptables --table filter --append INPUT --protocol tcp --destination-port 22 --jump ACCEPT # 4. si può entrare con SSH
iptables --table filter --append INPUT --match state --state ESTABLISHED,RELATED --jump ACCEPT # 5. risposte alle connessioni aperte da vpcChe cosa cambia a ogni regola (verifiche delle slide):
| Dopo il passo | links 127.0.0.1 su vpc |
ping vpc da ws |
ssh a vpc da ws |
links a vpc da ws |
vpc naviga su ws |
|---|---|---|---|---|---|
| 1 (politica DROP) | no (anche la loopback è bloccata) | no | no | no | no |
| 2 (loopback) | sì | no | no | no | no |
| 3 (echo-request) | sì | sì | no | no | no |
| 4 (porta 22) | sì | sì | sì | no | no |
| 5 (ESTABLISHED) | sì | sì | sì | no | sì |
Spiegazioni:
- Passo 1. La politica DROP in INPUT blocca anche i processi locali: senza l'eccezione per
lo,links 127.0.0.1non funzionerebbe (il pacchetto passa dall'interfaccia di loopback e rientra in INPUT). Perciò: «per non rompere i processi locali» si accetta tutto ciò che entra dalo. - Passo 3. Si accetta solo l'
echo-request(tipo di messaggio): lavpcrisponde ai ping, la risposta esce in OUTPUT (ACCEPT). - Passo 5. Anche se OUTPUT è ACCEPT e la richiesta di
vpcversowsesce, la risposta diwsrientra in INPUT e verrebbe scartata dalla politica DROP: lavpcnon riuscirebbe a navigare. La regola conESTABLISHED,RELATEDaccetta i pacchetti che appartengono a una conversazione iniziata dallavpcstessa. Unpingdavpcversowsfunziona per lo stesso motivo (l'echo-reply èESTABLISHED). - Il pacchetto bloccato da
DROPnon genera nessuna risposta: perlinksversovpcdawsla connessione resta in attesa fino al timeout. ConREJECTsi avrebbe un errore immediato.
Seguire un pacchetto nelle regole (dopo il passo 5, catena INPUT, politica DROP; si scorre l'elenco dall'alto e si applica la prima regola che corrisponde).
pacchetto che entra in vpc |
regola 2 (lo) |
regola 3 (ICMP echo-request) | regola 4 (TCP porta 22) | regola 5 (stato) | esito |
|---|---|---|---|---|---|
ping da ws (echo-request) |
no (arriva da eth0) |
sì | ACCEPT | ||
SYN di ws verso la porta 22 |
no | no (è TCP) | sì | ACCEPT | |
SYN di ws verso la porta 80 |
no | no | no (porta 80) | no (è NEW) | politica DROP |
risposta di ws alla richiesta web di vpc |
no | no | no | sì (ESTABLISHED) | ACCEPT |
Il terzo pacchetto è la richiesta di una nuova conversazione verso un servizio non previsto: nessuna regola lo riconosce, quindi cade nella politica. Il quarto è la risposta a una conversazione iniziata da vpc: passa solo per la regola 5.
Proprietà (politica restrittiva). Si parte con
INPUTinDROP(si vieta tutto) e si aggiungono eccezioni per ciò che serve (whitelist). Il vantaggio è che tutto ciò che non è stato previsto resta chiuso.
Esempio. Qui: loopback, ping, SSH e le risposte alle conversazioni iniziate dalla macchina. Il servizio web resta chiuso da fuori.
Esempio 2: il firewall sul router di una LAN
Obiettivo. R1 deve lasciar entrare il traffico verso il web server pubblico LANWS, ma non verso gli altri host della LAN (LANPC1, LANPC2), lasciando i computer della LAN liberi di collegarsi a Internet. Il traffico SSH in ingresso è bloccato, tranne le richieste da LANPC1 e LANPC2 verso R1 (per amministrare il firewall dall'interno).
Topologia: i tre host lanpc1 (147.162.13.111), lanpc2 (147.162.13.112), lanws (147.162.13.240) stanno sul dominio MYNET insieme a r1.eth0 (147.162.13.254/24); r1.eth1 (159.173.25.254/30) è collegato a r2.eth1 (.253); ws (148.163.14.240) sta dietro r2. r1 e r2 hanno ciascuno una rotta predefinita verso l'altro (route add -net default gw 159.173.25.253 su r1) e r1 avvia SSH (/etc/init.d/ssh start), con password rootpwd.
Esercizio 2. Prima di ogni regola, da WS: ssh root@147.162.13.254 entra in R1 (è raggiungibile da fuori) e ping 147.162.13.111 raggiunge LANPC1 (nessun filtro).
iptables --table filter --policy INPUT DROP # R1 non accetta nulla per se stesso...
iptables --table filter --policy OUTPUT ACCEPT # ...ma può inviare
iptables --table filter --append INPUT --in-interface lo --jump ACCEPT # loopback
iptables --table filter --policy FORWARD DROP # nessun pacchetto attraversa il router: la LAN è isolata da entrambi i latiOra R1 stesso non è raggiungibile da nessuna macchina e la LAN è staccata da Internet. Si riapre solo ciò che serve:
# 1. dalla LAN verso fuori: tutto
iptables --table filter --append FORWARD --in-interface eth0 --out-interface eth1 --jump ACCEPT
# 2. da fuori verso la LAN: solo le risposte
iptables --table filter --append FORWARD --in-interface eth1 --out-interface eth0 --match state --state ESTABLISHED,RELATED --jump ACCEPTEsercizio 3. Ora LANPC1 raggiunge WS (la richiesta esce dalla LAN e la risposta rientra come ESTABLISHED). WS non raggiunge il servizio web di LANWS: il primo pacchetto di una nuova connessione da fuori è NEW e non corrisponde a nessuna regola. Per pubblicare il servizio:
iptables --table filter --append FORWARD --protocol tcp --destination-port 80 --in-interface eth1 --out-interface eth0 --destination 147.162.13.240 --jump ACCEPT # solo TCP 80, solo verso LANWSLa regola ha quattro criteri insieme (protocollo e porta, interfaccia di ingresso e uscita, destinazione): un pacchetto la soddisfa solo se li soddisfa tutti. Infine l'accesso SSH di gestione:
iptables --table filter --append INPUT --protocol tcp --destination-port 22 --in-interface eth0 --source 147.162.13.111 --jump ACCEPT # LANPC1 può entrare in R1
iptables --table filter --append INPUT --protocol tcp --destination-port 22 --in-interface eth0 --source 147.162.13.112 --jump ACCEPT # LANPC2 pureLANWS non ha una regola (la sua sorgente non corrisponde) e quindi non può accedere al router, e neppure WS da fuori (interfaccia eth1).
Riassunto dell'effetto finale (in R1):
| Traffico | Esito | Regola |
|---|---|---|
| LAN Internet (qualsiasi) | passa | FORWARD eth0eth1 |
Internet LANWS TCP 80 |
passa | FORWARD con --destination 147.162.13.240 |
| Internet altri host della LAN | scartato | politica FORWARD DROP |
| Internet LAN, risposte | passano | FORWARD ESTABLISHED,RELATED |
LANPC1/LANPC2 R1 SSH |
passa | INPUT, porta 22 e sorgente |
LANWS, WS R1 |
scartato | politica INPUT DROP |
Esempio 3: NAT (esercizio avanzato)
La rete è la stessa, ma ora la LAN usa indirizzi privati (192.168.10.0/24) e R1 deve anche tradurre gli indirizzi. Nel laboratorio r è un router in mezzo ad «Internet».
LAN privata 192.168.10.0/24 Internet (reti pubbliche) rete di ws
lanpc1 .111, lanpc2 .112, lanws .240
--- eth0 .254 [r1] eth1 .253 ---- .254 eth0 [r] eth1 .253 ---- .254 eth1 [r2] eth0 .254 --- ws .240
161.175.30.252/30 (INTERNET1) 162.176.31.252/30 (INTERNET2) 148.163.14.0/24Indirizzi (verificati con Python): 161.175.30.252/30 collega r1 (.253) e r (.254); 162.176.31.252/30 collega r (.253) e r2 (.254). Rotte: r1 e r2 hanno una rotta predefinita verso r; r ha route add -net 148.163.14.0/24 gw 162.176.31.254 e route add default gw 161.175.30.253. Inoltre r ha due regole:
iptables --table filter --append INPUT --source 192.168.0.0/16 --jump DROP # scarta i pacchetti destinati a r con sorgente privata
iptables --table filter --append FORWARD --source 192.168.0.0/16 --jump DROP # scarta quelli da inoltrare con sorgente privataPerché: 192.168.0.0/16 (che contiene la LAN 192.168.10.0/24: verificato) è uno spazio privato, che non deve circolare in Internet; i router di Internet scartano questi pacchetti. Perciò all'inizio le LAN non si vedono tra loro né raggiungono WS (connettività limitata). La soluzione è il NAT su R1.
SNAT per il traffico uscente.
iptables --table nat --append POSTROUTING --source 192.168.10.0/24 --out-interface eth1 --jump SNAT --to 161.175.30.253Lettura: nella tabella nat, catena POSTROUTING (dopo l'instradamento), per i pacchetti con sorgente nella LAN (192.168.10.0/24: i primi bit sono 192.168.10, quindi l'host 192.168.10.111 rientra) che escono da eth1, sostituisce la sorgente con 161.175.30.253 (l'indirizzo pubblico di R1). I pacchetti dalla LAN ora raggiungono l'esterno. Le risposte tornano all'indirizzo pubblico di R1, e NetFilter, che ricorda la conversazione, rimette automaticamente l'indirizzo privato e le inoltra al giusto host. Le regole di nat si applicano solo al primo pacchetto di ogni connessione: i successivi e le risposte seguono la traduzione già registrata.
Esempio di traduzione. LANPC1 apre una connessione web verso WS: il pacchetto esce da 192.168.10.111:40000 verso 148.163.14.240:80. Su eth1 di R1 lo SNAT lo riscrive con sorgente 161.175.30.253:40000, e il tracciamento delle connessioni registra la coppia (). La risposta di WS torna con destinazione 161.175.30.253:40000; R1 trova la coppia e riscrive la destinazione in 192.168.10.111:40000. Se due host della LAN usassero per caso la stessa porta sorgente, R1 cambierebbe anche la porta per distinguerli (è il NAPT, NAT e indirizzi privatiUna rete privata (intranet) usa il protocollo TCP/IP con indirizzi privati ($10.0.0.0/8$, $172.16.0.0/12$, $192.168.0.0/16$), riutilizzabili da intranet diverse ma da non instradare in Internet: i router di bordo scartano i pacchetti con indirizzi privati. Per accedere a Internet servono un proxy applicativo (uno per applicazione) o il NAT (Network Address Translation): un router che traduce indirizzi privati in indirizzi pubblici di un pool, con una tabella NAT e un'associazione dinamica per sessione. Il NAT tradizionale è outbound: Basic NAT traduce solo l'IP (uno a uno, quindi servono tanti indirizzi pubblici quante le sessioni contemporanee), NAPT traduce anche la porta ([IP privato, porta] $\to$ [IP pubblico, porta del NAT]) e permette a molte sessioni di condividere un solo IP pubblico. Il Twice NAT permette sessioni anche dall'esterno, con un DNS interno e associazioni statiche.NAT e indirizzi privati →). Per questo le risposte non restano senza destinatario, anche se 192.168.10.111 non è raggiungibile da Internet.
Esercizio 4. links 148.163.14.240 da LANPC1 funziona. Una verifica con tcpdump su r: la sorgente vista è 161.175.30.253, non 192.168.10.111 (che sarebbe stato scartato dalla regola di r).
DNAT per esporre il web server.
iptables --table nat --append PREROUTING --protocol tcp --destination 161.175.30.253 --destination-port 80 --in-interface eth1 --jump DNAT --to 192.168.10.240:80Lettura: nella catena PREROUTING (prima dell'instradamento) i pacchetti TCP diretti a 161.175.30.253 porta arrivati da eth1 hanno la destinazione cambiata in 192.168.10.240:80. Poiché la traduzione precede l'instradamento, il pacchetto viene instradato verso la LAN e (in FORWARD) filtrato con la destinazione vera. Ora WS può raggiungere il servizio web di LANWS (links 161.175.30.253), ma non può fare ping alle macchine della LAN: la regola copre solo il TCP sulla porta (ping 161.175.30.253 risponde R1 stesso, non LANWS).
Esercizio 5. Accesso SSH a R1 dall'interno, come nell'esempio 2:
iptables --table filter --policy INPUT DROP
iptables --table filter --append INPUT --in-interface lo --jump ACCEPT
iptables --table filter --append INPUT --protocol tcp --destination-port 22 --in-interface eth0 --source 192.168.10.111 --jump ACCEPT
iptables --table filter --append INPUT --protocol tcp --destination-port 22 --in-interface eth0 --source 192.168.10.112 --jump ACCEPTCambia solo la sorgente (indirizzi privati). Le regole non toccano FORWARD né la tabella nat: SNAT e DNAT restano com'erano.
Errori tipici
- Dimenticare l'eccezione per
locon politica INPUT DROP: i processi locali smettono di funzionare. - Dimenticare
ESTABLISHED,RELATED: le risposte alle connessioni aperte dall'interno vengono scartate. - Filtrare in
INPUTil traffico che attraversa il router (va inFORWARD), o viceversa. - Pensare che dopo SNAT si possa filtrare sulla sorgente privata: il filtro viene prima.
- Confondere
DROP(silenzio, timeout) conREJECT(errore). - Cambiare la politica prima di aggiungere le eccezioni quando si lavora via SSH: ci si chiude fuori.
- Dimenticare che le regole sono nel kernel e vanno ripetute a ogni riavvio del laboratorio (
lclean/lstart): meglio metterle in un.startup.
Versione ripasso
- Filtri (FirewallUn firewall è un componente (hardware, software o entrambi) che blocca il traffico non autorizzato da una rete verso un'altra: filtra i dati, reindirizza il traffico, protegge dagli attacchi. Requisiti: tutto il traffico tra due zone di fiducia deve passare dal firewall, passa solo il traffico autorizzato, il firewall stesso deve essere immune alle intrusioni. L'amministratore configura le politiche (controllo di utente, di servizio, di direzione); un pacchetto può essere accettato, negato o rifiutato (negato più messaggio ICMP alla sorgente). Il firewall decide con le informazioni di intestazione dei livelli 2-4 (indirizzi, protocollo, porte, flag SYN/ACK/FIN). Packet filter: senza stato, filtra in ingresso e in uscita con regole su indirizzi, protocollo, porte, flag (esempi SMTP, Telnet, X11 e correzioni con porte sorgente e flag ACK). Stateful firewall: tiene traccia delle connessioni (NEW, ESTABLISHED, RELATED, INVALID), limita connessioni al secondo, timeout. Firewall applicativo/proxy: ispeziona il livello applicazione, apre una connessione separata verso la destinazione; sicuro ma lento. Linux: netfilter con 5 hook IPv4 e 5 verdetti, iptables (tabelle e catene), connection tracking nf_conntrack.Firewall →). Stateless: esamina ogni pacchetto da solo (protocollo, indirizzi, porte). Stateful: ricorda le conversazioni e decide a livello di connessione. Azioni:
DROPscarta in silenzio (il client va in timeout),REJECTrisponde con un errore ICMP subito,LOGregistra senza terminare la catena. Per UDP e per protocolli a più flussi come FTP serve il tracciamento o l'ispezione profonda. - Stati. NEW apre una conversazione; ESTABLISHED appartiene a una conversazione esistente; RELATED apre una conversazione collegata a una esistente (es. il canale dati di FTP). Lo stato non coincide con quello della connessione TCP; RELATED non esiste per i normali pacchetti TCP.
- NetFilter. Tabelle
filter(INPUT, OUTPUT, FORWARD),nat(PREROUTING, OUTPUT, POSTROUTING),mangle,raw(non usate nel corso). Ogni catena è una lista di regole: vale la prima regola che corrisponde, altrimenti la politica predefinita. Con--tableomesso la tabella èfilter. - Percorsi. Entrata:
nat PREROUTING(DNAT) instradamentofilter INPUT. Uscita:filter OUTPUTinstradamentonat POSTROUTING(SNAT). Inoltro:PREROUTINGinstradamentoFORWARDPOSTROUTING. - Conseguenze. Il DNAT avviene prima dell'instradamento: INPUT e FORWARD vedono la destinazione vera. Lo SNAT avviene dopo il filtro: si filtra sulla sorgente vera. Proteggere la macchina si fa in INPUT; proteggere ciò che sta dietro il router in FORWARD.
- Comandi.
--append(in coda),--insert,--delete,--replace,--list,--flush,--policy,--new-chain,--delete-chain,--rename-chain. Criteri:--in-interface,--out-interface,--source,--destination,--protocol,--icmp-type,--source-port,--destination-port,--tcp-flags,--match state --state. Target:--jump. Regola:iptables --table filter --append CATENA [criteri] --jump TARGETapplica il target solo se valgono tutti i criteri.
iptables --table filter --policy INPUT DROP # politica: scarta tutto ciò che entra
iptables --table filter --append INPUT --in-interface lo --jump ACCEPT # eccezione per la loopback dei processi locali
iptables --table filter --append INPUT --protocol icmp --icmp-type echo-request --jump ACCEPT # accetta ping verso la macchina
iptables --table filter --append INPUT --protocol tcp --destination-port 22 --jump ACCEPT # accetta SSH (porta 22)
iptables --table filter --append INPUT --match state --state ESTABLISHED,RELATED --jump ACCEPT # risposte alle connessioni aperte da lei- Esempio 1: firewall sulla macchina (vpc
147.162.13.111). Obiettivo: la vpc naviga, ma da fuori si raggiunge solo conpingessh. Con la politica DROP la loopback si blocca: senza l'eccezionelinks 127.0.0.1fallisce. Senza l'ultima regola le risposte ai siti visitati rientrano in INPUT e vengono scartate. Dopo ogni passo: ping dawssolo dopo la regola 3, SSH dopo la 4, navigazione dalla vpc solo dopo la 5; il web server della vpc resta chiuso da fuori. - Esempio 2: router r1 di una LAN (
147.162.13.0/24). PoliticaINPUTeFORWARDin DROP: la LAN è isolata da entrambi i lati. Poi si riaprono solo le eccezioni:--policy FORWARDnon basta, serveFORWARDeth0eth1ACCEPT (LAN verso fuori),FORWARDeth1eth0solo conESTABLISHED,RELATED. Il servizio web di LANWS si apre con--protocol tcp --destination-port 80 --in-interface eth1 --out-interface eth0 --destination 147.162.13.240 --jump ACCEPT(quattro criteri insieme). SSH a r1 solo da.111e.112con--in-interface eth0 --source. - Esempio 3: NAT (LAN privata
192.168.10.0/24). Il routerrscarta in INPUT e FORWARD la sorgente192.168.0.0/16(indirizzi privati): senza NAT la LAN non esce. SNAT per l'uscita:--table nat --append POSTROUTING --source 192.168.10.0/24 --out-interface eth1 --jump SNAT --to 161.175.30.253. Le risposte tornano all'indirizzo pubblico e il tracciamento rimette quello privato; la regola vale solo per il primo pacchetto della connessione. - DNAT per esporre il web:
--table nat --append PREROUTING --protocol tcp --destination 161.175.30.253 --destination-port 80 --in-interface eth1 --jump DNAT --to 192.168.10.240:80. WS raggiunge il web di LANWS, ma non le altre macchine della LAN né il ping versoLANWS. - Verifica. Con
tcpdumpsurla sorgente vista è161.175.30.253, non192.168.10.111. - Target. Tabella
filter:ACCEPT,DROP,REJECT(con--reject-with icmp-host-unreachable,icmp-net-unreachable,icmp-port-unreachable),RETURN(torna dalla catena utente),LOG(con--log-levele--log-prefix). Tabellanat:DNAT(cambia destinazione),SNAT(cambia sorgente),MASQUERADE(come SNAT, per indirizzo pubblico dinamico),REDIRECT(porta il pacchetto sul firewall). - Politica restrittiva (whitelist). Si parte da
INPUTin DROP e si aggiungono solo le eccezioni necessarie: tutto ciò che non è previsto resta chiuso. - Esempio 1, effetto di ogni regola. Dopo la regola 1 (politica DROP) non funziona nulla, nemmeno
links 127.0.0.1sulla vpc. Dopo la 2 (loopback) sì. Dopo la 3 (echo-request) il ping dawsriesce, SSH no. Dopo la 4 (porta 22) riesce anche SSH daws,linksverso la vpc no. Dopo la 5 (ESTABLISHED) la vpc naviga suws. Il pacchetto bloccato da DROP non genera risposta: la connessione resta in attesa fino al timeout. - Esempio 2, effetto finale in R1. LAN verso Internet: passa. Internet verso
LANWSTCP 80: passa. Internet verso gli altri host della LAN: scartato dalla politica FORWARD DROP. Risposte verso la LAN: passano (ESTABLISHED,RELATED).LANPC1eLANPC2verso R1 in SSH: passa.LANWSeWSverso R1: scartato dalla politica INPUT DROP. - Esempio 3, verifiche.
links 148.163.14.240daLANPC1funziona grazie allo SNAT. Il DNAT copre solo il TCP porta 80: il ping verso161.175.30.253risponde r1 stesso, nonLANWS. Nell'esercizio 5 cambiano solo le sorgenti SSH (indirizzi privati); FORWARD e tabellanatrestano com'erano. - Errori tipici: dimenticare l'eccezione per
locon INPUT DROP (i processi locali smettono di funzionare); dimenticareESTABLISHED,RELATED; filtrare in INPUT il traffico che attraversa il router (va in FORWARD); filtrare sulla sorgente privata dopo SNAT; confondereDROP(timeout) conREJECT(errore); cambiare la politica prima delle eccezioni lavorando via SSH (ci si chiude fuori); perdere le regole al riavvio del laboratorio (metterle in un.startup).