PR5021 - Firewall i IDS amb Docker
Objectius
- Desplegar un entorn de xarxa segmentat amb Docker
- Configurar regles de firewall amb nftables
- Implementar Suricata com a IDS/IPS
- Analitzar alertes d'intrusió en temps real
- Validar la segmentació de xarxa amb proves d'atac controlades
Prerequisits
| Element | Detall |
|---|---|
| Temps estimat | 4 hores |
| Eines necessàries | Docker Desktop, navegador web |
| Coneixements previs | Conceptes bàsics de xarxes, TCP/IP |
| Fitxers de la pràctica | Descarregables des del Moodle del curs |
Introducció
En aquesta pràctica construirem un entorn de laboratori que simula una arquitectura de xarxa empresarial amb tres segments: Internet (simulat), DMZ i xarxa interna. Usarem nftables (el successor modern d'iptables al kernel Linux) per a les regles de firewall i Suricata per a la detecció d'intrusions.
La pràctica segueix el principi de defense in depth: múltiples capes de seguretat que un atacant hauria de superar per arribar als sistemes interns.
flowchart TB
subgraph ext[Xarxa Externa - 10.0.1.0/24]
ATTACKER[Atacant simulat\nKali Linux]
end
subgraph dmz[DMZ - 10.0.2.0/24]
WEB[Servidor Web\nNGINX]
end
subgraph int[Xarxa Interna - 192.168.100.0/24]
DB[Base de Dades\nPostgreSQL]
CLIENT[Client intern]
end
FW[Firewall\nnftables + Suricata]
ATTACKER --> FW
FW --> WEB
FW --> CLIENT
WEB --> FW
FW --> DB
Part 1: Preparació de l'entorn
1.1 Estructura de fitxers
Crea l'estructura de directoris per a la pràctica:
1.2 Fitxer docker-compose.yml
# docker-compose.yml
version: '3.8'
services:
# Firewall + IDS
firewall:
image: ubuntu:22.04
container_name: fw-NOMCOGNOM
hostname: firewall-NOMCOGNOM
cap_add:
- NET_ADMIN
- NET_RAW
- SYS_ADMIN
networks:
externa:
ipv4_address: 10.0.1.1
dmz:
ipv4_address: 10.0.2.1
interna:
ipv4_address: 192.168.100.1
volumes:
- ./config/nftables.conf:/etc/nftables.conf
- ./rules/suricata.rules:/etc/suricata/rules/local.rules
- ./logs:/var/log/suricata
command: >
bash -c "
apt-get update -qq &&
apt-get install -y -qq nftables suricata curl iproute2 &&
sysctl -w net.ipv4.ip_forward=1 &&
nft -f /etc/nftables.conf &&
suricata -D -i eth0 -i eth1 -i eth2 &&
tail -f /var/log/suricata/fast.log
"
# Servidor web en DMZ
webserver:
image: nginx:alpine
container_name: web-NOMCOGNOM
hostname: web-dmz-NOMCOGNOM
networks:
dmz:
ipv4_address: 10.0.2.10
volumes:
- ./config/nginx-web.conf:/etc/nginx/nginx.conf
# Base de dades a la xarxa interna
database:
image: postgres:15-alpine
container_name: db-NOMCOGNOM
hostname: db-interna-NOMCOGNOM
networks:
interna:
ipv4_address: 192.168.100.10
environment:
POSTGRES_PASSWORD: "segura_lab_2024"
POSTGRES_DB: "empresa_db"
# Client simulat a la xarxa interna
client:
image: ubuntu:22.04
container_name: client-NOMCOGNOM
hostname: client-intern-NOMCOGNOM
networks:
interna:
ipv4_address: 192.168.100.20
command: sleep infinity
# Atacant simulat (xarxa externa)
attacker:
image: kalilinux/kali-rolling
container_name: attacker-NOMCOGNOM
hostname: attacker-NOMCOGNOM
networks:
externa:
ipv4_address: 10.0.1.100
command: sleep infinity
networks:
externa:
driver: bridge
ipam:
config:
- subnet: 10.0.1.0/24
dmz:
driver: bridge
ipam:
config:
- subnet: 10.0.2.0/24
interna:
driver: bridge
ipam:
config:
- subnet: 192.168.100.0/24
Part 2: Configuració del Firewall (nftables)
2.1 Regles nftables
Crea el fitxer config/nftables.conf:
# config/nftables.conf - Política de firewall per a l'empresa
# Alumne: NOMCOGNOM
# Data: 2024
#!/usr/sbin/nft -f
# Netejar totes les regles existents
flush ruleset
# Definir variables per a les xarxes
define NET_EXTERNA = 10.0.1.0/24
define NET_DMZ = 10.0.2.0/24
define NET_INTERNA = 192.168.100.0/24
define IP_WEBSERVER = 10.0.2.10
define IP_DATABASE = 192.168.100.10
table inet filter {
# Cadena per al tràfic entrant al firewall
chain input {
type filter hook input priority 0; policy drop;
# Permetre connexions establertes
ct state established,related accept
# Permetre loopback
iif lo accept
# Permetre ICMP (ping) amb límit
ip protocol icmp limit rate 10/second accept
# Descartar tot el reste (ja és la política per defecte)
log prefix "FW-INPUT-DROP: " drop
}
# Cadena per al tràfic que passa pel firewall (forwarding)
chain forward {
type filter hook forward priority 0; policy drop;
# Permetre connexions establertes i relacionades
ct state established,related accept
# REGLA 1: Externa -> DMZ: Permetre HTTP/HTTPS cap al servidor web
ip saddr $NET_EXTERNA ip daddr $IP_WEBSERVER tcp dport { 80, 443 } \
ct state new accept \
comment "Permetre accés web des de l'exterior"
# REGLA 2: DMZ -> Interna: Permetre accés a la BBDD NOMÉS des del web
ip saddr $IP_WEBSERVER ip daddr $IP_DATABASE tcp dport 5432 \
ct state new accept \
comment "Web pot accedir a la BBDD"
# REGLA 3: Interna -> DMZ: Permetre accés intern al web
ip saddr $NET_INTERNA ip daddr $NET_DMZ tcp dport { 80, 443 } \
ct state new accept \
comment "Xarxa interna pot accedir a la DMZ"
# REGLA 4: Interna -> Externa: Permetre HTTP/HTTPS per a navegació
ip saddr $NET_INTERNA oif eth0 tcp dport { 80, 443, 53 } \
ct state new accept \
comment "Navegació web interna"
# REGLA 5: BLOCAR External -> Interna directament
ip saddr $NET_EXTERNA ip daddr $NET_INTERNA \
log prefix "FW-BLOCKED-EXT-INT: " drop \
comment "Mai accés directe extern a la xarxa interna"
# Log i drop de tot el que no estigui permès
log prefix "FW-FORWARD-DROP: " drop
}
# NAT: traducció d'adreces per a la xarxa interna
chain postrouting {
type nat hook postrouting priority 100;
ip saddr $NET_INTERNA oif eth0 masquerade
}
}
2.2 Aplicar i verificar les regles
# Iniciar l'entorn
docker compose up -d
# Entrar al contenidor del firewall
docker exec -it fw-NOMCOGNOM bash
# Verificar que nftables està actiu
nft list ruleset
# Verificar que el forwarding està activat
cat /proc/sys/net/ipv4/ip_forward
# Ha de mostrar: 1
# Verificar les interfícies
ip addr show
Reflexió 1
Observa la taula inet filter. Quina és la política per defecte de la cadena forward? Per què és important que la política per defecte sigui drop en lloc de accept?
Part 3: Configuració de Suricata (IDS)
3.1 Regles personalitzades
Crea el fitxer rules/suricata.rules:
# Regles Suricata per a la pràctica
# Alumne: NOMCOGNOM
# =============================================
# Detecció d'escaneig de ports
# =============================================
# Detectar escaneig Nmap SYN scan
alert tcp any any -> $HOME_NET any (
msg:"SCAN Nmap SYN scan NOMCOGNOM";
flags:S;
detection_filter: track by_src, count 50, seconds 5;
classtype:network-scan;
sid:9100001;
rev:1;
)
# Detectar escaneig UDP (Nmap)
alert udp any any -> $HOME_NET any (
msg:"SCAN UDP port scan NOMCOGNOM";
detection_filter: track by_src, count 30, seconds 5;
classtype:network-scan;
sid:9100002;
rev:1;
)
# =============================================
# Detecció d'atacs de força bruta
# =============================================
# Força bruta SSH
alert tcp any any -> $HOME_NET 22 (
msg:"BRUTE FORCE SSH attempt NOMCOGNOM";
flow:to_server,established;
content:"SSH";
detection_filter: track by_src, count 5, seconds 30;
classtype:attempted-admin;
sid:9100003;
rev:1;
)
# Força bruta web (POST repetits)
alert http any any -> $HTTP_SERVERS any (
msg:"BRUTE FORCE HTTP POST attempt NOMCOGNOM";
http.method; content:"POST";
detection_filter: track by_src, count 20, seconds 10;
classtype:web-application-attack;
sid:9100004;
rev:1;
)
# =============================================
# Detecció d'atacs web (SQL Injection, XSS)
# =============================================
# SQL Injection bàsic
alert http any any -> $HTTP_SERVERS any (
msg:"WEB SQL Injection attempt NOMCOGNOM";
http.uri;
content:"UNION SELECT";
nocase;
classtype:web-application-attack;
sid:9100005;
rev:1;
)
alert http any any -> $HTTP_SERVERS any (
msg:"WEB SQL Injection OR-based NOMCOGNOM";
http.uri;
content:"' OR '1'='1";
classtype:web-application-attack;
sid:9100006;
rev:1;
)
# XSS bàsic
alert http any any -> $HTTP_SERVERS any (
msg:"WEB XSS attempt NOMCOGNOM";
http.uri;
content:"<script>";
nocase;
classtype:web-application-attack;
sid:9100007;
rev:1;
)
# =============================================
# Detecció de DDoS / SYN flood
# =============================================
# SYN flood
alert tcp any any -> $HOME_NET any (
msg:"DOS SYN flood attempt NOMCOGNOM";
flags:S;
detection_filter: track by_dst, count 500, seconds 10;
classtype:attempted-dos;
sid:9100008;
rev:1;
)
3.2 Monitorar alertes en temps real
# En un terminal, seguir les alertes de Suricata
docker exec -it fw-NOMCOGNOM bash
tail -f /var/log/suricata/fast.log
# En un altre terminal, generar tràfic de prova des de l'atacant
docker exec -it attacker-NOMCOGNOM bash
apt-get install -y nmap curl
# Escaneig de ports (ha de generar alerta)
nmap -sS 10.0.2.10
# Intent de SQL injection (ha de generar alerta)
curl "http://10.0.2.10/?id=1' UNION SELECT username,password FROM users--"
Reflexió 2
Després de fer l'escaneig Nmap, quantes alertes ha generat Suricata? Quina és la diferència entre els camps src_ip i dst_ip en els logs?
Part 4: Verificació de la segmentació
4.1 Proves de connectivitat
Realitza les proves des del contenidor d'atacant i registra els resultats:
# Des del contenidor attacker (10.0.1.100)
docker exec -it attacker-NOMCOGNOM bash
# PROVA 1: Accés a la DMZ (ha de funcionar per als ports 80/443)
curl -I http://10.0.2.10
# Resultat esperat: respon (perquè el firewall ho permet)
# PROVA 2: Intent d'accés directe a la BBDD des de l'exterior
nc -zv 192.168.100.10 5432
# Resultat esperat: NO respon (bloquejat pel firewall)
# PROVA 3: Intent d'accés SSH a la BBDD
ssh root@192.168.100.10
# Resultat esperat: bloquejat (timeout)
# Des del contenidor client intern (192.168.100.20)
docker exec -it client-NOMCOGNOM bash
# PROVA 4: Accés al servidor web (ha de funcionar)
apt-get install -y curl
curl -I http://10.0.2.10
# Resultat esperat: respon
# PROVA 5: Accés directe a la BBDD des de la xarxa interna
nc -zv 192.168.100.10 5432
# Resultat esperat: respon (perquè és tràfic intern)
4.2 Verificar els logs del firewall
# Al contenidor del firewall, veure les connexions bloquejades
docker exec -it fw-NOMCOGNOM bash
nft list ruleset statistics
# Veure els paquets bloquejats al kernel log
dmesg | grep "FW-BLOCKED"
Reflexió 3
La PROVA 2 (accés de l'atacant a la BBDD) ha de ser bloquejada. Quina regla de nftables és responsable d'aquest bloqueig? Indica el comentari de la regla i explica per quins paràmetres (IP origen, destí, port) la regla el bloca.
Part 5: Mode IPS - Bloqueig actiu
Suricata en mode IPS pot blocar el tràfic, no sols detectar-lo. Activem el mode inline:
5.1 Configuració IPS
# Afegir al docker-compose.yml - servei firewall, command:
# Modificar la línia de suricata per a mode IPS
command: >
bash -c "
apt-get update -qq &&
apt-get install -y -qq nftables suricata iproute2 &&
sysctl -w net.ipv4.ip_forward=1 &&
nft -f /etc/nftables.conf &&
# Mode IPS: Suricata en mode nfqueue (inline)
nft add rule inet filter forward queue num 0 bypass &&
suricata -D --af-packet -i eth1 -i eth2 &&
tail -f /var/log/suricata/fast.log
"
# Regla per a activar el bloqueig de SQL injection (mode IPS)
# Modificar la regla sid:9100005 a:
drop http any any -> $HTTP_SERVERS any (
msg:"WEB SQL Injection BLOCKED NOMCOGNOM";
http.uri;
content:"UNION SELECT";
nocase;
classtype:web-application-attack;
sid:9100009;
rev:1;
)
5.2 Verificar el bloqueig
# Reiniciar l'entorn amb la nova configuració
docker compose down && docker compose up -d
# Intentar SQL injection des de l'atacant
docker exec -it attacker-NOMCOGNOM bash
curl "http://10.0.2.10/?id=1' UNION SELECT 1,2,3--"
# Ha de ser bloquejat amb una resposta de timeout o connexió refusada
# Verificar l'alerta als logs:
docker exec -it fw-NOMCOGNOM tail -f /var/log/suricata/fast.log
Reflexió 4
En mode IPS, les peticions de SQL injection s'han bloquejat? Quina és la diferència pràctica entre IDS (detecció) i IPS (prevenció) en termes de la resposta a l'atac?
Informe de la pràctica
Crea un document informe_pr5021_NOMCOGNOM.md amb:
# Informe PR5021 - Firewall i IDS
**Alumne**: NOMCOGNOM
**Data**: ____________________
## 1. Topologia de xarxa implementada
[Diagrama o descripció de les xarxes i IPs]
## 2. Regles de firewall
[Llista les 5 regles que has configurat i explica cadascuna]
| Regla | Origen | Destí | Port | Acció | Justificació |
|-------|--------|-------|------|-------|--------------|
| 1 | | | | | |
...
## 3. Alertes de Suricata generades
[Captura de pantalla o text dels logs de fast.log]
| Alerta | IP Origen | IP Destí | Descripcció |
|--------|-----------|----------|-------------|
| | | | |
## 4. Resultats de les proves de connectivitat
| Prova | Origen | Destí | Port | Resultat | Regla que aplica |
|-------|--------|-------|------|----------|-----------------|
| 1 | 10.0.1.100 | 10.0.2.10 | 80 | | |
| 2 | 10.0.1.100 | 192.168.100.10 | 5432 | | |
...
## 5. Reflexions
[Respon a les 4 preguntes de reflexió de la pràctica]
Pregunta final de reflexió
Si afegissis un servidor de correu a la DMZ, quines regles addicionals hauries d'afegir al firewall? Considera:
- Accés des d'Internet (ports SMTP, IMAPS)
- Accés des de la xarxa interna als seus correus
- Restriccions necessàries
Rúbrica
Vegeu Rúbrica PR5021.