Esercizio - simulazione del lab test
In questa pagina 3
Testo. Il lab test dell'esame è una prova al computer con Katharà (peso del voto finale; nella simulazione disponibile, due esercizi indipendenti da e punti). Il materiale è una cartella exam_test con exercise1/ ed exercise2/ (file lab.conf, <macchina>.startup) e un PDF con il testo. Si prepara l'ambiente con source ./kathara.sh, si entra nella cartella dell'esercizio e si avvia con lstart; alla fine lclean e lwipe.
Esercizio 1 (quattro router in anello, già con gli indirizzi sulle interfacce). Far comunicare tutti i router tra loro con rotte statiche: ogni macchina deve poter fare ping a tutte le interfacce, cioè a tutti gli indirizzi, di ogni altra macchina.
| Macchina | eth0 |
eth1 |
|---|---|---|
| r1 | ||
| r2 | ||
| r3 | ||
| r4 |
I collegamenti (domini di collisione, in lab.conf) sono: A tra r1.eth0 e r2.eth1; B tra r2.eth0 e r3.eth1; C tra r3.eth0 e r4.eth1; D tra r4.eth0 e r1.eth1.
Esercizio 2 (due macchine, pc e srv nella stessa rete, con srv che esegue un web server sulla porta TCP e SSH). Configurare il firewall Linux su srv in modo che tutto il traffico in ingresso e in uscita sia scartato, tranne le richieste web in arrivo e le relative risposte in uscita.
Teoria usata: 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 →, Routing statico in KatharàLaboratorio 2 (LAB2). Due LAN (195.11.14.0/24 e 200.1.1.0/24) sono unite da due router r1 e r2 collegati da una rete 100.0.0.8/30. Una interfaccia attiva inserisce da sola nella tabella di instradamento solo la rete direttamente collegata: per le altre servono rotte inserite a mano. I PC usano una rotta predefinita (route add default gw 195.11.14.1), i router rotte statiche (route add -net 195.11.14.0/24 gw 100.0.0.9 dev eth1). Senza la rotta di ritorno su r2 le richieste di ping arrivano ma le risposte no: la raggiungibilità vale solo se c'è un percorso in entrambi i versi. A configurazione finita ping da pc1 a pc2 risponde con ttl=62 (64 meno 2 router).Routing statico in Katharà →, Firewall con iptables in KatharàLaboratorio 6 (LAB6). iptables è lo strumento da riga di comando che configura il filtro di pacchetti del kernel Linux (NetFilter). Quattro tabelle (filter, nat, mangle, raw) contengono catene di regole; un pacchetto segue la prima regola che lo riconosce, altrimenti la politica predefinita (ACCEPT, DROP, REJECT). Tabella filter: catene INPUT (pacchetti per la macchina), OUTPUT (generati da lei), FORWARD (che attraversano il router). Tabella nat: PREROUTING (DNAT) e POSTROUTING (SNAT/MASQUERADE). Lo stato di una conversazione si controlla con --match state --state ESTABLISHED,RELATED. Tre esperienze: firewall sulla macchina da proteggere (esempio 1), firewall sul router di una LAN con web server pubblico (esempio 2), NAT con SNAT e DNAT (esempio 3).Firewall con iptables in Katharà →, Instradamento e inoltroL'inoltro (forwarding) mette il pacchetto sulla strada verso la destinazione, un salto alla volta (hop by hop). Se la destinazione è nella stessa rete del mittente l'inoltro è diretto (si usa l'ARP per il MAC del destinatario), altrimenti è indiretto: il pacchetto va al router successivo (next hop) indicato dalla tabella di instradamento, o al default gateway. Con le netmask: l'inoltro è diretto attraverso l'interfaccia $x$ se $\text{IP(dst)}\ \text{AND}\ \text{NM}(x)=\text{IP}(x)\ \text{AND}\ \text{NM}(x)$; altrimenti si scorre la tabella dalla maschera più lunga (longest prefix match) e si usa il primo match. La riga con rete $0.0.0.0$ e maschera $0.0.0.0$ (default route) corrisponde sempre. L'aggregazione di rotte (route aggregation) riduce la tabella, e nell'inoltro con etichette (MPLS) la tabella si consulta per indice.Instradamento e inoltro →.
Esercizio 1: rotte statiche su quattro router in anello
Topologia. Quattro reti , una per collegamento: rete A (r1–r2), B (r2–r3), C (r3–r4), D (r4–r1). Ogni router ha due reti direttamente collegate (le sue interfacce le inseriscono da sole nella tabella) e ne ignora due. Per far rispondere ai ping a tutti gli indirizzi servono due rotte per router: una per ciascuna rete non collegata.
Grafico interattivo: Anello di quattro router e reti dei collegamenti
Quali rotte. Per ogni rete lontana si sceglie un prossimo salto raggiungibile direttamente. Procedimento: per r1 le reti direttamente collegate sono A (tramite eth0 ) e D (tramite eth1 ): l'AND di ogni indirizzo con la maschera dà e (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 →). Mancano B e C. B si trova dietro r2 (vicino sulla rete A, indirizzo ), C dietro r4 (vicino sulla rete D, indirizzo ): si scrive una rotta per ciascuna. Lo stesso ragionamento, ruotato, vale per gli altri router. Qui ogni rete lontana si raggiunge nel modo più breve passando da uno dei due vicini:
| Router | Rete lontana | Prossimo salto | Interfaccia | Perché |
|---|---|---|---|---|
| r1 | (B) | (r2) | eth0 |
r2 è collegato a B |
| r1 | (C) | (r4) | eth1 |
r4 è collegato a C |
| r2 | (C) | (r3) | eth0 |
r3 è collegato a C |
| r2 | (D) | (r1) | eth1 |
r1 è collegato a D |
| r3 | (A) | (r2) | eth1 |
r2 è collegato ad A |
| r3 | (D) | (r4) | eth0 |
r4 è collegato a D |
| r4 | (A) | (r1) | eth0 |
r1 è collegato ad A |
| r4 | (B) | (r3) | eth1 |
r3 è collegato a B |
Comandi (da lanciare nel terminale di ciascuna macchina, oppure da scrivere nel suo file <macchina>.startup dopo le righe ifconfig):
# --- su r1 ---
route add -net 100.100.20.0/24 gw 100.100.10.2 dev eth0 # rete B tramite r2 (eth0 di r1 è nella rete A insieme a r2)
route add -net 100.100.30.0/24 gw 100.100.40.1 dev eth1 # rete C tramite r4 (eth1 di r1 è nella rete D insieme a r4)
# --- su r2 ---
route add -net 100.100.30.0/24 gw 100.100.20.2 dev eth0 # rete C tramite r3
route add -net 100.100.40.0/24 gw 100.100.10.1 dev eth1 # rete D tramite r1
# --- su r3 ---
route add -net 100.100.10.0/24 gw 100.100.20.1 dev eth1 # rete A tramite r2
route add -net 100.100.40.0/24 gw 100.100.30.2 dev eth0 # rete D tramite r4
# --- su r4 ---
route add -net 100.100.10.0/24 gw 100.100.40.2 dev eth0 # rete A tramite r1
route add -net 100.100.20.0/24 gw 100.100.30.1 dev eth1 # rete B tramite r3Ogni riga ha la forma route add -net <rete>/<prefisso> gw <prossimo salto> dev <interfaccia>: "la rete si raggiunge tramite il prossimo salto, uscendo dall'interfaccia indicata". Il prossimo salto deve stare in una rete direttamente collegata all'interfaccia (altrimenti il comando dà errore).
Perché due rotte per router e non una sola. Se r1 conoscesse solo la rete B e non la C, un ping da r1 a (eth0 di r3) uscirebbe con "Network is unreachable". Il ritorno conta quanto l'andata: la risposta di r3 a r1 viene spedita verso l'indirizzo sorgente del ping (quello dell'interfaccia di r1 da cui è uscito) e anche r3 deve conoscere la rete di quell'indirizzo; con le due rotte di ogni router tutti i ritorni sono coperti.
Inoltro IP. Perché r2 inoltri un pacchetto da r1 a r3, in r2 l'inoltro IP deve essere attivo. Nelle macchine Katharà lo è già: lo si controlla con cat /proc/sys/net/ipv4/ip_forward (deve stampare 1); se stampasse 0 basterebbe echo 1 > /proc/sys/net/ipv4/ip_forward.
Alternativa con una sola riga per router. Poiché l'anello è un unico giro, basta una rotta predefinita verso il vicino "successivo": route add default gw 100.100.10.2 su r1, route add default gw 100.100.20.2 su r2, route add default gw 100.100.30.2 su r3, route add default gw 100.100.40.2 su r4 (r1→r2→r3→r4→r1). Funziona per tutti i ping tra le interfacce dell'esercizio (verificato), ma i percorsi sono asimmetrici e un indirizzo inesistente gira in cerchio fino a esaurire il TTL: la soluzione con due rotte per router è più pulita.
Verifica. Da ogni router:
ping -c 2 100.100.20.1 # r2 eth0 (e così via per tutti gli indirizzi non propri)
route -n # mostra la tabella: 2 rotte dirette + 2 statiche
traceroute 100.100.30.1 # da r1: un salto intermedio (r4), poi r3Il TTL di un ping non diretto (es. r1 → via r4) è : ogni router attraversato lo riduce di .
Esercizio 2: firewall sulla macchina srv
Perché si ragiona sulla porta : il web server ascolta sulla porta nota e il client usa una porta effimera qualsiasi come sorgente (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 →). Quindi le richieste hanno porta di destinazione e le risposte hanno porta sorgente : le due regole sotto sono simmetriche. L'obiettivo è una politica di default scarta tutto (DROP) sia per INPUT (pacchetti destinati a srv) sia per OUTPUT (pacchetti generati da srv), con due eccezioni: gli ingressi verso la porta e le uscite che sono risposte a quelle connessioni.
iptables --table filter --policy INPUT DROP # tutto ciò che entra in srv viene scartato per default
iptables --table filter --policy OUTPUT DROP # tutto ciò che esce da srv viene scartato per default
iptables --table filter --policy FORWARD DROP # srv non è un router: per completezza non inoltra nulla
# eccezione 1: richieste web in arrivo (da qualsiasi client, verso la porta TCP 80)
iptables --table filter --append INPUT --protocol tcp --destination-port 80 --jump ACCEPT
# eccezione 2: risposte web in uscita (pacchetti della connessione già stabilita, dalla porta 80)
iptables --table filter --append OUTPUT --protocol tcp --source-port 80 --match state --state ESTABLISHED,RELATED --jump ACCEPTSpiegazione delle righe:
--policy INPUT DROP/OUTPUT DROP: la politica predefinita si applica ai pacchetti che non corrispondono a nessuna regola. ConDROPil pacchetto viene scartato in silenzio (conREJECTsi manderebbe un messaggio ICMP di rifiuto).--append INPUT ... --destination-port 80 --jump ACCEPT: aggiunge in coda aINPUTuna regola che accetta i pacchetti TCP diretti alla porta , cioè le richieste HTTP al web server disrv.--append OUTPUT ... --source-port 80 --match state --state ESTABLISHED,RELATED: accetta in uscita solo i pacchetti TCP che partono dalla porta e appartengono a una connessione già aperta da un client (lo statoESTABLISHEDlo ricorda il kernel). Senza la condizione di stato,srvpotrebbe anche aprire connessioni verso l'esterno dalla porta .
Versione più stretta (lo stato anche sulla regola di ingresso: solo pacchetti che aprono la connessione o la proseguono):
iptables --table filter --append INPUT --protocol tcp --destination-port 80 --match state --state NEW,ESTABLISHED --jump ACCEPT
iptables --table filter --append OUTPUT --protocol tcp --source-port 80 --match state --state ESTABLISHED --jump ACCEPTInterfaccia loopback. Il testo chiede che tutto sia scartato tranne il web: non serve accettare lo. (Se un programma di srv parlasse con se stesso, per esempio con curl http://localhost, servirebbe --append INPUT --in-interface lo --jump ACCEPT e la corrispondente regola in OUTPUT; qui non serve.)
Verifica (dalla macchina pc, e controllando le regole su srv):
# su pc
wget -qO- http://100.100.100.254 # deve rispondere con la pagina di benvenuto (HTTP passa)
ping -c 2 100.100.100.254 # nessuna risposta: l'ICMP è scartato
ssh root@100.100.100.254 # si blocca: la porta 22 è scartata (SSH è attivo ma filtrato)
# su srv
iptables --table filter --list --numeric --verbose # regole e contatori: i pacchetti della prova compaiono accanto alle regoleI contatori mostrano quanti pacchetti ha riconosciuto ogni regola: dopo la prova la regola di INPUT sulla porta e quella di OUTPUT hanno contatori non nulli, mentre i pacchetti del ping (ICMP) e di SSH sono fermati dalla politica DROP.
Salvataggio. Nell'esame le istruzioni su come salvare il lavoro vengono date in aula. Per far sì che il firewall si riapplichi a ogni avvio del laboratorio, si possono incollare le righe iptables in srv.startup (dopo service apache2 restart).
Errori comuni
- Esercizio 1: mettere il prossimo salto sbagliato (per esempio su r1: è il suo indirizzo, non quello del vicino): il comando
route addfallisce, perché il prossimo salto deve essere in una rete collegata. - Esercizio 1: aggiungere rotte solo per l'andata: il ping non risponde perché manca la rotta di ritorno.
- Esercizio 1: dimenticare di verificare tutti gli indirizzi: ogni router ha due interfacce e ciascun indirizzo va provato da ogni altra macchina.
- Esercizio 2: impostare la politica
DROPprima di aggiungere le eccezioni su una sessione remota (SSH) e chiudersi fuori: nell'esame si lavora dal terminale della macchina, ma l'ordine "politica, eccezioni" va comunque seguito con attenzione. - Esercizio 2: accettare in
OUTPUTtutto il traffico dalla porta senza lo stato: non protegge le uscite. - Esercizio 2: controllare il risultato solo con il ping: il ping deve fallire, mentre
wgetocurlalla porta deve riuscire.
(Verificato con una simulazione in Python dell'esercizio 1: con le otto rotte statiche, e anche con le quattro rotte predefinite orarie, ogni indirizzo è raggiungibile da ogni router e le risposte tornano.)
Versione ripasso
Esame di laboratorio. Katharà: source ./kathara.sh, cd exercise1, lstart; alla fine lclean e lwipe. (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 →)
Esercizio 1 (anello di r1–r2–r3–r4, reti , , , tutte ): su ogni router due rotte per le due reti lontane, route add -net <rete>/24 gw <next hop> dev <ethX>. (Routing statico in KatharàLaboratorio 2 (LAB2). Due LAN (195.11.14.0/24 e 200.1.1.0/24) sono unite da due router r1 e r2 collegati da una rete 100.0.0.8/30. Una interfaccia attiva inserisce da sola nella tabella di instradamento solo la rete direttamente collegata: per le altre servono rotte inserite a mano. I PC usano una rotta predefinita (route add default gw 195.11.14.1), i router rotte statiche (route add -net 195.11.14.0/24 gw 100.0.0.9 dev eth1). Senza la rotta di ritorno su r2 le richieste di ping arrivano ma le risposte no: la raggiungibilità vale solo se c'è un percorso in entrambi i versi. A configurazione finita ping da pc1 a pc2 risponde con ttl=62 (64 meno 2 router).Routing statico in Katharà →)
- r1: B via (
eth0), C via (eth1). - r2: C via (
eth0), D via (eth1). - r3: A via (
eth1), D via (eth0). - r4: A via (
eth0), B via (eth1). - Verifica:
pinga tutte le interfacce,route -n; TTL via un router. Errore tipico: rotte solo per l'andata; next hop non collegato.
--policy INPUT DROP,--policy OUTPUT DROP(eFORWARD DROP).INPUT:--protocol tcp --destination-port 80 --jump ACCEPT.OUTPUT:--protocol tcp --source-port 80 --match state --state ESTABLISHED,RELATED --jump ACCEPT.- Verifica: da
pcwgetalla porta riesce,pingesshno;iptables --list --numeric --verbosemostra i contatori.