Il lab precedente#
Nel Lab 04 abbiamo creato la topologia di rete. Ora la mettiamo in sicurezza.
iptables default DROP - il security-level#
Cisco: cisco-packet-tracer-dmz#FW1 - configurazione|FW1 - configurazione — su un ASA Cisco il traffico da zona a security-level piu' basso verso zona a security-level piu' alto e' bloccato per default. Nessuna ACL = nessun transito.
iptables -P FORWARD DROPe' la stessa policy: la chain e' vuota, tutto cade nella policy di default.
| Stato attuale | Obiettivo | Come | |
|---|---|---|---|
| Kali → Sofia :qualsiasi | ✓ PASS | ✗ DROP | -P FORWARD DROP su FW1 |
| Sofia → Giulia :qualsiasi | ✓ PASS | ✗ DROP | -P FORWARD DROP su FW2 |
| Kali → Giulia :qualsiasi | ✓ PASS | ✗ DROP | DROP su FW1 + FW2 in cascata |
# ns-fw1: blocca tutto il traffico in transito.
# equivalente di: access-group outside_access_in in interface outside (deny-all implicito)
sudo ip netns exec ns-fw1 iptables -P FORWARD DROP
# ns-fw2: LAN isolata per default.
# nessun pacchetto dalla DMZ raggiunge ns-giulia senza una regola esplicita
sudo ip netns exec ns-fw2 iptables -P FORWARD DROPVerifica immediata dopo il DROP — Kali non raggiunge piu' Sofia:
# da Kali VM
ping -c3 10.10.10.2
# 3 packets transmitted, 0 received, 100% packet lossVerifica su ns-fw1 — i pacchetti droppati sono contati dalla policy:
sudo ip netns exec ns-fw1 iptables -L FORWARD -v -n
# Chain FORWARD (policy DROP 3 packets, 252 bytes)La chain e' vuota — nessuna regola esplicita. I 3 pacchetti sono esattamente i 3 ping di Kali, droppati dalla policy di default. Non da una regola, dalla policy. Differenza importante: le regole esplicite (-A FORWARD) compaiono nella lista sopra la policy. La policy e' il catch-all finale per tutto quello che non matcha nessuna regola.
flowchart LR
classDef ext fill:#4a0d0d,stroke:#e05555,color:#eee
classDef fw fill:#3d0d0d,stroke:#ff4444,color:#eee
classDef dmz fill:#2d2010,stroke:#886633,color:#aaa
classDef lan fill:#0d1a0d,stroke:#336633,color:#aaa
KALI["Kali"]:::ext
FW1["ns-fw1
FORWARD DROP
chain vuota"]:::fw
SOFIA["ns-sofia
irraggiungibile"]:::dmz
FW2["ns-fw2
FORWARD DROP
chain vuota"]:::fw
GIULIA[("ns-giulia
irraggiungibile")]:::lan
KALI -. "qualsiasi traffico" .-> FW1
FW1 -. "✗ DROP — nessuna regola" .-> SOFIA
SOFIA -. "qualsiasi traffico" .-> FW2
FW2 -. "✗ DROP — nessuna regola" .-> GIULIA
Isolamento namespace - il test equivalente alle VLAN#
Cisco: su un ASA con security-level configurati, un PC nella LAN non puo' raggiungere la DMZ senza una
access-listesplicita — anche se conosce il percorso. Stesso principio: la policy DROP blocca il transito indipendentemente dal routing.
Tre test dopo iptables -P FORWARD DROP su ns-fw1 e ns-fw2:
ns-giulia → ns-sofia (10.10.10.2)#
sudo ip netns exec ns-giulia ping -c3 10.10.10.2
# 3 packets transmitted, 0 received, 100% packet lossIl pacchetto parte da ns-giulia verso il default gateway ns-fw2 (10.30.30.1). ns-fw2 dovrebbe instradarlo verso la DMZ — ma la FORWARD chain di ns-fw2 ha policy DROP. Il pacchetto viene silenziosamente scartato.
mindmap
root((ns-giulia a ns-sofia))
Percorso tentato
ns-giulia a ns-fw2 default gw
ns-fw2 dovrebbe forwardare a DMZ
Risultato DROP
FORWARD chain ns-fw2 policy DROP
Scartato silenziosamente
ns-sofia → ns-giulia (10.30.30.2)#
sudo ip netns exec ns-sofia ping -c3 10.30.30.2
# From 10.10.10.1: icmp_seq=1 Redirect Host(New nexthop: 10.10.10.3)
# From 10.10.10.1: icmp_seq=2 Redirect Host(New nexthop: 10.10.10.3)
# From 10.10.10.1: icmp_seq=3 Redirect Host(New nexthop: 10.10.10.3)
# 3 packets transmitted, 0 received, 100% packet lossns-fw1 manda ancora l'ICMP Redirect (vedi Linux-namespaces-dmz#Test 7 - ns-sofia → ns-giulia|Test 7) suggerendo a Sofia di andare direttamente a ns-fw2. Sofia ci prova — ma ns-fw2 riceve il pacchetto sulla sua interfaccia DMZ e deve instradarlo verso la LAN: FORWARD chain → DROP. Il redirect e' inutile se il firewall successivo blocca comunque.
mindmap
root((ns-sofia a ns-giulia))
ICMP Redirect da ns-fw1
ns-fw1 suggerisce nexthop ns-fw2
Risultato DROP
ns-fw2 FORWARD chain DROP
Redirect inutile se FW blocca
ns-fw1 → ns-sofia (10.10.10.2)#
sudo ip netns exec ns-fw1 ping -c3 10.10.10.2
# 64 bytes from 10.10.10.2: icmp_seq=1 ttl=64 time=0.081 ms
# 3 packets transmitted, 3 received, 0% packet lossFunziona — TTL=64, nessun drop. ns-fw1 e' il mittente del pacchetto, non un router di transito. La FORWARD chain si applica solo ai pacchetti che attraversano il namespace da un'interfaccia all'altra. Un pacchetto originato dal namespace stesso passa per la chain OUTPUT, non FORWARD.
| Test | Percorso | Chain coinvolta | Risultato |
|---|---|---|---|
| ns-giulia → ns-sofia | ns-fw2 deve forwardare | FORWARD ns-fw2 | DROP |
| ns-sofia → ns-giulia | ns-fw2 deve forwardare | FORWARD ns-fw2 | DROP |
| ns-fw1 → ns-sofia | ns-fw1 e' il mittente | OUTPUT ns-fw1 | PASS |
La regola e' semplice: FORWARD = traffico in transito. OUTPUT = traffico originato localmente. iptables -P FORWARD DROP non isola il firewall da se stesso — isola le zone tra loro.
flowchart TB
classDef ext fill:#4a0d0d,stroke:#e05555,color:#eee
classDef fw fill:#0d1a3d,stroke:#4a9eff,color:#eee
classDef dmz fill:#3d2a0d,stroke:#ffaa4a,color:#eee
classDef drop fill:#3d0d0d,stroke:#ff4444,color:#eee
classDef pass fill:#0d2d15,stroke:#4aff7e,color:#eee
subgraph TRANSIT["Pacchetto in TRANSITO — chain FORWARD"]
K["Kali"]:::ext -. "SYN verso Sofia" .-> F1T["ns-fw1
FORWARD chain
policy DROP"]:::fw -. "✗ DROP" .-> D["scartato"]:::drop
end
subgraph LOCAL["Pacchetto ORIGINATO da ns-fw1 — chain OUTPUT"]
F1L["ns-fw1
OUTPUT chain
nessun DROP"]:::fw -->|"✓ PASS"| S["ns-sofia
risponde TTL=64"]:::dmz
end
mindmap
root((ns-fw1 a ns-sofia))
Risultato PASS
TTL 64 nessun drop
Motivo
ns-fw1 e mittente non transito
Chain OUTPUT non FORWARD
Security-level equivalente: chi puo' parlare con chi#
Cisco: cisco-packet-tracer-dmz#Security-level: chi puo' parlare con chi|Security-level ASA — su un ASA ogni interfaccia ha un security-level da 0 a 100. Il traffico fluisce liberamente da livello alto a livello basso (inside → DMZ → outside), il contrario richiede una
access-listesplicita. In Linux non esiste il concetto di security-level — tutto e' simmetrico e tutto e' bloccato. Ogni direzione richiede una regola esplicita.
| Zona | Cisco security-level | iptables equivalente |
|---|---|---|
| Outside (Kali) | 0 | nessuna interfaccia privilegiata — tutto bloccato |
| DMZ (ns-sofia) | 50 | FORWARD chain ns-fw1: regole esplicite per HTTP/HTTPS |
| Inside (ns-giulia) | 100 | FORWARD chain ns-fw2: regola esplicita per MySQL |
La differenza fondamentale:
In Cisco, inside (100) puo' raggiungere DMZ (50) e outside (0) senza ACL — il traffico fluisce naturalmente verso security-level piu' basso. Il firewall e' asimmetrico per design.
In Linux con iptables, la simmetria e' totale: ns-giulia non puo' raggiungere ns-sofia, e ns-sofia non puo' raggiungere ns-giulia, finche' non esiste una regola esplicita in entrambe le direzioni. Non c'e' gerarchia — c'e' solo permit o deny.
| Direzione | Cisco (default) | iptables (dopo FORWARD DROP) |
|---|---|---|
| Kali → Sofia | DENY (0→50) | DENY |
| Kali → Giulia | DENY (0→100) | DENY |
| Sofia → Kali | PERMIT (50→0) | DENY |
| Sofia → Giulia | DENY (50→100) | DENY |
| Giulia → Sofia | PERMIT (100→50) | DENY |
| Giulia → Kali | PERMIT (100→0) | DENY |
In produzione con iptables si replicano le stesse policy Cisco con regole esplicite — piu' verboso, ma piu' controllabile. Nessun comportamento implicito da ricordare.
Connessioni permesse — stato finale#
flowchart LR
classDef ext fill:#4a0d0d,stroke:#e05555,color:#eee
classDef fw fill:#0d1a3d,stroke:#4a9eff,color:#eee
classDef dmz fill:#3d2a0d,stroke:#ffaa4a,color:#eee
classDef lan fill:#0d2d15,stroke:#4aff7e,color:#eee
KALI["Kali
192.168.64.200"]:::ext
FW1["ns-fw1
FORWARD DROP
ACL: 80, 443"]:::fw
SOFIA["ns-sofia
nginx + WAF
10.10.10.2"]:::dmz
FW2["ns-fw2
FORWARD DROP
ACL: 3306 da Sofia"]:::fw
GIULIA[("ns-giulia
MySQL
10.30.30.2")]:::lan
KALI -->|"TCP 80"| FW1
KALI -->|"TCP 443"| FW1
FW1 -->|"PASS"| SOFIA
SOFIA -->|"TCP 3306"| FW2
FW2 -->|"PASS"| GIULIA
Dove si interrompe e perche'#
flowchart LR
classDef ext fill:#4a0d0d,stroke:#e05555,color:#eee
classDef fw fill:#0d1a3d,stroke:#4a9eff,color:#eee
classDef dmz fill:#3d2a0d,stroke:#ffaa4a,color:#eee
classDef lan fill:#0d2d15,stroke:#4aff7e,color:#eee
classDef drop fill:#1a1a1a,stroke:#666,color:#888
KALI["Kali"]:::ext
FW1["ns-fw1
FORWARD DROP"]:::fw
FW2["ns-fw2
FORWARD DROP"]:::fw
SOFIA["ns-sofia"]:::dmz
GIULIA[("ns-giulia")]:::lan
DROP1["✗ DROP
nessuna ACL per porta 22"]:::drop
DROP2["✗ DROP
nessuna ACL verso LAN"]:::drop
DROP3["✗ DROP
non e' 10.10.10.2"]:::drop
DROP4["✗ DROP
nessuna ACL outbound"]:::drop
DROP5["✗ DROP
nessuna ACL su porta 22"]:::drop
KALI -. "TCP 22 SSH" .-> FW1 -. " " .-> DROP1
KALI -. "TCP 3306 verso LAN" .-> FW1 -. " " .-> DROP2
GIULIA -. "TCP 80 inizia connessione" .-> FW2 -. " " .-> DROP4
SOFIA -. "TCP 3306 altro host DMZ" .-> FW2 -. " " .-> DROP3
SOFIA -. "TCP 22 verso Giulia" .-> FW2 -. " " .-> DROP5
Il ciclo richiesta-risposta — chi inizia e chi risponde#
sequenceDiagram
participant Kali
participant FW1
participant Sofia
participant FW2
participant Giulia
Note over Kali,FW1: ACL: TCP 80 in entrata
Kali->>FW1: SYN TCP 80 → PASS
FW1->>Sofia: SYN forwarded
Note over Sofia,FW1: ACL: ESTABLISHED in uscita
Sofia->>FW1: SYN-ACK → PASS
FW1->>Kali: SYN-ACK forwarded
Note over Sofia,FW2: ACL: TCP 3306 da 10.10.10.2
Sofia->>FW2: SYN TCP 3306 → PASS
FW2->>Giulia: SYN forwarded
Note over Giulia,FW2: ACL: ESTABLISHED in uscita
Giulia->>FW2: SYN-ACK → PASS
FW2->>Sofia: SYN-ACK forwarded
Note over Giulia,FW2: Giulia NON puo' iniziare
Giulia--xFW2: SYN TCP 80 → DROP
iptables ACL su ns-fw1 - HTTP e HTTPS verso ns-sofia#
Cisco: cisco-packet-tracer-dmz#FW1 - configurazione|FW1 ACL — su un ASA le access-list aprono porte specifiche dopo il default deny.
access-list outside_in permit tcp any host 10.10.10.2 eq 80diventa in Linux una regola FORWARD esplicita su ns-fw1.
| Stato attuale | Obiettivo | Come | |
|---|---|---|---|
| Kali → Sofia :80 | ✗ DROP | ✓ PASS | ACCEPT tcp:80 in entrata su FW1 |
| Kali → Sofia :443 | ✗ DROP | ✗ rimane bloccato | nessuna regola per ora |
| Sofia → Kali (risposta) | ✗ DROP | ✓ PASS | ACCEPT ESTABLISHED su FW1 |
Con iptables -P FORWARD DROP attivo, aggiungiamo due regole su ns-fw1: una per i pacchetti in ingresso verso Sofia, una per le risposte.
# apri TCP porta 80 da outside verso DMZ (Kali → ns-sofia)
sudo ip netns exec ns-fw1 iptables -A FORWARD \
-i veth-fw1-out -o veth-fw1-dmz \
-p tcp --dport 80 -j ACCEPT
# permetti il traffico di ritorno: SYN-ACK, ACK, dati in risposta (ns-sofia → Kali)
# ESTABLISHED = connessione gia' aperta, RELATED = traffico correlato (es. ICMP error)
sudo ip netns exec ns-fw1 iptables -A FORWARD \
-i veth-fw1-dmz -o veth-fw1-out \
-m state --state ESTABLISHED,RELATED -j ACCEPTVerifica regole aggiunte:
sudo ip netns exec ns-fw1 iptables -L FORWARD -v -n
# Chain FORWARD (policy DROP 6 packets, 504 bytes)
# pkts bytes target prot opt in out source destination
# 0 0 ACCEPT 6 -- veth-fw1-out veth-fw1-dmz 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
# 0 0 ACCEPT 0 -- veth-fw1-dmz veth-fw1-out 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHEDI contatori sono a 0 — le regole ci sono ma nessun pacchetto ha ancora attraversato la chain.
Primo test: 0 pacchetti — diagnosi#
Listener su ns-sofia, connessione da Kali:
# Ubuntu - terminale 1
sudo ip netns exec ns-sofia nc -l -p 80
# Kali - terminale 2
echo "hello world" | nc 10.10.10.2 80Niente. Pacchetti ancora 0. Il testo non arriva su ns-sofia.
tcpdump su ns-fw1 per vedere se il SYN di Kali arriva sull'interfaccia outside:
sudo ip netns exec ns-fw1 tcpdump -i veth-fw1-out -n
# nessun outputIl pacchetto non arriva nemmeno a ns-fw1. Il problema e' prima — su Ubuntu host.
tcpdump su enp0s1 — l'interfaccia dove Ubuntu riceve i pacchetti di Kali:
sudo tcpdump -i enp0s1 -n host 192.168.64.200
# 20:22:02 IP 192.168.64.200.50882 > 10.10.10.2.80: Flags [S], seq 2068371333 ...
# 20:22:03 IP 192.168.64.200.50882 > 10.10.10.2.80: Flags [S], seq 2068371333 ...
# 20:22:04 IP 192.168.64.200.50882 > 10.10.10.2.80: Flags [S], seq 2068371333 ...Il SYN arriva su Ubuntu — ma non viene inoltrato a ns-fw1. Ubuntu riceve e droppa.
Root cause — FORWARD chain di Ubuntu host:
sudo iptables -L FORWARD -v -n
# Chain FORWARD (policy DROP 68 packets, 4080 bytes)
# pkts bytes target prot opt in out source destination
# 38265 417M DOCKER-USER 0 -- * * 0.0.0.0/0 0.0.0.0/0
# 38265 417M DOCKER-FORWARD 0 -- * * 0.0.0.0/0 0.0.0.0/0
# 95 6348 ufw-before-forward 0 -- * * 0.0.0.0/0 0.0.0.0/0
# 68 4080 ufw-reject-forward 0 -- * * 0.0.0.0/0 0.0.0.0/0
# ...Lo stesso problema di ip_forward: Docker e ufw hanno la loro FORWARD chain sul namespace di default di Ubuntu. Nessuna regola permette il traffico tra enp0s1 e veth-host — tutto cade nella policy DROP del host.
Docker/ufw e la FORWARD chain dell'host
Docker imposta iptables -P FORWARD DROP sull'host e aggiunge le sue catene (DOCKER-USER, DOCKER-FORWARD) per gestire il traffico dei container. ufw aggiunge le sue (ufw-before-forward, ufw-reject-forward). Il traffico del nostro lab non e' Docker e non e' noto a ufw — viene droppato silenziosamente.
In un ambiente senza Docker/ufw la FORWARD chain dell'host avrebbe policy ACCEPT di default e questo problema non si presenterebbe.
Fix — aggiungi regole FORWARD sull'host Ubuntu:
# permetti forwarding da Kali (enp0s1) verso ns-fw1 (veth-host)
# -I inserisce in cima alla chain, prima delle regole Docker/ufw
sudo iptables -I FORWARD -i enp0s1 -o veth-host -j ACCEPT
sudo iptables -I FORWARD -i veth-host -o enp0s1 -j ACCEPTmindmap
root((Primo test diagnosi))
Sintomo
nc non riceve niente
Contatori ns-fw1 a zero
Diagnosi
tcpdump ns-fw1 nessun SYN
tcpdump enp0s1 SYN arriva
Ubuntu droppa prima del namespace
Root cause
FORWARD chain Ubuntu host
Docker e ufw policy DROP
Traffico non e Docker non e noto
Secondo test: funziona#
# Ubuntu
sudo ip netns exec ns-sofia nc -l -p 80
# Kali
echo "hello world" | nc 10.10.10.2 80Su ns-sofia compare:
hello worldVerifica contatori ns-fw1 dopo il test:
sudo ip netns exec ns-fw1 iptables -L FORWARD -v -n
# Chain FORWARD (policy DROP 6 packets, 504 bytes)
# pkts bytes target prot opt in out
# 4 228 ACCEPT 6 -- veth-fw1-out veth-fw1-dmz tcp dpt:80
# 4 216 ACCEPT 0 -- veth-fw1-dmz veth-fw1-out state RELATED,ESTABLISHED4 pacchetti per direzione: SYN, SYN-ACK, ACK, dato. La regola funziona. Il testo e' passato attraverso ns-fw1 come previsto.
flowchart LR
classDef ext fill:#4a0d0d,stroke:#e05555,color:#eee
classDef fw fill:#0d1a3d,stroke:#4a9eff,color:#eee
classDef fwblock fill:#3d0d0d,stroke:#ff4444,color:#eee
classDef dmz fill:#3d2a0d,stroke:#ffaa4a,color:#eee
classDef lan fill:#0d2d15,stroke:#4aff7e,color:#eee
classDef drop fill:#1a1a1a,stroke:#555,color:#888
KALI["Kali"]:::ext
FW1["ns-fw1
ACL: TCP 80 in
ESTABLISHED out"]:::fw
SOFIA["ns-sofia
nc listener :80"]:::dmz
FW2["ns-fw2
FORWARD DROP
nessuna ACL"]:::fwblock
GIULIA[("ns-giulia")]:::lan
DROP1["✗ DROP
porta non in ACL"]:::drop
DROP2["✗ DROP
FW2 no ACL"]:::drop
KALI -->|"TCP 80 ✓
hello world"| FW1 -->|"PASS"| SOFIA
SOFIA -->|"ESTABLISHED ✓
ritorno"| FW1 -->|"PASS"| KALI
KALI -. "TCP 443, 22..." .-> DROP1
SOFIA -. "verso Giulia" .-> FW2 -. " " .-> DROP2
mindmap
root((Secondo test funziona))
Fix applicato
iptables -I FORWARD enp0s1 a veth-host
iptables -I FORWARD veth-host a enp0s1
Risultato
hello world arriva su ns-sofia
4 pacchetti per direzione
SYN SYN-ACK ACK dato
iptables ACL su ns-fw2 - MySQL verso ns-giulia#
Cisco: cisco-packet-tracer-dmz#ACL su FW2 - MySQL verso Giulia/MySQL|FW2 ACL —
access-list DMZ_IN permit tcp host 10.10.10.2 host 10.30.30.2 eq 3306. La stessa logica: la sorgente e' un IP specifico, nonany. Solo ns-sofia puo' aprire connessioni verso il database.
| Stato attuale | Obiettivo | Come | |
|---|---|---|---|
| Kali → Giulia :3306 | ✗ DROP a FW1 | ✗ rimane bloccato | nessuna regola su FW1 verso LAN |
| Sofia → Giulia :3306 | ✗ DROP a FW2 (no ACL) | ✓ PASS | ACCEPT tcp:3306 src 10.10.10.2 su FW2 |
| Sofia → Giulia :altra porta | ✗ DROP a FW2 | ✗ rimane bloccato | nessuna regola su FW2 |
# Sofia → Giulia: bloccato a FW2 con ICMP Redirect da FW1
sudo ip netns exec ns-sofia ping -c3 10.30.30.2
# From 10.10.10.1: icmp_seq=1 Redirect Host(New nexthop: 10.10.10.3)
# From 10.10.10.1: icmp_seq=2 Redirect Host(New nexthop: 10.10.10.3)
# From 10.10.10.1: icmp_seq=3 Redirect Host(New nexthop: 10.10.10.3)
# 3 packets transmitted, 0 received, 100% packet loss
# Kali → Giulia: bloccato a FW1 (nessuna ACL verso LAN)
ping -c3 10.30.30.2
# 3 packets transmitted, 0 received, 100% packet lossFW2 ha policy DROP. ns-sofia non puo' raggiungere ns-giulia. Apriamo solo MySQL (3306) e solo dall'IP specifico del web server — non da qualsiasi host della DMZ.
# apri TCP porta 3306 solo da ns-sofia (10.10.10.2) verso ns-giulia (10.30.30.2).
# -s 10.10.10.2: solo il web server puo' aprire connessioni al database.
# se un attaccante compromette un altro host in DMZ, il suo IP non matcha
# questa regola e viene droppato — lateral movement bloccato a livello L3/L4.
#
# -i veth-fw2-dmz -o veth-fw2-lan: il traffico entra dal lato DMZ ed esce
# verso la LAN. Se arrivasse da un'altra interfaccia la regola non matcha.
sudo ip netns exec ns-fw2 iptables -A FORWARD \
-i veth-fw2-dmz -o veth-fw2-lan \
-p tcp --dport 3306 \
-s 10.10.10.2 -d 10.30.30.2 \
-j ACCEPT
# traffico di ritorno: risposte MySQL da ns-giulia verso ns-sofia.
# senza questa regola il SYN-ACK verrebbe droppato — la connessione non si apre.
# ESTABLISHED,RELATED: solo risposte a connessioni gia' aperte da Sofia.
# ns-giulia non puo' avviare connessioni spontanee verso la DMZ.
sudo ip netns exec ns-fw2 iptables -A FORWARD \
-i veth-fw2-lan -o veth-fw2-dmz \
-m state --state ESTABLISHED,RELATED -j ACCEPTVerifica regole — pkts deve essere 0, nessun traffico e' ancora passato:
sudo ip netns exec ns-fw2 iptables -L FORWARD -v -n
# Chain FORWARD (policy DROP 3 packets, 252 bytes)
# pkts bytes target prot opt in out
# 0 0 ACCEPT 6 -- veth-fw2-dmz veth-fw2-lan 10.10.10.2 10.30.30.2 tcp dpt:3306
# 0 0 ACCEPT 0 -- veth-fw2-lan veth-fw2-dmz 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHEDProblema: il routing di Sofia non passa per FW2
Prima di testare, controllo dove Sofia manda effettivamente il traffico verso 10.30.30.2:
# ip route get mostra il next-hop esatto che il kernel userebbe per raggiungere l'IP
sudo ip netns exec ns-sofia ip route get 10.30.30.2
# 10.30.30.2 via 10.10.10.1 dev veth-sofia src 10.10.10.2 uid 0
# cacheIl next-hop e' 10.10.10.1 — ns-fw1. Questo e' il default gateway di Sofia, e ogni traffico
verso subnet sconosciute ci passa. ns-fw1 riceve il pacchetto, non ha nessuna regola per
Sofia→LAN, FORWARD DROP: il pacchetto sparisce. ns-fw2 non lo vede mai — i contatori rimangono a 0.
Su Cisco il problema non esiste perche' Sofia e' sulla DMZ e il default gateway del PC e' FW2. Qui la topologia e' diversa: Sofia ha solo FW1 come gateway. Va aggiunta una rotta statica per dire a Sofia di raggiungere la LAN passando direttamente per FW2:
# rotta statica: il traffico verso la LAN (10.30.30.0/30) passa per ns-fw2 (10.10.10.3),
# non per il default gateway ns-fw1 (10.10.10.1).
# senza questa rotta il SYN arriva a FW1 che lo droppa — FW2 non vede niente.
sudo ip netns exec ns-sofia ip route add 10.30.30.0/30 via 10.10.10.3Verifica che ora il next-hop sia corretto:
sudo ip netns exec ns-sofia ip route get 10.30.30.2
# 10.30.30.2 via 10.10.10.3 dev veth-sofia src 10.10.10.2 uid 0
# cacheTest — netcat su 3306:
# Ubuntu - terminale 1: simula MySQL in ascolto su ns-giulia
sudo ip netns exec ns-giulia nc -l -p 3306
# Ubuntu - terminale 2: connessione da ns-sofia (il web server)
# bash -c serve per eseguire la pipe dentro il namespace corretto
sudo ip netns exec ns-sofia bash -c "echo 'SELECT * FROM lezioni' | nc 10.30.30.2 3306"Su ns-giulia compare:
SELECT * FROM lezioniContatori dopo il test — pkts in crescita su entrambe le regole:
sudo ip netns exec ns-fw2 iptables -L FORWARD -v -n
# Chain FORWARD (policy DROP 3 packets, 252 bytes)
# pkts bytes target prot opt in out
# 4 228 ACCEPT 6 -- veth-fw2-dmz veth-fw2-lan 10.10.10.2 10.30.30.2 tcp dpt:3306
# 4 216 ACCEPT 0 -- veth-fw2-lan veth-fw2-dmz 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
# 4 pacchetti in entrambe le direzioni: SYN, SYN-ACK, dati, FINTest negativo — Kali non raggiunge il database:
# da Kali VM: nessuna rotta verso la LAN, FW1 blocca tutto
nc -w3 10.30.30.2 3306
# (UNKNOWN) [10.30.30.2] 3306 (mysql) : Connection timed outflowchart LR
KALI["🖥 Kali
192.168.64.200"]:::ext
FW1["🛡 ns-fw1
ACL: tcp :80 ✓
ACL: tcp :3306 ✗
ACL: ESTABLISHED ✓"]:::fw
SOFIA["🌐 ns-sofia
10.10.10.2"]:::dmz
FW2["🛡 ns-fw2
ACL: tcp :3306 ✓
solo src 10.10.10.2
ACL: ESTABLISHED ✓"]:::fw
GIULIA[("🗄 ns-giulia
10.30.30.2")]:::lan
KALI -- "tcp :80" --> FW1
FW1 -- "✓" --> SOFIA
SOFIA -- "tcp :3306" --> FW2
FW2 -- "✓" --> GIULIA
KALI -. "tcp :3306 ✗" .-> FW1
classDef ext fill:#4a1942,color:#fff,stroke:#c084fc
classDef fw fill:#1e3a5f,color:#fff,stroke:#60a5fa
classDef dmz fill:#1a3a2a,color:#fff,stroke:#4ade80
classDef lan fill:#3a2a1a,color:#fff,stroke:#fb923c
Sofia non parla mai direttamente con Giulia — il traffico attraversa sempre ns-fw2. ns-fw2 e' il confine tra le due zone: controlla porta, sorgente, e direzione. Kali non raggiungera' mai ns-giulia direttamente — FW1 non ha nessuna regola che permette il transito verso la LAN.
Porta 443 su ns-fw1#
| Stato attuale | Obiettivo | Come | |
|---|---|---|---|
| Kali → Sofia :80 | ✓ PASS | ✓ PASS | gia' aperta |
| Kali → Sofia :443 | ✗ DROP | ✓ PASS | ACCEPT tcp:443 su FW1 |
La porta 80 e' aperta, la 443 no. Aggiungiamo HTTPS — stesso pattern della 80:
# aggiungi TCP 443 (HTTPS) alla chain FORWARD di ns-fw1.
# la regola ESTABLISHED,RELATED gia' configurata copre il traffico di ritorno
# per entrambe le porte — non serve una seconda regola.
sudo ip netns exec ns-fw1 iptables -A FORWARD \
-i veth-fw1-out -o veth-fw1-dmz \
-p tcp --dport 443 -j ACCEPTVerifica — ns-fw1 ha ora tre regole:
sudo ip netns exec ns-fw1 iptables -L FORWARD -v -n
# Chain FORWARD (policy DROP X packets, Y bytes)
# pkts bytes target prot opt in out
# 4 228 ACCEPT 6 -- veth-fw1-out veth-fw1-dmz tcp dpt:80
# 0 0 ACCEPT 6 -- veth-fw1-out veth-fw1-dmz tcp dpt:443
# 4 216 ACCEPT 0 -- veth-fw1-dmz veth-fw1-out state RELATED,ESTABLISHEDTest TCP 443 con netcat — verifica che il SYN arriva a ns-sofia prima di installare nginx con TLS:
# Ubuntu - terminale 1
sudo ip netns exec ns-sofia nc -l -p 443
# Kali - terminale 2
echo "test https" | nc 10.10.10.2 443Il testo arriva su ns-sofia. La porta 443 attraversa FW1.
mindmap
root((Porta 443 su ns-fw1))
Stato prima
80 aperta
443 DROP
Regola aggiunta
ACCEPT tcp 443 in entrata
ESTABLISHED gia copre il ritorno
Verifica
nc listener su ns-sofia 443
Testo arriva da Kali
Stato finale ns-fw1
tcp 80 ACCEPT
tcp 443 ACCEPT
ESTABLISHED RELATED ACCEPT
Topologia completa — stato prima del WAF#
Tutte le regole iptables sono in place. Prima di passare al layer applicativo (nginx + WAF), la rete e' questa:
flowchart LR
KALI["🖥 Kali
192.168.64.200"]:::ext
UBUNTU["Ubuntu host
192.168.64.1 / 10.0.0.1"]:::host
FW1["🛡 ns-fw1
10.0.0.2 / 10.10.10.1
ACCEPT tcp:80
ACCEPT tcp:443
ACCEPT ESTABLISHED"]:::fw
BRIDGE["br-dmz
switch L2"]:::bridge
SOFIA["🌐 ns-sofia
10.10.10.2"]:::dmz
FW2["🛡 ns-fw2
10.10.10.3 / 10.30.30.1
ACCEPT tcp:3306 src .10.2
ACCEPT ESTABLISHED"]:::fw
GIULIA[("🗄 ns-giulia
10.30.30.2")]:::lan
KALI -->|"enp0s1 / veth-host"| UBUNTU
UBUNTU -->|"veth-host / veth-fw1-out"| FW1
FW1 -->|"veth-fw1-dmz / veth-fw1-dmz-br"| BRIDGE
BRIDGE -->|"veth-sofia-br / veth-sofia"| SOFIA
BRIDGE -->|"veth-fw2-dmz-br / veth-fw2-dmz"| FW2
FW2 -->|"veth-fw2-lan / veth-giulia"| GIULIA
classDef ext fill:#4a1942,color:#fff,stroke:#c084fc
classDef host fill:#2a2a2a,color:#fff,stroke:#9ca3af
classDef fw fill:#1e3a5f,color:#fff,stroke:#60a5fa
classDef bridge fill:#1a2a3a,color:#fff,stroke:#38bdf8
classDef dmz fill:#1a3a2a,color:#fff,stroke:#4ade80
classDef lan fill:#3a2a1a,color:#fff,stroke:#fb923c
Ogni label sugli edge mostra i due capi del cavo virtuale:
- l'interfaccia di chi manda
- e quella di chi riceve.
FW1 e FW2 hanno le ACL attive — tutto il resto e' DROP.
Script e file di configurazione del lab: github.com/Barno/u-random-dev





