Compartir IPs prohibidas fail2ban


18

Estoy usando fail2ban en todos los servidores con servicios visibles públicamente y me pregunto:

  1. ¿Hay una manera fácil de compartir IP prohibidas entre los hosts que controlo?
  2. ¿Existe algún servicio que recopile y publique esos datos?

He recibido innumerables intentos de inicio de sesión desde el día 1 de configuración de este servidor.


2
Bienvenido al internet. No tiene sentido publicar esta lista: todos conocemos esta situación demasiado bien.
Sven

1
Gracias. Creo que es bueno tener ejemplos al describir algo. Siéntase libre de ignorarlos si lo sabe mejor.
ndemou

Eliminé la lista de IP y aproveché la oportunidad para convertir su pregunta en una pregunta. No solo no tiene sentido publicar la lista, sino que también abarrota la pregunta y quedará desactualizada rápidamente.
gparent

2
También mi sugerencia es eliminar fail2ban y dejar de preocuparme por esto. Si ha desactivado la autenticación de contraseña, hay muy poco más que pueda hacer. fail2ban ha sido explotado en el pasado y agregar un agujero de seguridad potencial que no proporciona absolutamente ningún beneficio es una pérdida neta.
gparent

@gparent: Respecto a sus sugerencias: Gracias. Nunca antes había visto el historial de exploits fail2ban. Por seguridad, S / WI esperaría un mejor historial. Con respecto a sus ediciones: no creo que sea bueno alterar tanto una pregunta. Si es una mala pregunta, deje que el cartel sufra las consecuencias. De todos modos lo dejaré como está ahora.
ndemou

Respuestas:


8

Una vez vi un sistema para centralizar datos de fail2ban en este sitio , y creé una versión modificada. La base de datos es la misma, pero cambié y creé algunos scripts.

Mi sistema tiene 4 componentes:

  1. base de datos fail2ban

    Es una base de datos MySQL que contiene solo una tabla erp_core_fail2ban:

    CREATE TABLE IF NOT EXISTS 'erp_core_fail2ban' (
      'id' bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      'hostname' varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      'created' datetime NOT NULL,
      'name' text COLLATE utf8_unicode_ci NOT NULL,
      'protocol' varchar(16) COLLATE utf8_unicode_ci NOT NULL,
      'port' varchar(32) COLLATE utf8_unicode_ci NOT NULL,
      'ip' varchar(64) COLLATE utf8_unicode_ci NOT NULL,
      PRIMARY KEY ('id'),
      KEY 'hostname' ('hostname','ip')
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    
  2. fail2ban.php

    Cada vez que se prohíbe un host, rellenará la base de datos:

    
    <?php
    require_once("/etc/fail2ban/phpconfig.php");
    
    $name = $_SERVER["argv"][1];
    $protocol = $_SERVER["argv"][2];
    $port = $_SERVER["argv"][3];
    if (!preg_match('/^\d{1,5}$/', $port))
        $port = getservbyname($_SERVER["argv"][3], $protocol);
    $ip = $_SERVER["argv"][4];
    
    $hostname = gethostname();
    
    $query = "INSERT INTO 'erp_core_fail2ban' set hostname='" . addslashes($hostname) . "', name='" . addslashes($name) ."', protocol='" . addslashes($protocol) . "', port='" . addslashes($port) . "', ip='" . addslashes($ip) . "', created=NOW()";
    $result = mysql_query($query) or die('Query failed: ' . mysql_error());
    mysql_close($link);
    exit;
    ?>
    
  3. cron2ban

    Pones esto para ejecutar en crontab, cada minuto. Recuperará los últimos hosts agregados y los prohibirá.

    
    <?php
    // phpconfig.php will have database configuration settings
    require_once("/etc/fail2ban/phpconfig.php");
    
    // file with only a line, containing the last id banned
    $lastbanfile="/etc/fail2ban/lastban";
    
    $lastban = file_get_contents($lastbanfile);
    
    // select only hosts banned after last check
    $sql = "select id, ip from erp_core_fail2ban where id > $lastban";
    $result = mysql_query($sql) or die('Query failed: ' . mysql_error());
    mysql_close($link);
    
    while ($row = mysql_fetch_array($result)) {
            //
            $id = $row['id'];
            $ip = $row['ip'];
    
    
        exec("fail2ban-client set $jail banip $ip");
    
    } // $id contains the last banned host, add it to the config file file_put_contents($lastbanfile, $id); ?>
  4. phpconfig

    Este archivo va a / etc / fail2ban y tiene configuración de base de datos y selección de cárcel.

    
    <?php
    // jail to be used
    $jail = "ssh";
    
    // file to keep the last ban
    $lastbanfile="/etc/fail2ban/lastban";
    
    // database configuration
    $dbserver="localhost";
    $dbuser="root";
    $dbpass="root";
    $dbname="fail2ban";
    
    // connect to database
    $link = mysql_connect($dbserver, $dbuser, $dbpass) or die('Could not connect: ' . mysql_error());
    mysql_select_db($dbname) or die('Could not select database');
    
    ?>
    

Cree esos archivos y cambie la configuración de fail2ban:

Después de la línea con actionban = .....una nueva fila insertada para invocar el script PHP:

/root/fail2ban.php <name> <protocol> <port> <ip>

El uso de esta estructura en todos sus servidores asegurará que cada vez que un host sea bloqueado en un servidor, todos los demás servidores también lo bloquearán.


3

Así que hice un montón de investigación sobre cómo hacer esto después de ver que la misma dirección IP golpeó mi clúster de servidores web uno tras otro. Como estoy usando AWS, pensé que podría haber una manera fácil y que funcionaba maravillosamente en mis primeros dos días de prueba de 5 servidores.

Lo primero que recomiendo es deshabilitar temporalmente SELinux, lo trataremos al final. No soy un experto en SELinux, pero lo que hice funciona hasta ahora.

El requisito principal es un origen de archivo compartido, yo uso AWS EFS. Una vez que se aprovisionó y montó la nueva unidad, cambié el objetivo de log dentro de /etc/fail2ban/fail2ban.conf a una subcarpeta en la unidad EFS.

logtarget = /efsmount/fail2ban/server1.log

Luego escribí un filtro simple y lo coloqué en /etc/fail2ban/filter.d/fail2ban-log.conf

[Definition]

failregex = .* Ban <HOST>

ignoreregex =

Se agregó el filtro a /etc/fail2ban/jail.local

[fail2ban-log]
enabled = true
port = http,https
findtime = 86400 ; 1 day
logpath  = /efsmount/fail2ban/server1.log
        /efsmount/fail2ban/server2.log
        /efsmount/fail2ban/server3.log
        /efsmount/fail2ban/server4.log
maxretry = 1

Luego reinició fail2ban

sudo fail2ban-client reload

¡Hasta aquí todo bien! No, la parte dolorosa es SELinux. Después de dejar que fail2ban se ejecute por un momento, ejecuté este comando que permitiría a fail2ban a través de los filtros.

sudo grep fail2ban /var/log/audit/audit.log | sudo audit2allow -M fail2ban-nfs

Audit2allow le dirá que ejecute este comando

sudo semodule -i fail2ban-nfs.pp

Todavía estoy revisando mis registros SELinux aquí y allá para ver si hay más negaciones. Si alguien tiene un consejo sobre cómo obtener ese SELinux claro con otro método, sería increíble.

sudo cat /var/log/audit/audit.log |grep fail2ban |grep denied

En este punto, todavía recibía errores al reiniciar fail2ban. Hay un error al usar action = action_mwl en jail.local. Después de buscar un poco en Google, encontré esto que está funcionando hasta ahora. Por lo que leí es por los saltos de línea en la directiva logpath que apunta a múltiples archivos. Intenté con comas, espacios, etc. nada más funcionó con action_mwl.

action_mwm = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             %(mta)s-whois-matches[name=%(__name__)s, dest="%(destemail)s", chain="%(chain)s"]

action = %(action_mwm)s

¡No olvide volver a encender SELinux!


Al igual que usted, he invertido mucho esfuerzo en fail2ban (he publicado esta pregunta), pero después de un poco más de investigación, he seguido el consejo de gparent para eliminar fail2ban (ver comentarios sobre la pregunta)
ndemou

2

Acabo de implementar esto y hasta ahora parece estar funcionando bien. Sin embargo, tuve que actualizar algunos de los php porque los scripts en la respuesta original usan funciones obsoletas.

Aquí están los guiones actualizados

phpconfig.php

#!/usr/bin/php
<?php
// jail to be used
$jail = "ssh";

// file to keep the last ban
$lastbanfile="/etc/fail2ban/lastban";

// database configuration
$dbserver="[your.mysql.hostname]";
$dbport="[sql.port.default.is.3306]";
$dbuser="[sql.user";
$dbpass="[sql.password]";
$dbname="[sql.table]";

// connect to database
$link = mysqli_connect($dbserver, $dbuser, $dbpass, $dbname, $dbport) or die('Could not connect: ' . mysqli_error());
mysqli_select_db($link,$dbname) or die('Could not select database');

?>

fail2ban.php

#!/usr/bin/php 
<?php
require_once("/etc/fail2ban/phpconfig.php");

$name = $_SERVER["argv"][1];
$protocol = $_SERVER["argv"][2];
$port = $_SERVER["argv"][3];
if (!preg_match('/^\d{1,5}$/', $port))
    $port = getservbyname($_SERVER["argv"][3], $protocol);
$ip = $_SERVER["argv"][4];

$hostname = gethostname();

$query = "INSERT INTO erp_core_fail2ban (hostname,created,name,protocol,port,ip) VALUES ('$hostname',NOW(),'$name','$protocol','$port','$ip')";
echo $query;
$result = mysqli_query($link,$query) or die('Query failed: ' . mysqli_error($link));
mysqli_close($link);
exit;
?>

cron2ban.php

#!/usr/bin/php
<?php
// phpconfig.php will have database configuration settings
require_once("/etc/fail2ban/phpconfig.php");

// file with only a line, containing the last id banned
$lastbanfile="/etc/fail2ban/lastban";

$lastban = file_get_contents($lastbanfile);
// select only hosts banned after last check
$sql = "SELECT id,ip FROM erp_core_fail2ban WHERE id > $lastban";
$result = mysqli_query($link,$sql) or die('Query failed: ' . mysqli_error($link));
mysqli_close($link);

while ($row = mysqli_fetch_array($result)) {
        //
        $id = $row['id'];
        $ip = $row['ip'];

    exec("fail2ban-client set $jail banip $ip");


}

// $id contains the last banned host, add it to the config file
file_put_contents($lastbanfile, $id);
?>

Además, donde sea que coloque la acción fail2ban.php, debe sangrarse tanto como la línea que se encuentra sobre ella. Por ejemplo:

actionban = ...
            /etc/fail2ban/fail2ban.php

De lo contrario, fail2ban no se iniciará. Espero que esto ayude a cualquiera que intente implementar esto.


1

Una alternativa a DenyHostsfail2ban es que viene con una funcionalidad de sincronización. La instalación es bastante similar a , vea el tutorial de Cyberciti para más detalles .fail2ban

El problema es que el servicio de sincronización está centralizado y el código fuente del lado del servidor no parece estar disponible, por lo que no puede iniciar fácilmente su propio servicio DenyHosts y tiene que depender de terceros (lo que puede estar bien para algunos casos de uso).


FWIW el enlace al servicio de sincronización está caído hoy
ndemou

0

Si y si. Ambos se pueden hacer.

Debe encontrar un mecanismo adecuado para compartir la lista de IP. Si usa AWS, por ejemplo, podría aprovechar s3. Puede usar rsync entre hosts Linux o una base de datos común a todos los hosts. Podría activar un servicio con su lenguaje de programación favorito que proporciona una API tranquila, la elección es suya.

En términos de compartir la lista de aliados públicos, podría crear un sitio web y alojar un archivo de texto simple, algunos ya proporcionan dichas listas (no sé de fuentes multitudinarias). Cómo crear su propio sitio / servicio estaría fuera del alcance de una respuesta, sin embargo, no debería ser terriblemente difícil de hacer.


0
Is there an easy way to share banned IPs between hosts I control?

Una configuración bastante manual sería cambiar la configuración que llama iptablesa actualizar las reglas para que llame a un guión de su propia creación que recorre una lista de hosts (¿leído de un archivo?) Y realiza las iptablesllamadas en cada uno a través de SSH. Necesitaría una autenticación basada en claves entre todos los hosts configurados para que esto funcione. Las herramientas de automatización de administración como Puppet pueden facilitar la configuración y el mantenimiento. Esto no sería terriblemente eficiente, pero a menos que vea una gran cantidad de tráfico de sondeo (y / o tenga una gran cantidad de hosts), entonces estoy seguro de que sería lo suficientemente bueno. Si solo tiene unos pocos hosts, entonces ni siquiera necesita recorrer un archivo: configure cada uno para llamar a los otros en orden. El esfuerzo de scripting será mínimo.

Is there a way to share banned IPs publicly?

No hay duda de muchas maneras. Haga que las secuencias de comandos anteriores coloquen los datos en una base de datos y haga que los clientes lean eso, sondeen las nuevas reglas y las ejecuten a medida que entran. El simple "ejecutar una regla como la ve" no será perfecto si muchos Los hosts están enviando información, por ejemplo este caso:

  1. A las 12:00 el servidor 1 dice "prohibir el host X ahora" y "desbancar el host X en una hora".
  2. A las 12:45, el servidor 2 dice "prohibir el host X ahora" y "desbancar el host X en una hora".
  3. La superposición significa que el servidor 3 prohibirá el host X durante una hora, no una hora + 45 minutos si sigue las instrucciones en orden.

pero esto no debería ser un problema importante, y si se vuelve un poco más inteligente con la base de datos, podría administrar varias presentaciones de manera más limpia si decidiera que valió la pena el esfuerzo.

Sin embargo, ejecutar eso como un servicio público te abriría a un mundo de problemas administrativos:

  • Administrar el ancho de banda y otros recursos si gana muchos usuarios.
  • Organizar y hacer cumplir los métodos de pago en caso de que trate de resolver el problema de los recursos cobrando por el acceso de alguna manera.
  • Al tratar con los intentos de contaminar su base de datos, un mal actor que intenta que un competidor sea expulsado de los lugares que se suscriben a la lista como un inconveniente comercial o un intento de chantaje.
  • Tratar las quejas cuando alguien está prohibido y piensa que no debería estarlo.
  • Tratar con ataques DDoS, que se vienen si su servicio es del todo exitoso en molestar a los robots de alguien.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.