🔥 Firewalls de verdad
Qué es un firewall, iptables y nftables con reglas reales, UFW y firewalld, apertura de puertos para un servidor web, rate limiting, fail2ban y persistencia.
Firewalls de verdad
Un firewall es la frontera de red de tu servidor: decide qué tráfico entra, sale y se reenvía. Es tu primera línea de defensa y, mal configurado, es también la forma más rápida de encerrarte fuera de tu propio servidor. Esta guía cubre de lo más bajo (iptables/nftables) a lo más cómodo (UFW, firewalld), con ejemplos que puedes ejecutar hoy.
¿Qué es un firewall?
Filtra paquetes según sus atributos: IP origen/destino, puerto, protocolo (TCP/UDP), interfaz y estado de la conexión. Cada paquete pasa por un conjunto de reglas; la primera que coincida decide (ACEPTAR, RECHAZAR o IGNORAR).
💡 ACCEPT permite, DROP ignora el paquete en silencio (el cliente espera hasta el timeout), REJECT lo rechaza con un error (el cliente se entera al instante). Para servicios expuestos suele preferirse DROP; para puertos cerrados, REJECT.
iptables
iptables organiza las reglas en tablas (filtro, nat, mangle…) y dentro de cada tabla en cadenas. La tabla más usada es filter, con tres cadenas por defecto:
| Cadena | Filtra tráfico |
|---|---|
INPUT |
Que entra al servidor |
OUTPUT |
Que sale del servidor |
FORWARD |
Que se reenvía a través del servidor (router) |
Estructura de una regla
iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT
# ^cadena ^proto ^puerto destino ^origen ^acción
-Aañade al final,-Iinserta al principio,-Dborra.-pprotocolo,--dportpuerto destino,-s/-dorigen/destino,-iinterfaz.-jla acción (ACCEPT/DROP/REJECT).
Reglas para un servidor web
Solo abrimos SSH, HTTP y HTTPS; el resto se bloquea:
# 1. Permite tráfico ya establecido (respuestas de conexiones iniciadas)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 2. Permite loopback (lo) — siempre
iptables -A INPUT -i lo -j ACCEPT
# 3. Abre puertos de servicio
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # HTTPS
# 4. Default policy: DROP todo lo demás que entra
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
⚠️ Orden importa: iptables evalúa en orden y aplica la primera coincidencia. Pon las excepciones (accept) antes de la política por defecto. Y nunca apliques una política
DROPenINPUTsin haber abierto antes el puerto 22, o te quedarás sin SSH.
Ver y limpiar
iptables -L -n -v # lista reglas (sin resolver nombres)
iptables -L INPUT --line-numbers # con números de línea
iptables -D INPUT 3 # borra la regla 3
iptables -F # vacía todas las reglas (¡cuidado!)
nftables: el sucesor
nftables (paquete nft) es el reemplazo moderno: sintaxis más limpia, una sola herramienta, y soporta tablas y cadenas sin la duplicación de iptables. Es el backend por defecto en distribuciones nuevas.
# Tabla y cadena base
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
# Reglas (mismo servidor web: 22, 80, 443)
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input iif lo accept
nft add rule inet filter input tcp dport { 22, 80, 443 } accept
# Ver
nft list ruleset
💡 iptables en kernels modernos es una capa de compatibilidad sobre nftables. Si empiezas un proyecto nuevo, escribe reglas en nft; si administras servidores viejos, iptables sigue perfectamente válido.
UFW: el firewall fácil
Uncomplicated Firewall es el frontend amigable sobre iptables/nftables de Ubuntu/Debian. Ideal para el día a día:
ufw default deny incoming # bloquea todo lo que entra por defecto
ufw default allow outgoing # permite todo lo que sale
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow from 10.0.0.5 to any port 3306 # MySQL solo para una IP
ufw limit ssh # rate-limit SSH (anti fuerza bruta)
ufw enable # ACTIVA el firewall
ufw status verbose # estado y reglas
ufw status numbered
ufw delete 3 # borra la regla 3
⚠️
ufw enableactiva el firewall de inmediato. Verifica que el puerto 22 (SSH) está permitido antes de habilitarlo, y hazlo desde una sesión donde no pierdas el acceso.
firewalld: zonas
firewalld (Fedora/RHEL/CentOS) organiza las reglas por zonas (niveles de confianza de la red). Un servidor web suele usar public, un servidor interno internal:
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --permanent --zone=public --add-port=22/tcp
firewall-cmd --reload # aplica cambios (necesario tras --permanent)
firewall-cmd --list-all --zone=public
firewall-cmd --get-default-zone
| Zona | Confianza | Uso típico |
|---|---|---|
public |
Baja | servidor expuesto a internet |
internal |
Media | red interna corporativa |
trusted |
Alta | red privada de confianza |
drop |
Nula | descarta todo |
Rate limiting (anti fuerza bruta)
Limitar peticiones por IP evita que un atacante pruebe contraseñas miles de veces por segundo:
# iptables: máx. 5 conexiones SSH por minuto por IP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --set --name ssh
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --update --seconds 60 --hitcount 5 --rttl \
--name ssh -j REJECT
# UFW: igual pero en un comando
ufw limit ssh
fail2ban
fail2ban vigila los logs y banea IPs automáticamente tras demasiados intentos fallidos. Configuración real para SSH:
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 10m # duración del ban
findtime = 10m # ventana de tiempo
maxretry = 5 # intentos fallidos antes de ban
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log # Debian/Ubuntu
# logpath = /var/log/secure # en RHEL/CentOS
systemctl enable --now fail2ban
fail2ban-client status sshd # IPs baneadas
fail2ban-client set sshd unbanip 1.2.3.4 # desbanea manual
💡 fail2ban no sustituye a la política de acceso: sigue usando llaves SSH en vez de contraseñas y
PasswordAuthentication noensshd_config. fail2ban es una capa más, no la única.
Hacer la configuración persistente
Todo lo que configuras con iptables/nft se pierde al reiniciar si no lo guardas:
# iptables-persistent (Debian/Ubuntu)
apt install iptables-persistent
netfilter-persistent save
netfilter-persistent reload
# nftables
nft list ruleset > /etc/nftables.conf
systemctl enable nftables
# UFW y firewalld ya son persistentes por sí mismos (systemd)
systemctl enable ufw
systemctl enable firewalld
Cheatsheet
| Necesito… | Comando |
|---|---|
| Bloquear todo lo entrante por defecto | ufw default deny incoming |
| Abrir un puerto | ufw allow 80/tcp / firewall-cmd --add-port=80/tcp |
| Listar reglas iptables | iptables -L -n -v |
| Rate limit SSH | ufw limit ssh |
| Ban automático | fail2ban (maxretry + bantime) |
| Guardar iptables | netfilter-persistent save |
| Guardar nft | nft list ruleset > /etc/nftables.conf |
Para profundizar
- Netfilter/iptables HOWTO: documentación oficial de Netfilter.
- nftables wiki: la guía del sucesor.
- Ubuntu UFW documentation: UFW paso a paso.
- fail2ban docs: configuración avanzada.
- DigitalOcean: Common Firewall Rules and Commands: recetas listas.
- Ruta completa: Infraestructura y DevOps.