Security para mailcow — guía
Instalación
- El módulo viene con el mailcow Toolkit 0.6.0 o más reciente (un paquete, una licencia por producto). En el host de mailcow, como root, ejecuta el instalador del Toolkit como siempre:
sudo ./install.sh --mailcow-dir /opt/mailcow-dockerized --name <instance>, o actualiza el Toolkit desde System → Updates (Toolkit). El instalador copiadata/web/mlw-security/, crea las tablas del módulo en la base de datos de mailcow, añade la entrada de menú y el temporizadormlw-mailcow-security-<instance>.timer(una vez por minuto) y recarga php-fpm. - Abre System → Security en el menú de administración de mailcow.
Licencia
Abre System → Updates (Toolkit) y busca la tarjeta Security for mailcow: pega la clave y actívala, o empieza la prueba de 30 días. Por consola: php /web/mlw-toolkit/cli.php activate mailcow-security <KEY> dentro de php-fpm-mailcow. La licencia se comprueba a diario; sin internet el módulo funciona 7 días desde la última comprobación correcta.
Sin licencia válida no se lee, detecta, bloquea ni envía nada; los bloqueos hechos antes se siguen levantando cuando caducan, y el historial se queda. No se borra nada.
La primera pasada
La primera pasada importa lo que mailcow aún conserva en sus registros (normalmente las últimas horas) y no bloquea ni alerta. A partir de ahí la tarea lee solo las líneas nuevas, cada minuto. Overview → Status muestra la última pasada; si una línea dice que se perdieron líneas, mailcow recortó sus registros antes de que se leyeran (un servidor con mucha actividad): sube LOG_LINES en mailcow.conf.
Qué se lee
| Fuente | Qué se convierte en registro |
|---|---|
dovecot (redis DOVECOT_MAILLOG) |
inicios de sesión IMAP / POP3 / ManageSieve fallidos (con el número de intentos), conexiones que nunca inician sesión, inicios de sesión correctos |
postfix (redis POSTFIX_MAILLOG) |
SMTP AUTH fallidos, envíos autenticados, rechazos de rspamd, rechazos por listas de bloqueo DNS, intentos de relay, sondeos de protocolo (conexión perdida tras EHLO, pipelining, errores TLS, postscreen) |
SOGo (redis SOGO_LOG) |
inicios de sesión en el webmail fallidos y correctos |
fail2ban (redis NETFILTER_LOG) |
cada bloqueo que hace el propio fail2ban de mailcow |
| servidor web (registro de docker, a través del agente del host) | respuestas 4xx: rutas de exploits conocidas (/.env, /.git, wp-login.php, phpMyAdmin, …) y otros 404 |
| php-fpm (registro de docker, a través del agente del host) | inicios de sesión fallidos en la interfaz y la API de mailcow |
Se descartan los registros de direcciones privadas (los propios contenedores de mailcow, un proxy inverso delante de mailcow) y de las redes que ignores. Los registros se cuentan por minuto, dirección, buzón y fuente; el historial se guarda 90 días por defecto (Settings).
Resumen
- Totales de las últimas 24 horas por tipo; un clic abre los eventos correspondientes.
- Últimos 14 días: inicios de sesión fallidos, escaneos y spam por día (los valores están en Values).
- Status: modo (solo vigilancia o protección automática), bloqueos activos, bloqueos del propio fail2ban de mailcow, incidentes abiertos, la última pasada.
- Direcciones más activas con un botón Ban, buzones atacados, incidentes activos.
Reglas e incidentes
Una regla cuenta registros en una ventana deslizante. Cuando se alcanza el umbral abre un incidente; mientras el ataque continúa, se prolonga el mismo incidente, no se repite.
| Regla | Cuenta | Por defecto |
|---|---|---|
| Fuerza bruta en el inicio de sesión web | inicios de sesión fallidos en SOGo / interfaz de mailcow / API por dirección | 5 en 15 min → bloqueo 24 h |
| Fuerza bruta lenta | inicios de sesión fallidos por dirección a lo largo de un día | 20 en 24 h → bloqueo 24 h |
| Password spraying | buzones distintos en los que falló una dirección | 5 en 60 min → bloqueo 7 días |
| Reincidente | bloqueos de una dirección por el fail2ban de mailcow | 3 en 7 días → bloqueo 30 días |
| Escaneo de exploits web | peticiones a rutas de exploits / filtraciones | 3 en 30 min → bloqueo 7 días |
| Escaneo web de 404 | respuestas 404 por dirección | 40 en 30 min → alerta |
| Sondeo de relay | «Relay access denied» por dirección | 3 en 60 min → bloqueo 7 días |
| Escaneo de protocolo | conexiones que nunca inician sesión o rompen el protocolo | 30 en 60 min → alerta |
| Avalancha de spam | rechazos de rspamd y de listas de bloqueo por dirección | 20 en 60 min → alerta |
| Buzón atacado | fallos en un buzón desde al menos 5 direcciones | 30 en 60 min → alerta |
| Pico de envíos | mensajes enviados por un buzón | 300 en 60 min → alerta |
| Inicios de sesión desde muchas direcciones | direcciones distintas desde las que inicia sesión un buzón | 8 en 60 min → alerta |
| Inicio de sesión tras fallos | un primer inicio de sesión desde una dirección que falló en el buzón | 3 fallos en 24 h → alerta (critical) |
En Rules puedes desactivar cada regla y cambiar su umbral, su ventana, su acción y la duración del bloqueo (0 = permanente). Las reglas de dirección pueden alert o ban; las de buzón, alert, limit sending o disallow login. Reset to defaults las restablece todas.
Incidents las lista por estado (abierto, visto, resuelto, falso positivo), gravedad mínima y regla. False positive pone la dirección en la lista de permitidos y levanta sus bloqueos.
Acciones automáticas
El interruptor de arriba en Rules está apagado al principio: el módulo solo vigila, y cada incidente dice qué se habría hecho («would ban»). Déjalo así unos días, revisa los incidentes, ajusta las reglas y después actívalo. Los incidentes cuyo ataque sigue en curso se tratan en la siguiente pasada.
Nunca se bloquean automáticamente:
- las direcciones privadas y reservadas;
- la lista de permitidos del módulo (Settings) y la del fail2ban de mailcow (Configuration → Fail2ban);
- las direcciones públicas del propio servidor (de la comprobación de DNS inverso del Toolkit);
- con protect known addresses activado (por defecto), las direcciones que iniciaron sesión correctamente en un buzón en los últimos 30 días — a un compañero que se equivoca al escribir la contraseña no se le deja fuera.
Bloqueos
Un bloqueo pone la dirección o la red en la lista de bloqueo del fail2ban de mailcow. El netfilter de mailcow lo aplica en el cortafuegos, en todos los puertos de mailcow, en menos de un minuto, y lo ves en la propia página Fail2ban de mailcow. El módulo lo levanta cuando caduca; un bloqueo que borras en la página Fail2ban de mailcow cuenta como levantado.
Bans muestra los bloqueos del módulo (motivo, quién, hasta cuándo, estado en Cloudflare), los bloqueos temporales del propio fail2ban de mailcow (Lift o Make it longer), el resto de la lista de bloqueo de mailcow y el historial. El formulario de arriba bloquea una dirección o una red (CIDR) de 1 hora a 30 días, o de forma permanente; tu propia dirección actual se rechaza.
Si Manage external está activado en los ajustes de fail2ban de mailcow, netfilter no toca el cortafuegos: la página te avisa, y tu propio cortafuegos tiene que aplicar la lista de mailcow.
Cloudflare
Cuando los hosts web de mailcow (la interfaz, el webmail) están detrás del proxy de Cloudflare, los ataques web llegan a mailcow desde direcciones de Cloudflare y netfilter no puede detenerlos. En Settings → Cloudflare elige bans of the web rules and ticked manual bans o every ban: cada bloqueo se convierte entonces también en una IP Access Rule de Cloudflare («block») a nivel de cuenta, que cubre todas las zonas de la cuenta y se elimina junto con el bloqueo. Usa las credenciales de Cloudflare guardadas en System → DNS & Cloudflare; el token necesita Account → Account Firewall Access Rules → Edit (la Global API Key puede hacerlo). Cloudflare bloquea direcciones sueltas y los rangos /16 y /24 (IPv4), /32, /48 y /64 (IPv6).
Una dirección, un buzón
Haz clic en cualquier dirección para ver sus registros, los buzones que probó, sus inicios de sesión correctos, incidentes y bloqueos, su DNS inverso y enlaces a AbuseIPDB, ipinfo y Shodan; bloquéala, levanta su bloqueo o ponla en la lista de permitidos (opcionalmente también en la de mailcow).
Haz clic en cualquier buzón para ver las direcciones que lo probaron, con los fallos y los inicios de sesión correctos uno al lado del otro (una señal de aviso marca una dirección que tiene ambos), sus envíos, inicios de sesión e incidentes. Acciones, todas con las propias funciones de mailcow y registradas también por mailcow:
- Disallow login: el buzón sigue recibiendo correo, nadie puede iniciar sesión (el «disallow login» de mailcow); Allow login again lo deshace.
- End IMAP / POP3 sessions: dovecot cierra las sesiones al momento (a través del agente del host).
- Require a password change en el siguiente inicio de sesión.
- Limit sending a N mensajes por hora (Settings), o quitar el límite.
Alertas
En Settings → Alerts: la dirección de correo (vacía = la dirección de notificaciones del Toolkit), el token del bot de Telegram (cifrado; «-» lo elimina) y el id del chat, la gravedad mínima (por defecto: high), el máximo de alertas por hora (el resto se cuenta en la siguiente alerta), el idioma (inglés o rumano) y el resumen diario (después de las 07:00). Send a test alert comprueba los dos canales. Cada incidente nuevo de esa gravedad o superior genera una alerta, con un enlace a él.
Registro de auditoría y consola
Audit log lista cada acción: bloqueos, levantamientos, cambios en la lista de permitidos, estados de incidentes, acciones sobre cuentas, cambios de reglas y de ajustes — hechos por un administrador o por una regla.
Dentro de php-fpm-mailcow (docker compose exec -u www-data php-fpm-mailcow …):
php /web/mlw-security/cli.php status
php /web/mlw-security/cli.php ban 203.0.113.7 48 "reason"
php /web/mlw-security/cli.php unban 203.0.113.7
Desinstalación
sudo ./uninstall.sh levanta primero todos los bloqueos del módulo y después elimina los archivos y los temporizadores. Las tablas mlw_sec_* se quedan en la base de datos de mailcow (y en sus copias de seguridad).