- Una DMZ e' una zona di mezzo: esposta verso internet, isolata dalla LAN
- Due firewall significa che anche se Sofia/nginx viene compromessa, Giulia/MySQL e' ancora protetta da FW2
- Su ASA il traffico da security-level basso verso alto e' bloccato per default - non serve scrivere nessuna regola di blocco
▶ $ history
nameif- assegna nome logico all'interfaccia ASA (outside, dmz, inside)security-level- livello di fiducia: 0=esterno, 50=DMZ, 100=LANroute outside 0.0.0.0 0.0.0.0 x.x.x.x- default route su ASAshow nameif- interfacce ASA con security level
Perche' questo lab#
corsobitcoin.com e' una piattaforma di corsi online. Ha iscritti, sessioni, video, dati di pagamento.
- Sofia/nginx e' il web server nella DMZ. Riceve le richieste HTTP, serve il frontend, interroga il database.
- Giulia/MySQL e' il database nella LAN privata. Non deve essere mai raggiungibile da internet.
Browser studente
| GET /lezioni/bitcoin-101 HTTP/1.1
FW1 <- vede solo HTTP/HTTPS sulla porta 80/443
|
Sofia/nginx <- verifica la sessione, chiede al DB
| SELECT * FROM lezioni WHERE user_id=99
FW2 <- vede solo MySQL sulla porta 3306 da Sofia
|
Giulia/MySQL <- risponde con i dati della lezioneSe un attaccante compromette Sofia/nginx, FW2 blocca tutto tranne MySQL sulla 3306. Il danno rimane nella DMZ. Questo e' il motivo per cui esistono due firewall.
La topologia#

| Dispositivo | Ruolo |
|---|---|
| PC-Kali | attaccante esterno, simula internet |
| SW-EXT | switch zona esterna, VLAN 10 |
| FW1 (ASA 5506-X) | primo firewall, outside(sec:0) e dmz(sec:50) |
| SW-DMZ | switch DMZ, VLAN 20 |
| Sofia/nginx | web server nella DMZ |
| FW2 (ASA 5506-X) | secondo firewall, dmz(sec:50) e inside(sec:100) |
| SW-LAN | switch LAN interna, VLAN 30 |
| Giulia/MySQL | database nella LAN privata |
Riferimento rapido#
FW1
Gig1/1 outside sec:0 10.0.0.2/30 -> Kali
Gig1/2 dmz sec:50 10.10.10.1/29 -> SW-DMZ
FW2
Gig1/1 dmz sec:50 10.10.10.3/29 -> SW-DMZ
Gig1/2 inside sec:100 10.30.30.1/30 -> SW-LAN
HOSTS
Kali 10.0.0.1/30 gw: 10.0.0.2
Sofia/nginx 10.10.10.2/29 gw: 10.10.10.1
Giulia/MySQL 10.30.30.2/30 gw: 10.30.30.1
ROTTE
FW1: route outside 0.0.0.0 0.0.0.0 10.0.0.1
FW1: route dmz 10.30.30.0 255.255.255.252 10.10.10.3
FW2: route dmz 0.0.0.0 0.0.0.0 10.10.10.1Il security-level indica quanto mi fido di quella zona, non quanto traffico passa.
- security 0 = non mi fido di nessuno che viene da li
- security 50 = fiducia parziale
- security 100 = mi fido completamente
La regola e': il traffico fluisce liberamente da chi e' piu' fidato verso chi e' meno fidato. Da 100 verso 0 passa. Da 0 verso 100 e' bloccato.
Quindi security 0 su outside non significa "passa tutto" - significa "non mi fido di nessuno che arriva da outside". E' la zona piu' pericolosa.
Schema IP#
| Zona | VLAN | Subnet | Dispositivo | IP |
|---|---|---|---|---|
| Esterna | 10 | 10.0.0.0/30 | PC-Kali | 10.0.0.1 |
| Esterna | 10 | 10.0.0.0/30 | FW1 outside | 10.0.0.2 |
| DMZ | 20 | 10.10.10.0/29 | FW1 dmz | 10.10.10.1 |
| DMZ | 20 | 10.10.10.0/29 | Sofia/nginx | 10.10.10.2 |
| DMZ | 20 | 10.10.10.0/29 | FW2 dmz | 10.10.10.3 |
| LAN | 30 | 10.30.30.0/30 | FW2 inside | 10.30.30.1 |
| LAN | 30 | 10.30.30.0/30 | Giulia/MySQL | 10.30.30.2 |
La DMZ usa /29 (6 host utili) perche' ci sono tre dispositivi: FW1, Sofia/nginx e FW2.
FW1 - configurazione#
Su ASA ogni interfaccia ha un nome logico (nameif) e un livello di sicurezza (security-level). Non basta ip address come sui router. Il security-level e' il cuore dell'ASA: decide in automatico cosa bloccare e cosa lasciar passare, senza che io scriva una sola regola.
| nameif | security-level | Significato | Traffico in uscita |
|---|---|---|---|
| outside | 0 | non mi fido di nessuno che viene da qui | bloccato verso DMZ e LAN (sale di livello) |
| dmz | 50 | zona semi-fidata, esposta a internet | passa verso outside (scende), bloccato verso LAN (sale) |
| inside | 100 | zona completamente fidata | passa verso DMZ e outside (scende sempre) |
Il security-level non indica quanto traffico passa - indica quanto mi fido di quella zona. Il traffico fluisce liberamente solo scendendo di livello (da 100 verso 0). Salire di livello e' sempre bloccato per default.
# entra in modalita' privilegiata - necessario per modificare la configurazione
enable
# entra in modalita' configurazione globale
conf t
# seleziona l'interfaccia fisica collegata a SW-EXT (verso Kali)
interface GigabitEthernet1/1
# assegna il nome logico "outside" - da questo momento ASA sa che questa e'
# la zona non fidata. Tutte le ACL e le rotte usano questo nome, non Gig1/1
nameif outside
# imposta il livello di fiducia a 0: il piu' basso possibile.
# il traffico da questa interfaccia verso zone con security-level piu' alto
# sara' bloccato per default
security-level 0
# assegna l'IP su questa interfaccia. /30 perche' il link verso Kali
# ha solo due host: Kali (10.0.0.1) e FW1 (10.0.0.2)
ip address 10.0.0.2 255.255.255.252
# le interfacce ASA nascono spente (shutdown). Senza questo comando
# l'interfaccia e' fisicamente attiva ma non processa traffico
no shutdownAppena scrivo nameif outside l'ASA risponde:
INFO: Security level for "outside" set to 0 by default.Lo sa gia' che outside = 0. La riga security-level 0 e' ridondante, ma la scrivo per capire cosa sta succedendo.
Compare anche Waiting for the earlier webvpn instance to terminate - artefatto di Packet Tracer, non un errore. Si ignora.
# seleziona l'interfaccia fisica collegata a SW-DMZ (verso Sofia/nginx e FW2)
interface GigabitEthernet1/2
# nome logico "dmz" - la zona di mezzo. Sofia/nginx sta qui
nameif dmz
# livello 50: piu' alto di outside (0), piu' basso di inside (100).
# Sofia/nginx puo' rispondere verso Kali (da 50 verso 0: permesso).
# Kali non puo' entrare nella DMZ senza una regola esplicita (da 0 verso 50: bloccato)
security-level 50
# /29 perche' nella DMZ ci sono tre dispositivi: FW1 (10.10.10.1),
# Sofia/nginx (10.10.10.2) e FW2 (10.10.10.3). Il /30 avrebbe solo 2 host
ip address 10.10.10.1 255.255.255.248
no shutdown
# torna in modalita' configurazione globale per aggiungere le rotte
exit
# default route: tutto quello che FW1 non conosce lo manda verso Kali (10.0.0.1).
# "outside" e' il nameif dell'interfaccia da cui uscire
route outside 0.0.0.0 0.0.0.0 10.0.0.1
# rotta specifica: per raggiungere la LAN (10.30.30.0/30) chiedi a FW2 (10.10.10.3).
# FW1 non e' direttamente collegato alla LAN - deve passare per FW2
route dmz 10.30.30.0 255.255.255.252 10.10.10.3La sezione Routing non esiste nella GUI per l'ASA in Packet Tracer. Per verificare: show route da CLI.
FW2 - configurazione#
FW2 e' il secondo firewall - quello che protegge Giulia/MySQL dalla DMZ. Ha due interfacce: una nella DMZ e una nella LAN. Ogni interfaccia ha il suo IP, il suo nome logico e il suo security-level.
# entra in modalita' privilegiata, come su FW1
enable
# entra in modalita' configurazione globale
conf t
# seleziona la prima porta fisica di FW2 - quella collegata a SW-DMZ.
# attenzione: e' sempre Gig1/1 perche' e' la prima porta del firewall,
# ma stavolta non e' la porta esterna - e' la porta verso la DMZ
interface GigabitEthernet1/1
# questa interfaccia si affaccia sulla DMZ - stessa zona di FW1 Gig1/2.
# usiamo "dmz" come nameif per coerenza con FW1
nameif dmz
# livello 50: la DMZ e' semi-fidata. Sofia/nginx potrebbe essere compromessa,
# quindi non ci fidiamo ciecamente di tutto quello che arriva da li
security-level 50
# l'IP di FW2 nella DMZ. e' il terzo host della subnet 10.10.10.0/29:
# 10.10.10.1 = FW1, 10.10.10.2 = Sofia/nginx, 10.10.10.3 = FW2 (questo)
# quando FW1 deve mandare traffico verso la LAN, lo spedisce a questo indirizzo
ip address 10.10.10.3 255.255.255.248
no shutdown
# seleziona la seconda porta fisica - quella collegata a SW-LAN verso Giulia/MySQL
interface GigabitEthernet1/2
# questa interfaccia si affaccia sulla LAN interna - zona completamente fidata
nameif inside
# livello 100: il massimo. il traffico da inside verso dmz passa liberamente
# (scende da 100 a 50). il traffico da dmz verso inside e' bloccato per default
# (salirebbe da 50 a 100) - serve una ACL esplicita per aprirlo
security-level 100
# l'IP di FW2 nella LAN. /30 perche' ci sono solo due host:
# FW2 (10.30.30.1) e Giulia/MySQL (10.30.30.2)
ip address 10.30.30.1 255.255.255.252
no shutdown
# torna in modalita' configurazione globale per aggiungere la rotta
exit
# default route di FW2: tutto quello che non conosce va verso FW1 (10.10.10.1).
# FW2 non sa niente di internet - sa solo che per uscire deve passare da FW1.
# "dmz" e' il nameif dell'interfaccia da cui uscire per raggiungere FW1
route dmz 0.0.0.0 0.0.0.0 10.10.10.1FW2 ha una sola rotta perche' non ha bisogno di sapere altro: tutto cio' che non e' nella sua LAN esce verso FW1. E' FW1 che sa come raggiungere internet.

Il show running-config conferma: Gig1/1 nameif dmz sec:50, Gig1/2 nameif inside sec:100. Le interfacce Gig1/3 e successive sono shutdown - porte fisiche non collegate, le ignoriamo.
Host - configurazione IP#
Desktop -> IP Configuration su ogni PC.
PC-Kali:
IP: 10.0.0.1 Mask: 255.255.255.252 GW: 10.0.0.2Sofia/nginx:
IP: 10.10.10.2 Mask: 255.255.255.248 GW: 10.10.10.1Giulia/MySQL:
IP: 10.30.30.2 Mask: 255.255.255.252 GW: 10.30.30.1VLAN - configurazione switch#
Senza VLAN tutto e' sulla VLAN 1 di default - Kali, Sofia/nginx e Giulia/MySQL sarebbero sullo stesso broadcast domain. Chiunque potrebbe vedere il traffico di chiunque a livello 2. Le VLAN creano l'isolamento fisico che i firewall da soli non garantiscono.
Le VLAN proteggono da te stesso e dai tuoi colleghi. Il firewall protegge da internet.
SW-EXT - VLAN 10#

# entra in modalita' privilegiata
enable
# entra in modalita' configurazione globale
conf t
# seleziona la porta fisica Fa0/1 - quella collegata a PC-Kali
interface FastEthernet0/1
# imposta la porta in modalita' access: significa che questa porta
# appartiene a una sola VLAN e i frame che escono non hanno il tag 802.1Q.
# il PC collegato non sa di essere in una VLAN - la gestisce lo switch
switchport mode access
# assegna questa porta alla VLAN 10.
# il messaggio "Access VLAN does not exist. Creating vlan 10" e' normale:
# la VLAN non esisteva ancora, lo switch la crea automaticamente
switchport access vlan 10
exit
# seleziona la porta Fa0/2 - quella collegata a FW1 (Gig1/1 outside)
interface FastEthernet0/2
switchport mode access
# stessa VLAN 10: Kali e FW1 sono nella stessa zona esterna
# e devono vedersi a livello 2
switchport access vlan 10
exit
# esci da config per usare show (show non funziona in modalita' config)
exit
# mostra un riepilogo di tutte le VLAN configurate sullo switch e le porte assegnate
show vlan briefL'output di show vlan brief conferma:
- VLAN 10 attiva con
Fa0/1eFa0/2- Kali e FW1 isolati nella loro zona - VLAN 1 default con tutte le altre porte - non collegate a niente di rilevante
Le VLAN 1002-1005 sono VLAN di sistema di Cisco, si ignorano.

Questa tabella mostra una cosa importante: la VLAN e' associata alla porta dello switch, non al PC.
Fa0/1 VLAN 10 MAC 0010.11D1.C901 <- Kali, in VLAN 10 senza saperlo
Fa0/2 VLAN 10 MAC 0010.11D1.C902 <- FW1 outside, stessa VLAN
Fa0/3 VLAN 1 MAC 0010.11D1.C903 <- PC intruso, VLAN 1 di defaultKali non ha nessuna configurazione VLAN. Non sa di essere in VLAN 10. E' lo switch che tiene traccia di quale porta appartiene a quale VLAN. Quando un frame arriva su Fa0/1, lo switch sa che quella porta e' VLAN 10 e tratta il frame di conseguenza.
Il match non e' tra MAC e VLAN - e' tra porta fisica e VLAN. Il MAC serve allo switch per sapere dove inoltrare il frame all'interno della stessa VLAN, non per decidere a quale VLAN appartiene.
Test VLAN: dimostrare l'isolamento#
Per dimostrare che la VLAN isola davvero ho aggiunto un PC intruso allo SW-EXT su una porta non configurata (Fa0/3). Questa porta rimane sulla VLAN 1 di default - non l'ho assegnata alla VLAN 10.

Il PC intruso ha un IP nella stessa subnet di Kali:
PC intruso: 10.0.0.100/24 gw: 10.0.0.2
Kali: 10.0.0.1/24 gw: 10.0.0.2Stessa subnet, stesso gateway, stesso switch fisico. In una rete senza VLAN si vedrebbero.
Ping dal PC intruso verso Kali: request time out.

Perche' non passa:
PC intruso (Fa0/3, VLAN 1)
|
| frame ARP: "chi ha 10.0.0.1?"
v
SW-EXT
|
| guarda la porta di ingresso: Fa0/3 = VLAN 1
| guarda le porte di destinazione: Fa0/1 = VLAN 10, Fa0/2 = VLAN 10
| VLAN 1 != VLAN 10 --> DROP
v
[frame eliminato, non inoltrato]
Kali (Fa0/1, VLAN 10) non riceve niente.
PC intruso non riceve risposta ARP.
Ping: request time out.Lo switch non guarda l'IP di destinazione. Non guarda il MAC. Guarda da quale porta arriva il frame e su quale VLAN e' quella porta. Se la VLAN di ingresso e la VLAN di destinazione non coincidono, il frame non esiste.
Nota importante: in Simulation mode di Packet Tracer bisogna attivare il filtro ARP altrimenti il pacchetto non e' visibile nell'animazione - ARP e' il primo passo del ping (il PC cerca il MAC di Kali prima di mandare ICMP).
SW-LAN - VLAN 30#

# entra in modalita' privilegiata
enable
# entra in modalita' configurazione globale
conf t
# seleziona la porta Fa0/1 - quella collegata a FW2 inside (Gig1/2)
# FW2 e' il guardiano della LAN: tutto il traffico verso Giulia/MySQL
# passa fisicamente da questa porta
interface FastEthernet0/1
# imposta la porta in modalita' access: un solo dispositivo collegato,
# un solo VLAN, nessun tag 802.1Q nel frame. FW2 non sa di essere in VLAN 30
switchport mode access
# assegna questa porta alla VLAN 30.
# la VLAN 30 non esisteva ancora: lo switch la crea automaticamente
# ("Access VLAN does not exist. Creating vlan 30" e' normale)
switchport access vlan 30
exit
# seleziona la porta Fa0/2 - quella collegata a Giulia/MySQL
interface FastEthernet0/2
switchport mode access
# stessa VLAN 30: FW2 inside e Giulia/MySQL devono vedersi a livello 2.
# senza questo, il ping di Giulia verso FW2 fallisce gia' allo switch -
# il frame non viene inoltrato perche' le porte sono su VLAN diverse
switchport access vlan 30
exit
# esci da config per usare show (show non funziona in modalita' config)
exit
# verifica: mostra tutte le VLAN attive e le porte assegnate
show vlan briefOutput:
VLAN 30 VLAN0030 active Fa0/1, Fa0/2FW2 inside e Giulia/MySQL nella stessa VLAN 30. La LAN e' isolata - nessun dispositivo di altre zone puo' raggiungerla a livello 2.
SW-DMZ - VLAN 20#
Stessa logica di SW-EXT, zona diversa. Nella DMZ ci sono tre dispositivi collegati allo switch: FW1 (Gig1/2 dmz), Sofia/nginx e FW2 (Gig1/1 dmz). Tutti e tre devono essere nella stessa VLAN 20 per parlarsi a livello 2 - il firewall FW1 e FW2 devono raggiungere Sofia/nginx attraverso lo switch DMZ.
# entra in modalita' privilegiata
enable
# entra in modalita' configurazione globale
conf t
# seleziona la porta Fa0/1 - quella collegata a FW1 (Gig1/2, interfaccia dmz)
interface FastEthernet0/1
# access port: questa porta appartiene a una sola VLAN.
# FW1 non sa di essere in VLAN 20 - e' lo switch che lo gestisce
switchport mode access
# assegna alla VLAN 20.
# come prima, se la VLAN 20 non esiste lo switch la crea automaticamente
switchport access vlan 20
exit
# seleziona la porta Fa0/2 - quella collegata a Sofia/nginx
interface FastEthernet0/2
switchport mode access
# stessa VLAN 20: FW1, Sofia/nginx e FW2 devono vedersi a livello 2
# per poter instradare il traffico attraverso la DMZ
switchport access vlan 20
exit
# seleziona la porta Fa0/3 - quella collegata a FW2 (Gig1/1, interfaccia dmz)
interface FastEthernet0/3
switchport mode access
# FW2 e' nella stessa DMZ di FW1 e Sofia/nginx - stessa VLAN 20.
# quando Sofia/nginx manda una richiesta MySQL verso Giulia, il frame
# passa prima da SW-DMZ e arriva a FW2, che poi decide se lasciarlo passare
switchport access vlan 20
exit
# esci da config per usare show
exit
# verifica: mostra VLAN attive e le porte assegnate
show vlan briefOutput atteso:
VLAN Name Status Ports
20 VLAN0020 active Fa0/1, Fa0/2, Fa0/3Tre porte, una sola VLAN. FW1, Sofia/nginx e FW2 condividono il broadcast domain della DMZ - si vedono a livello 2, ma il firewall controlla cosa possono dirsi a livello 3 e superiori.
Security-level: chi puo' parlare con chi#
Ogni dispositivo eredita il security-level dell'interfaccia del firewall da cui e' raggiungibile:
Kali → entra/esce da FW1 outside → sec:0
Sofia/nginx → entra/esce da FW1 dmz → sec:50
Giulia/MySQL → entra/esce da FW2 inside → sec:100La regola e' una sola: il numero sale = bloccato. Il numero scende = passa.
| Ping | Direzione | Risultato | Perche' |
|---|---|---|---|
| Kali → Sofia/nginx | 0 → 50 | BLOCCATO | sale di livello |
| Sofia/nginx → Kali | 50 → 0 | PASSA | scende di livello |
| Sofia/nginx → Giulia/MySQL | 50 → 100 | BLOCCATO | sale di livello |
| Giulia/MySQL → Sofia/nginx | 100 → 50 | PASSA | scende di livello |
Nessuna regola scritta. L'ASA blocca e permette in automatico solo guardando da quale interfaccia entra il pacchetto e da quale dovrebbe uscire.
Il modello reale e' questo: il database puo' rispondere a Sofia, ma Sofia non puo' aprire una connessione spontanea verso Giulia/MySQL senza un permesso esplicito. Un dispositivo non fidato non entra mai in una zona piu' fidata per sua iniziativa.
Per aprire traffico che sale di livello serve una ACL esplicita - lo faremo quando configureremo HTTP verso Sofia e MySQL da Sofia verso Giulia.
Ping matrix - chi raggiunge chi e perche'#
Prima di aprire qualsiasi ACL, mappo il comportamento di default della rete. Ogni ping racconta qualcosa di diverso: la VLAN, il firewall, il security-level, il routing.
Test 1 - Kali → FW1 outside#
| Mittente | PC-Kali 10.0.0.1 |
| Destinazione | FW1 outside 10.0.0.2 |
| Risultato | FUNZIONA |
# da PC-Kali: Desktop → Command Prompt
ping 10.0.0.2Nessun firewall da attraversare. Kali e FW1 outside sono sulla stessa subnet 10.0.0.0/30 e sulla stessa VLAN 10. Il frame non esce mai dallo switch SW-EXT. E' il test piu' basico - se fallisce c'e' un errore nella configurazione IP o VLAN.
Test 2 - Kali → Sofia/nginx#
| Mittente | PC-Kali 10.0.0.1 (sec:0) |
| Destinazione | Sofia/nginx 10.10.10.2 (sec:50) |
| Risultato | FALLISCE (prima dell'ACL) → FUNZIONA (dopo ACL su FW1) |
# da PC-Kali
ping 10.10.10.2Il pacchetto arriva a FW1 sull'interfaccia outside (sec:0). La destinazione e' raggiungibile tramite l'interfaccia dmz (sec:50). ASA confronta:
ingresso sec:0 → uscita sec:50
0 < 50 → sale di livello → DROPQuesto e' il comportamento di default, senza ACL. Dopo aver configurato OUTSIDE_IN con il permit ICMP e TCP 80/443, il ping funziona. L'ACL sovrascrive il blocco del security-level per il traffico specifico che abbiamo autorizzato.
Test 3 - Kali → Giulia/MySQL#
| Mittente | PC-Kali 10.0.0.1 (sec:0) |
| Destinazione | Giulia/MySQL 10.30.30.2 (sec:100) |
| Risultato | FALLISCE |
# da PC-Kali
ping 10.30.30.2Il pacchetto non arriva nemmeno a FW2. Viene bloccato gia' da FW1: outside (sec:0) non puo' entrare nella dmz (sec:50). FW2 non vede niente.
Due firewall da attraversare, bloccato al primo.
Test 4 - Sofia/nginx → FW1 dmz#
| Mittente | Sofia/nginx 10.10.10.2 |
| Destinazione | FW1 dmz 10.10.10.1 |
| Risultato | FUNZIONA |
# da Sofia/nginx: Desktop → Command Prompt
ping 10.10.10.1Stessa subnet 10.10.10.0/29, stessa VLAN 20, stesso switch SW-DMZ. Il frame non esce mai dallo switch. Non attraversa nessun firewall.
Test 5 - Sofia/nginx → FW2 dmz#
| Mittente | Sofia/nginx 10.10.10.2 |
| Destinazione | FW2 dmz 10.10.10.3 |
| Risultato | FUNZIONA |
# da Sofia/nginx
ping 10.10.10.3Stessa subnet, stessa VLAN 20, stesso switch SW-DMZ. FW1, Sofia/nginx e FW2 sono tutti e tre nella stessa zona DMZ a livello 2.
Test 6 - Sofia/nginx → Kali#
| Mittente | Sofia/nginx 10.10.10.2 (sec:50) |
| Destinazione | PC-Kali 10.0.0.1 (sec:0) |
| Risultato | FUNZIONA |
# da Sofia/nginx
ping 10.0.0.1Direzione inversa del test 2. Il pacchetto entra in FW1 dalla dmz (sec:50) e deve uscire dalla outside (sec:0):
ingresso sec:50 → uscita sec:0
50 > 0 → scende di livello → PASSASofia/nginx puo' rispondere a Kali. La risposta torna, l'iniziativa da Kali no.
Test 7 - Sofia/nginx → Giulia/MySQL#
| Mittente | Sofia/nginx 10.10.10.2 (sec:50) |
| Destinazione | Giulia/MySQL 10.30.30.2 (sec:100) |
| Risultato | FALLISCE |
# da Sofia/nginx
ping 10.30.30.2Il pacchetto arriva a FW2 sull'interfaccia dmz (sec:50). La destinazione e' raggiungibile tramite inside (sec:100):
ingresso sec:50 → uscita sec:100
50 < 100 → sale di livello → DROPQuesto e' il muro piu' importante della topologia. Anche se Sofia/nginx venisse compromessa, non potrebbe aprire connessioni verso Giulia/MySQL. Il danno rimane nella DMZ.
Test 8 - Giulia/MySQL → FW2 inside#
| Mittente | Giulia/MySQL 10.30.30.2 |
| Destinazione | FW2 inside 10.30.30.1 |
| Risultato | FUNZIONA (dopo VLAN 30 su SW-LAN) |
# da Giulia/MySQL: Desktop → Command Prompt
ping 10.30.30.1Stessa subnet 10.30.30.0/30, nessun firewall da attraversare. Prima di configurare VLAN 30 su SW-LAN il ping falliva: le porte erano sulla VLAN 1 di default e il frame veniva droppato a L2. Dopo la configurazione di SW-LAN funziona.
Test 9 - Giulia/MySQL → Sofia/nginx#
| Mittente | Giulia/MySQL 10.30.30.2 (sec:100) |
| Destinazione | Sofia/nginx 10.10.10.2 (sec:50) |
| Risultato | FUNZIONA |
# da Giulia/MySQL
ping 10.10.10.2ingresso sec:100 → uscita sec:50
100 > 50 → scende di livello → PASSAIl database puo' iniziare connessioni verso la DMZ. Non e' il comportamento reale che vogliamo - ma e' quello di default dell'ASA. Le ACL che configureremo dopo limiteranno questo a solo MySQL sulla porta 3306.
ACL - aprire solo quello che serve#
Fino a qui la rete e' configurata ma inutile per il suo scopo reale: Kali non puo' raggiungere Sofia/nginx, Sofia/nginx non puo' raggiungere Giulia/MySQL. I firewall bloccano tutto il traffico che sale di security-level.
E' corretto. E' esattamente quello che volevamo. Ma ora dobbiamo aprire solo quello che serve - niente di piu'.
Cosa sono le ACL#
Una ACL (Access Control List) e' una lista di regole che dice al firewall: "questo traffico specifico puo' passare, anche se normalmente lo bloccheresti".
Senza ACL il firewall usa solo il security-level: alto verso basso passa, basso verso alto no. Le ACL aggiungono precisione chirurgica: non "apri tutta la DMZ a Kali", ma "apri solo la porta 80 e 443 di Sofia/nginx a chiunque venga da outside".
La logica e' sempre la stessa: nega tutto per default, poi apri solo quello che sai essere necessario. E' il principio del minimo privilegio applicato al traffico di rete.
Perche' sono indispensabili#
Senza ACL la rete ha due stati possibili:
- traffico bloccato - sicuro ma inutile. Sofia/nginx non e' raggiungibile da nessuno.
- traffico aperto - accessibile ma senza controllo. Kali potrebbe fare qualsiasi cosa su qualsiasi porta.
Le ACL sono il punto di mezzo: il traffico che serve passa, tutto il resto no. E' la differenza tra un cancello chiuso a chiave e un cancello aperto - le ACL sono la serratura che lascia passare solo chi ha la chiave giusta.
L'obiettivo#
Vogliamo replicare esattamente il modello di corsobitcoin.com:
Browser studente (Kali)
|
| HTTP porta 80 / HTTPS porta 443 <- aperto da ACL su FW1
v
Sofia/nginx (DMZ)
|
| MySQL porta 3306 <- aperto da ACL su FW2
v
Giulia/MySQL (LAN)Due ACL, due firewall, due porte specifiche. Tutto il resto rimane bloccato:
- Kali non puo' fare SSH a Sofia/nginx (porta 22 non aperta)
- Kali non puo' raggiungere Giulia/MySQL in nessun modo (bloccato gia' a FW1)
- Sofia/nginx non puo' aprire connessioni arbitrarie verso Giulia/MySQL (solo 3306)
- Giulia/MySQL non puo' iniziare connessioni verso la DMZ (lo aggiungeremo nell'ACL di FW2)
ACL su FW1 - HTTP e HTTPS verso Sofia/nginx#
Se stessi facendo questo lab su Linux invece di Packet Tracer, a questo punto avresti:
- namespace separati per ogni zona (outside, dmz, lan)
iptablescon policy DROP di default al posto del security-level ASA- nginx installato nel namespace DMZ - solo nginx, ancora nessun MySQL
- le regole iptables equivalenti alle ACL che stiamo per scrivere:
# Linux equivalente di "apri HTTP verso Sofia/nginx" # iptables: iptables -A FORWARD -i eth-outside -o eth-dmz -p tcp --dport 80 -j ACCEPT iptables -A FORWARD -i eth-outside -o eth-dmz -p tcp --dport 443 -j ACCEPT # ufw: ufw route allow proto tcp from any to 10.10.10.2 port 80 ufw route allow proto tcp from any to 10.10.10.2 port 443 # ASA fa la stessa cosa con: access-list OUTSIDE_IN permit tcp any host 10.10.10.2 eq 80 access-list OUTSIDE_IN permit tcp any host 10.10.10.2 eq 443La differenza: su Linux le regole vivono sul server stesso - se nginx viene compromessa, l'attaccante ha accesso a iptables. Su ASA le regole stanno su hardware separato che l'attaccante non controlla.
# entra in modalita' configurazione globale
# iptables/ufw: non serve un "conf t", le regole si scrivono direttamente da shell
conf t
# permette TCP da qualsiasi sorgente verso Sofia/nginx (10.10.10.2) sulla porta 80 (HTTP).
# "any" = qualsiasi IP sorgente. "host" = un singolo IP specifico.
# iptables: iptables -A FORWARD -i eth-outside -o eth-dmz -p tcp -d 10.10.10.2 --dport 80 -j ACCEPT
# ufw: ufw route allow proto tcp from any to 10.10.10.2 port 80
access-list OUTSIDE_IN permit tcp any host 10.10.10.2 eq 80
# permette TCP verso la porta 443 (HTTPS).
# stessa logica della riga sopra ma per il traffico cifrato.
# iptables: iptables -A FORWARD -i eth-outside -o eth-dmz -p tcp -d 10.10.10.2 --dport 443 -j ACCEPT
# ufw: ufw route allow proto tcp from any to 10.10.10.2 port 443
access-list OUTSIDE_IN permit tcp any host 10.10.10.2 eq 443
# permette ICMP (ping) verso Sofia/nginx - utile per testare la connettivita'.
# in produzione questa riga si rimuove: non vuoi che chiunque da internet possa pingare il tuo server.
# iptables: iptables -A FORWARD -i eth-outside -o eth-dmz -p icmp -d 10.10.10.2 -j ACCEPT
# ufw: ufw route allow proto icmp from any to 10.10.10.2
access-list OUTSIDE_IN permit icmp any host 10.10.10.2
# applica la lista OUTSIDE_IN all'interfaccia "outside" in direzione inbound.
# "in" significa: controlla il traffico che ENTRA da outside verso il firewall.
# senza questo comando la lista esiste ma non viene usata.
# iptables: le regole FORWARD si applicano automaticamente alla chain, non serve un attach separato
# ufw: stesso - ufw route apply le regole subito, non serve un comando di attach
access-group OUTSIDE_IN in interface outside
exitRisultato: da PC-Kali ping 10.10.10.2 funziona. Il pacchetto attraversa FW1 perche' l'ACL OUTSIDE_IN lo permette esplicitamente. Prima dell'ACL veniva droppato dal security-level (sec:0 → sec:50). Ora la regola sovrascrive il comportamento di default.
Per verificare le ACL configurate e quante volte hanno fatto match:
show access-listaccess-list OUTSIDE_IN; 3 elements; name hash: 0xe9c9a254
access-list OUTSIDE_IN line 1 extended permit tcp any host 10.10.10.2 eq www (hitcnt=0)
access-list OUTSIDE_IN line 2 extended permit tcp any host 10.10.10.2 eq 443 (hitcnt=0)
access-list OUTSIDE_IN line 3 extended permit icmp any host 10.10.10.2 (hitcnt=3)Il campo hitcnt e' la prova che le regole funzionano: 3 pacchetti ICMP (i ping di test) hanno fatto match con la regola. HTTP e HTTPS sono a 0 perche' non c'e' ancora un vero web server su Sofia/nginx. Nota che Packet Tracer traduce porta 80 in www - e' la stessa cosa.
ACL su FW2 - MySQL verso Giulia/MySQL#
FW2 protegge Giulia/MySQL dalla DMZ. Senza ACL, Sofia/nginx non puo' aprire connessioni verso Giulia/MySQL - FW2 blocca tutto il traffico che sale da sec:50 a sec:100.
Vogliamo aprire solo MySQL (porta 3306) e solo da Sofia/nginx. Non da qualsiasi IP della DMZ - solo dall'IP specifico del web server.
# entra in modalita' privilegiata
# iptables/ufw: non serve, si scrive direttamente da shell con sudo
enable
# entra in modalita' configurazione globale
conf t
# permette TCP da Sofia/nginx (10.10.10.2) verso Giulia/MySQL (10.30.30.2) sulla porta 3306 (MySQL).
# a differenza di OUTSIDE_IN dove la sorgente era "any" (chiunque da internet),
# qui la sorgente e' un singolo IP specifico: solo Sofia/nginx puo' parlare con il database.
# un attaccante che compromette un altro dispositivo in DMZ non puo' raggiungere Giulia.
# iptables: iptables -A FORWARD -i eth-dmz -o eth-lan -p tcp -s 10.10.10.2 -d 10.30.30.2 --dport 3306 -j ACCEPT
# ufw: ufw route allow proto tcp from 10.10.10.2 to 10.30.30.2 port 3306
access-list DMZ_IN permit tcp host 10.10.10.2 host 10.30.30.2 eq 3306
# permette ICMP da Sofia/nginx verso Giulia/MySQL - per testare la connettivita'.
# come su FW1, in produzione questa riga si rimuove.
# iptables: iptables -A FORWARD -i eth-dmz -o eth-lan -p icmp -s 10.10.10.2 -d 10.30.30.2 -j ACCEPT
# ufw: ufw route allow proto icmp from 10.10.10.2 to 10.30.30.2
access-list DMZ_IN permit icmp host 10.10.10.2 host 10.30.30.2
# applica la lista DMZ_IN all'interfaccia "dmz" in direzione inbound.
# controlla il traffico che entra da Sofia/nginx verso FW2.
# iptables: le regole FORWARD si applicano automaticamente alla chain
# ufw: stesso - ufw route applica le regole subito
access-group DMZ_IN in interface dmz
exitTest: da Sofia/nginx ping 10.30.30.2 - funziona. Prima dell'ACL FW2 bloccava tutto (sec:50 → sec:100). Ora Sofia/nginx puo' raggiungere Giulia/MySQL solo su MySQL 3306 e ICMP.
Il percorso completo ora funziona:
Kali → FW1 (ACL OUTSIDE_IN: 80/443/icmp) → Sofia/nginx
Sofia/nginx → FW2 (ACL DMZ_IN: 3306/icmp) → Giulia/MySQLKali non raggiunge mai Giulia/MySQL direttamente. Passa obbligatoriamente da Sofia/nginx, che passa obbligatoriamente da FW2. Due checkpoint, due ACL, due porte specifiche.
Per verificare le ACL su FW2:
show access-listaccess-list DMZ_IN; 2 elements
access-list DMZ_IN line 1 extended permit tcp host 10.10.10.2 host 10.30.30.2 eq 3306 (hitcnt=0)
access-list DMZ_IN line 2 extended permit icmp host 10.10.10.2 host 10.30.30.2 (hitcnt=6)hitcnt=6 sulla riga ICMP - i ping di test da Sofia verso Giulia. hitcnt=0 su MySQL perche' non c'e' ancora un vero database in ascolto sulla 3306.
Nota: se compare una line 1 senza porta (permit tcp senza eq 3306) e' una riga troppo permissiva entrata per errore. Si rimuove con:
conf t
no access-list DMZ_IN extended permit tcp host 10.10.10.2 host 10.30.30.2
exitTest end-to-end#
Il percorso completo della rete. Ogni ping dimostra che un pezzo della catena funziona.
# Step 1 - da PC-Kali: raggiunge FW1 (stessa VLAN, no firewall)
ping 10.0.0.2
# Step 2 - da PC-Kali: raggiunge Sofia/nginx (attraversa FW1, ACL OUTSIDE_IN apre ICMP)
ping 10.10.10.2
# Step 3 - da Sofia/nginx: raggiunge Giulia/MySQL (attraversa FW2, ACL DMZ_IN apre ICMP)
ping 10.30.30.2Kali (10.0.0.1)
│
│ ping 10.0.0.2 ✓ (stessa VLAN 10, no firewall)
▼
FW1 outside (10.0.0.2)
│
│ ping 10.10.10.2 ✓ (ACL OUTSIDE_IN: permit icmp any host 10.10.10.2)
▼
Sofia/nginx (10.10.10.2)
│
│ ping 10.30.30.2 ✓ (ACL DMZ_IN: permit icmp host 10.10.10.2 host 10.30.30.2)
▼
Giulia/MySQL (10.30.30.2)Kali non raggiunge mai Giulia/MySQL direttamente. Ogni salto e' controllato da un firewall con una ACL specifica.
Nota: il ping da Kali verso Sofia/nginx potrebbe fallire al primo tentativo. E' normale - e' ARP che risolve il MAC address. Il secondo ping funziona sempre. In Packet Tracer questo comportamento e' piu' evidente che su hardware reale.
Cosa ho imparato#
Il security-level e' una politica, non un permesso. Dire security-level 0 non significa "blocca tutto" - significa "non mi fido di nessuno che viene da qui". Il blocco e' la conseguenza automatica quando il traffico tenta di salire di livello. Le ACL sono l'eccezione esplicita a quella politica.
Ogni dispositivo eredita il security-level del firewall da cui e' raggiungibile. Kali non e' a sec:0 perche' e' pericolosa - e' a sec:0 perche' si affaccia sull'interfaccia outside di FW1. Sofia/nginx e' a sec:50 perche' sta dietro l'interfaccia dmz. Giulia/MySQL e' a sec:100 perche' e' dietro inside di FW2. Il security-level e' geografico, non personale.
La VLAN isola a livello 2, il firewall a livello 3. Le VLAN impediscono che i frame si mescolino sullo stesso switch. Il firewall decide quali pacchetti possono attraversare zone diverse. Sono due meccanismi complementari: senza VLAN un dispositivo potrebbe bypassare il firewall a livello 2; senza firewall le VLAN non controllano il routing tra zone.
Le ACL si scrivono per differenza. Il default e' blocca tutto. Si aggiunge solo quello che serve: HTTP, HTTPS e ICMP su FW1 verso Sofia; MySQL e ICMP su FW2 verso Giulia. Ogni porta aperta e' una decisione consapevole, non un'eccezione dimenticata.
Due firewall significano due perimetri indipendenti. Se Sofia/nginx viene compromessa, FW2 blocca comunque tutto tranne MySQL 3306. Il danno rimane nella DMZ. Questo e' il motivo per cui esistono le screened subnet: non impedire l'attacco, ma limitare il blast radius quando l'attacco riesce.
Ricapitolando - quello che ho capito#
FW1 e FW2 insieme creano la DMZ. Non basta un firewall solo - con uno solo hai dentro e fuori. Con due hai dentro, mezzo e fuori. Il mezzo e' la DMZ: Sofia/nginx vive li, esposta a internet ma separata dal database.
Le VLAN separano il traffico a livello 2. Di default tutto e' sulla VLAN 1 - Kali, Sofia, Giulia si vedrebbero tutte sullo stesso switch come se fossero nella stessa stanza. Le VLAN mettono muri fisici: VLAN 10 per la zona esterna, VLAN 20 per la DMZ, VLAN 30 per la LAN. Un frame che entra su una porta VLAN 10 non esce mai su una porta VLAN 20. Lo switch lo droppa prima ancora che il firewall lo veda.
Il security-level non e' un permesso, e' una geografia. Kali e' a 0 perche' sta fuori. Sofia e' a 50 perche' sta nel mezzo. Giulia e' a 100 perche' sta dentro. Un numero basso non puo' mai raggiungere un numero alto da solo - deve salire, e salire e' bloccato per default. Giulia invece puo' raggiungere tutti perche' scende sempre.
Senza ACL il firewall e' tirato su ma inutile: Sofia non e' raggiungibile da nessuno. Le ACL aprono esattamente quello che serve e niente di piu'. HTTP e HTTPS su FW1 verso Sofia. MySQL su FW2 solo da Sofia verso Giulia - non da qualsiasi IP della DMZ, solo da quell'IP specifico.
Il risultato: Kali puo' parlare con Sofia sulla 80 e 443. Sofia puo' parlare con Giulia sulla 3306. Kali non raggiungera' mai Giulia direttamente - e' fisicamente impossibile senza passare da Sofia, e Sofia non ha il permesso di fare da tramite su nessun'altra porta.
Il prossimo lab: Linux namespaces#
La stessa identica topologia, senza hardware Cisco. In Linux ogni zona diventa un namespace - un processo isolato con le sue interfacce, le sue rotte, il suo stack di rete.
| Packet Tracer | Linux namespace |
|---|---|
| PC-Kali | Kali VM reale (192.168.64.200) |
| SW-EXT | veth pair (cavo virtuale, no namespace) |
| FW1 ASA | ns-fw1 con iptables al posto del security-level |
| SW-DMZ | veth pair |
| Sofia/nginx | ns-sofia con nginx installato |
| FW2 ASA | ns-fw2 con iptables |
| SW-LAN | veth pair |
| Giulia/MySQL | ns-giulia con netcat sulla 3306 |
Gli switch non diventano namespace - sono solo cavi virtuali (veth pair) che collegano i namespace. Le VLAN non si configurano esplicitamente: la separazione e' gia' nella struttura dei namespace, ogni veth pair e' gia' un segmento isolato.
Le ACL diventano regole iptables -A FORWARD. Il security-level diventa iptables -P FORWARD DROP. Stessa logica, sintassi diversa, nessun hardware dedicato.
Il WAF - quello che manca in questo lab#
In questo lab Packet Tracer Sofia/nginx e' solo un PC simulato. Il WAF (ModSecurity sopra nginx) non si puo' implementare qui - e' software reale che ispeziona il traffico HTTP a livello 7.
FW1 fa filtraggio di rete (L3/L4): vede TCP porta 80, non sa cosa c'e' dentro.
Il WAF fa filtraggio applicativo (L7): legge la request HTTP e blocca GET /etc/passwd o ' OR 1=1--.
Sono due difese complementari - una non sostituisce l'altra.
FW1 vede: TCP 10.0.0.1:54321 → 10.10.10.2:80 [PERMIT]
WAF vede: GET /login?id=' OR 1=1-- HTTP/1.1 [BLOCK - SQL injection]Nel lab Linux installeremo nginx + ModSecurity su ns-dmz e vedremo il WAF in azione con request reali.
Scarica il Laboratorio#
Vuoi smontare e rimontare questa rete con le tue mani? Ecco il file Packet Tracer bello e pronto:
⬇ Scarica il lab Packet Tracer (.pkt)



