Fail2ban vs CrowdSec en 2026: ¿cuál instalar en tu VPS? (y dónde encaja PSAD)
Seguridad · · 10 min de lectura
Respuesta corta: si tu VPS solo expone SSH, instala Fail2ban. Si sirve tráfico web público (nginx, Traefik, WordPress, cualquier cosa en 80/443), instala CrowdSec con un bouncer: sus escenarios HTTP cubren mucho más que los filtros de Fail2ban y bloquea IPs que otros usuarios ya han reportado. PSAD detecta escaneos de puertos, pero no publica una versión desde 2018, así que tómalo como un extra de nicho.
Elijas la que elijas, es una capa más de tu estrategia de seguridad y hardening de VPS, no la estrategia entera.
1. Fail2ban vs CrowdSec vs PSAD de un vistazo
Versiones comprobadas el 30 de octubre de 2026.
| Fail2ban | CrowdSec | PSAD | |
|---|---|---|---|
| Última versión | 1.1.1 (agosto de 2026) | 1.8.2 (octubre de 2026) | 2.4.6 (agosto de 2018) |
| Cómo detecta | Filtros regex sobre archivos de log o el journal de systemd. Cuenta fallos por IP en una ventana de tiempo | Parsers y escenarios YAML sobre archivos de log, el journal o los logs de contenedores Docker | Lee las líneas LOG de iptables en el log del kernel y puntúa los escaneos de puertos |
| Cómo bloquea | Regla de firewall (nftables, iptables, firewalld, ufw) o cualquier acción programada, como la API de Cloudflare | Un bouncer aparte: firewall (nftables, iptables, ipset), nginx, Traefik, HAProxy, Cloudflare | Bloqueo opcional con iptables, desactivado por defecto |
| Bloquea IPs antes de que te prueben | No | Sí, con la blocklist de la comunidad | No |
| Recursos | Un demonio en Python. La CPU crece con el volumen de logs | Motor en Go, menos de 100 MB de RAM en instalaciones pequeñas y medianas según su documentación, más el bouncer | Demonio en Perl, más el logging extra del firewall que necesita |
| Esfuerzo de instalación | apt install y unas líneas de jail.local |
Repositorio del fabricante, motor, bouncer y una colección por servicio | Reglas LOG en iptables y ajuste de umbrales |
| Datos compartidos | Ninguno | Envía por defecto la IP atacante, el escenario, la hora y el ID de máquina. No tus logs. Se puede desactivar | Ninguno |
| Gratis vs de pago | Gratis (GPL-2.0) | Motor y bouncers gratis (MIT). Consola gratuita: 500 alertas/mes, 2 meses de historial, 3 blocklists. Premium se factura por motor | Gratis (GPL-2.0) |
| IPv6 | Sí | Sí | Sí (logs de ip6tables) |
| nftables | Sí. Acción por defecto en Debian 13 | Sí, con un paquete de bouncer propio | No, solo iptables |
| Docker | Los bloqueos van a INPUT y no afectan a los puertos publicados de los contenedores salvo que uses DOCKER-USER |
El bouncer de nftables filtra el tráfico reenviado por defecto y el motor lee los logs de los contenedores | No está pensado para ello |
2. Fail2ban: un demonio, una regex, un bloqueo
Fail2ban sigue un log (o el journal de systemd), compara cada línea con un filtro y cuenta los fallos por IP. Con la configuración de serie, 5 fallos en 10 minutos bloquean esa IP durante 10 minutos. El bloqueo es una regla de firewall o cualquier comando que definas como acción.
La versión actual es la 1.1.1 (15 de agosto de 2026), la primera desde la 1.1.0 de abril de 2024. Lo más probable es que tu distribución traiga una anterior: Debian 12 y Ubuntu 24.04 llevan la 1.0.2 y Debian 13 la 1.1.0. Para SSH da igual.
Una trampa en Debian 12: sin rsyslog no existe /var/log/auth.log y la jail de sshd falla con "Have not found any log file for sshd jail". Haz que lea el journal. Un jail.local razonable para empezar:
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
# Los reincidentes reciben bloqueos cada vez más largos
bantime.increment = true
# No te bloquees a ti mismo: añade tu IP fija
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
[sshd]
enabled = true
backend = systemd
Después, sudo systemctl restart fail2ban.
Lo que hace bien:
- Ni llamadas de red ni cuenta: nada sale del servidor.
- Trae filtros para sshd, nginx, Apache, Postfix, Dovecot y decenas más.
- Las acciones son simples comandos, así que puede bloquear en el firewall local o enviar el bloqueo a Cloudflare.
Dónde se queda corto:
- Es puramente reactivo. Cada IP nueva tiene sus 5 intentos antes del bloqueo. Una botnet que rota direcciones casi ni lo nota.
- Cada línea de log pasa por regex de Python. En un log de SSH tranquilo no se nota. En un access log de nginx con tráfico aparece en
top. - Para ataques web acabas escribiendo y probando tus propias regex.
3. CrowdSec: detección más una blocklist compartida
CrowdSec divide el trabajo en dos. El Security Engine analiza logs y ejecuta escenarios (fuerza bruta, sondeo de rutas, escaneos de CVE) para generar decisiones. Un bouncer las aplica: en el firewall, en nginx, en Traefik o en Cloudflare.
El motor por sí solo no bloquea nada. Lo dice la propia documentación de CrowdSec y es un fallo fácil de pasar por alto: motor funcionando, ningún bouncer, cero bloqueos.
La versión actual es la 1.8.2 (26 de octubre de 2026). No la instales desde los repositorios de Debian o Ubuntu: traen la 1.4.6. Usa el repositorio del fabricante:
curl -s https://install.crowdsec.net | sudo sh
sudo apt install crowdsec
sudo apt install crowdsec-firewall-bouncer-nftables
El instalador intenta detectar tus servicios e instalar las colecciones correspondientes. Compruébalo con sudo cscli collections list y añade lo que falte, por ejemplo sudo cscli collections install crowdsecurity/nginx.
La blocklist de la comunidad
Esta es la ventaja real de CrowdSec. Tu motor reporta lo que detecta y, a cambio, descarga una blocklist construida con lo que han detectado otros motores, filtrada según los escenarios que usas. Los usuarios gratuitos que contribuyen reciben la lista Community (15.000 IPs). Los que no contribuyen reciben la Lite (3.000 IPs). Los planes de pago reciben la Premium (hasta 60.000 IPs) sin necesidad de contribuir. Solo cuentan como contribución las señales de escenarios del Hub sin modificar.
Qué comparte CrowdSec y cómo evitarlo
Por defecto, el motor envía "metadatos de señal" a la Central API de CrowdSec: nombre y versión del escenario, la hora, tu ID de máquina y la IP atacante. No envía tus líneas de log. También informa de qué escenarios y bouncers tienes en marcha.
Para dejar de compartir, pon esto en /etc/crowdsec/config.yaml:
api:
server:
online_client:
sharing: false
En el plan gratuito eso te deja con la blocklist Lite. Si comentas el bloque online_client entero, te desconectas de la Central API y te quedas sin blocklist de la comunidad.
Gratis vs de pago
El motor y los bouncers son open source (MIT) y gratuitos. La consola web es opcional. En el plan gratuito Community guarda 500 alertas al mes con 2 meses de historial y permite suscribirse a 3 blocklists. Console Premium se factura por cada Security Engine registrado y añade la blocklist Premium, más retención y cuotas de alertas más altas. Para nada de lo que cuenta este artículo necesitas la consola.
Lo que hace bien:
- Bloquea IPs ya reportadas por otros motores antes de que envíen una sola petición.
- La colección HTTP detecta de serie path traversal, sondeos de
.envy.git, sondeos de SQLi y XSS, escaneos de WordPress y sondeos de CVE. - Bouncers para el firewall, nginx, Traefik, HAProxy y Cloudflare.
Dónde se queda corto:
- Más piezas: motor, bouncer, colecciones y una conexión saliente.
- Los paquetes de las distribuciones tienen años, así que dependes del repositorio del fabricante.
- La blocklist funciona porque compartes. Si desactivas la compartición, te quedas con la lista Lite de 3.000 IPs.
4. ¿Cuál deberías instalar?
VPS pequeño, solo con SSH abierto
Fail2ban, solo con la jail de sshd. Es un paquete, sin cuenta y sin nada que mantener sincronizado.
Sé realista con lo que te aporta. Si ya entras solo con llaves SSH (PasswordAuthentication no, login de root desactivado) y el firewall no expone nada más, un ataque de fuerza bruta no puede tener éxito de todas formas. Fail2ban te acorta los logs y ahorra algo de CPU en handshakes inútiles. Merece los cinco minutos, pero tu defensa son las llaves y el firewall, no Fail2ban. Lo desarrollamos en Fail2ban vs llaves SSH.
Servidor web con nginx
CrowdSec con el bouncer de firewall. Los escáneres que recorren todas las IPs públicas buscando /.env, /wp-login.php o el último CVE son justo lo que cubren la blocklist de la comunidad y los escenarios HTTP. Fail2ban tiene filtros para nginx (nginx-http-auth, nginx-botsearch, nginx-limit-req, nginx-bad-request, nginx-forbidden) y funcionan, pero todo lo que vaya más allá son regex que escribes y mantienes tú. Si quieres bloqueo tipo WAF dentro de nginx, CrowdSec tiene también un bouncer para nginx.
Detrás de Cloudflare
El proxy cambia el problema. Tu servidor ve las IPs de Cloudflare, no las del visitante, así que:
- Recupera la IP real antes de escribir el log. En nginx, usa el módulo realip con los rangos que publica Cloudflare. Sin esto, CrowdSec solo ve direcciones de la CDN, que sus listas blancas por defecto ignoran, y no te llega ninguna alerta.
# Una línea por rango de https://www.cloudflare.com/ips/
set_real_ip_from 173.245.48.0/20;
real_ip_header CF-Connecting-IP;
- Bloquea donde entra el tráfico. Un bloqueo en el firewall de tu servidor no frena las peticiones que pasan por el proxy, porque llegan desde Cloudflare. Bloquea en Cloudflare (con la acción
cloudflare-tokende Fail2ban o con el bouncer Cloudflare Worker de CrowdSec, que según CrowdSec funciona mejor con un plan de Workers de pago) o dentro de nginx con el bouncer de nginx de CrowdSec. - Acepta el 80/443 solo desde los rangos de Cloudflare, para que nadie se salte el proxy.
SSH no pasa por el proxy, así que ahí una jail de sshd o el bouncer de firewall funcionan como siempre. Elige CrowdSec si quieres los escenarios HTTP. Fail2ban para SSH más el WAF de Cloudflare para la web también es una combinación razonable.
Servidor con mucho Docker
CrowdSec, por dos motivos:
- Dónde cae el bloqueo. El tráfico hacia un puerto publicado de un contenedor pasa por FORWARD, no por INPUT. Fail2ban bloquea en INPUT por defecto, así que el contenedor sigue accesible desde la IP bloqueada. Es el mismo mecanismo por el que Docker se salta UFW. El bouncer de nftables de CrowdSec se engancha a input y a forward por defecto. En modo iptables, añade
DOCKER-USERaiptables_chainsen la configuración del bouncer. - Dónde están los logs. Los logs de los contenedores no están en
/var/log. CrowdSec tiene una fuente de datos Docker que los lee directamente. Con Fail2ban tienes que llevarlos a algún sitio donde pueda leerlos.
Si te quedas con Fail2ban, pon chain = DOCKER-USER en la jail con una acción basada en iptables, como banaction = iptables-allports. La variante allports importa porque en DOCKER-USER el puerto de destino es el interno del contenedor, no el publicado.
¿Los dos a la vez?
Se puede, pero tiene poco sentido analizar el mismo log dos veces. Si quieres ambos, repártelos por servicio: Fail2ban para SSH y CrowdSec para la parte web.
5. Dónde encaja PSAD
PSAD lee las entradas LOG de iptables en el log del kernel y las puntúa para detectar escaneos de puertos (SYN, FIN, NULL, Xmas, etc.). Puede bloquear automáticamente, pero viene desactivado.
Importa más su estado que sus funciones. La última versión es la 2.4.6, de agosto de 2018, y el último commit en GitHub es de noviembre de 2018. Debian 12 y 13 lo siguen empaquetando. El código solo conoce iptables; no tiene soporte para nftables.
En un VPS que solo abre los puertos que necesita, los escaneos son ruido de fondo. Saber que te han escaneado no cambia lo que tienes que hacer. Sáltate PSAD salvo que uses iptables y quieras alertas de escaneo en concreto.
6. ¿De verdad está bloqueando algo?
Instalar es la mitad del trabajo. Comprueba que los bloqueos ocurren.
Fail2ban:
sudo fail2ban-client status # jails activas
sudo fail2ban-client status sshd # fallos y bloqueos de sshd
sudo fail2ban-client banned # todas las IPs bloqueadas, por jail
En status sshd, mira "Total failed" y "Total banned". Si tu log de autenticación muestra intentos fallidos pero "Total failed" sigue en 0, la jail lee la fuente equivocada (el caso de auth.log en Debian 12 de más arriba). Con una acción de nftables, sudo nft list table inet f2b-table muestra el set real del firewall.
CrowdSec:
sudo cscli decisions list # bloqueos locales
sudo cscli decisions list -a # incluida la blocklist de la comunidad
sudo cscli bouncers list # ¿hay un bouncer registrado y consultando?
sudo cscli metrics show bouncers # tráfico realmente descartado, por origen
sudo cscli metrics show acquisition # ¿se leen y se parsean tus logs?
Si cscli bouncers list no muestra ningún bouncer, no se está bloqueando nada, diga lo que diga decisions list. Si las métricas de adquisición marcan cero en "Lines parsed", CrowdSec está leyendo un log que no sabe interpretar, o el archivo equivocado.
Para comparar el consumo de memoria en tu propio servidor, systemctl status fail2ban crowdsec muestra una línea "Memory" por cada servicio en marcha.
7. Revisa tu VPS con SecuryBlack
Elijas la herramienta que elijas, solo sirve si está funcionando y el resto del servidor está en orden.
¿Quieres un primer vistazo sin registrarte? Lanza la comprobación gratuita de solo lectura. No envía nada a ningún sitio:
curl -fsSL https://securyblack.com/audit.sh | sudo sh
SecuryBlack es un panel alojado que monitoriza y gestiona tu propio VPS. Su auditoría de seguridad, que ejecuta nuestro agente open source en Rust FerroSentry, revisa el login SSH de root y con contraseña, el firewall, los puertos de Docker publicados por encima de UFW, si tienes Fail2ban o CrowdSec instalado, las bases de datos que escuchan más allá de localhost y las actualizaciones de seguridad pendientes. Cada hallazgo viene con el comando exacto para corregirlo, y el hardening en un clic solo se aplica cuando tú lo confirmas. Es gratis durante la beta.