Condivisione di IP vietati fail2ban


18

Sto usando Fail2ban su tutti i server con servizi visibili pubblicamente e mi chiedo:

  1. Esiste un modo semplice per condividere gli IP vietati tra host che controllo?
  2. Esiste un servizio là fuori che raccoglie e pubblica quei dati?

Ricevo innumerevoli tentativi di accesso dal primo giorno di installazione di questo server.


2
Benvenuti in Internet. Non ha senso pubblicare questo elenco: tutti conosciamo fin troppo bene questa situazione.
Sven

1
Grazie. Credo che gli esempi siano belli da avere quando descrivono qualcosa. Sentiti libero di ignorarli se conosci meglio.
ndemou,

Ho rimosso l'elenco IP e ne ho approfittato per trasformare la tua domanda in una domanda. Non solo non è utile pubblicare l'elenco, ma ingombra la domanda e sarà rapidamente superata.
gparent

2
Inoltre il mio suggerimento è quello di rimuovere Fail2ban e smettere di preoccuparsene. Se hai disattivato l'autenticazione con password, c'è ben poco altro che puoi fare. fail2ban è stato sfruttato in passato e l'aggiunta di un potenziale buco di sicurezza che non fornisce assolutamente alcun vantaggio è una perdita netta.
gparent

@gparent: per quanto riguarda i tuoi suggerimenti: grazie - non avevo mai visto la cronologia degli exploit fail2ban prima. Per la sicurezza, S / WI si aspetterebbe un track record migliore. Per quanto riguarda le tue modifiche: non credo sia bene modificare così tanto una domanda. Se è una cattiva domanda, lascia che il poster ne subisca le conseguenze. Comunque lo lascerò com'è adesso.
ndemou,

Risposte:


8

Una volta ho visto un sistema per centralizzare i dati fail2ban su questo sito e ho creato una versione modificata. Il database è lo stesso, ma ho cambiato e creato alcuni script.

Il mio sistema ha 4 componenti:

  1. database fail2ban

    È un database MySQL che contiene solo una tabella 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

    Ogni volta che un host viene bandito, popolerà il database:

    
    <?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

    Lo metti in esecuzione su crontab, ogni minuto. Recupererà gli ultimi host aggiunti e li bandirà.

    
    <?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

    Questo file va in / etc / fail2ban e ha la configurazione del database e la selezione della jail.

    
    <?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');
    
    ?>
    

Crea quei file e modifica la configurazione da fail2ban:

Dopo la riga con actionban = .....una nuova riga inserita per invocare lo script PHP:

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

L'uso di questa struttura su tutti i tuoi server assicurerà che ogni volta che un host viene bannato su un server, anche tutti gli altri server lo vieteranno.


3

Quindi ho fatto molte ricerche su come farlo dopo aver visto lo stesso indirizzo IP colpire il mio cluster di server Web uno dopo l'altro. Dal momento che sto usando AWS ho pensato che potrebbe esserci un modo semplice e che funziona magnificamente nei miei primi due giorni di test di 5 server.

La prima cosa che raccomando è disabilitare temporaneamente SELinux, ci occuperemo alla fine. Non sono un esperto SELinux ma quello che ho fatto funziona finora.

Il requisito principale è una fonte di file condivisa, utilizzo AWS EFS. Una volta eseguito il provisioning e il montaggio della nuova unità, ho modificato logtarget all'interno di /etc/fail2ban/fail2ban.conf in una sottocartella nell'unità EFS.

logtarget = /efsmount/fail2ban/server1.log

Quindi ho scritto un filtro semplice e l'ho inserito in /etc/fail2ban/filter.d/fail2ban-log.conf

[Definition]

failregex = .* Ban <HOST>

ignoreregex =

Aggiunto il 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

Quindi riavviato fail2ban

sudo fail2ban-client reload

Fin qui tutto bene! No, la parte dolorosa è SELinux. Dopo aver lasciato che fail2ban funzionasse per un po 'ho eseguito questo comando che avrebbe permesso fail2ban attraverso i filtri.

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

Audit2allow ti dirà di eseguire questo comando

sudo semodule -i fail2ban-nfs.pp

Sto ancora controllando i miei registri SELinux qua e là per vedere se ci sono altri rifiuti. Se qualcuno ha un suggerimento su come ottenere SELinux chiaro con un altro metodo sarebbe fantastico.

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

A questo punto stavo ancora riscontrando errori al riavvio di fail2ban. C'è un bug quando si utilizza action = action_mwl in jail.local. Dopo un po 'di ricerche su google ho trovato questo che funziona finora. Da quello che ho letto è a causa delle interruzioni di riga nella direttiva logpath che punta a più file. Ho provato con virgole, spazi, ecc. Nient'altro ha funzionato 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

Non dimenticare di riaccendere SELinux!


Come te, ho investito molto impegno in fail2ban (ho pubblicato questa domanda) ma dopo un po 'più di ricerca ho preso il consiglio di gparent per rimuovere fail2ban (vedi commenti sulla domanda)
ndemou

2

L'ho appena implementato e finora sembra funzionare bene. Tuttavia, ho dovuto aggiornare parte del php perché gli script nella risposta originale utilizzano funzioni obsolete.

Ecco gli script aggiornati

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);
?>

Inoltre, ovunque posizioniate l'azione fail2ban.php, deve essere rientrato tanto quanto la linea sopra di essa. Per esempio:

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

Altrimenti fail2ban non si avvierà. Spero che questo aiuti chiunque cerchi di implementarlo.


1

Un'alternativa a fail2banè DenyHosts che viene fornito con una funzionalità di sincronizzazione. L'installazione è abbastanza simile a fail2ban, vedi il tutorial di Cyberciti per maggiori dettagli .

Il problema è che il servizio di sincronizzazione è centralizzato e il codice sorgente del lato server non sembra essere disponibile, quindi non puoi facilmente avviare il tuo servizio DenyHosts e devi fare affidamento su terze parti (che potrebbe andare bene per alcuni casi d'uso).


FWIW il link al servizio di sincronizzazione è giù oggi
ndemou

0

Si e si. Entrambi possono essere fatti.

È necessario trovare un meccanismo adatto per condividere l'elenco di IP. Ad esempio, se usi AWS potresti sfruttare s3. È possibile utilizzare rsync tra host Linux o un database comune a tutti gli host. Potresti interrompere un servizio con il tuo linguaggio di programmazione preferito che fornisce un'API riposante a tua scelta.

In termini di condivisione dell'elenco alleato pubblico è possibile creare un sito Web e ospitare un semplice file di testo, alcuni già forniscono tali elenchi (non di crowdfunding di cui io sia a conoscenza). Come creare il proprio sito / servizio sarebbe al di fuori dell'ambito di una risposta, tuttavia non dovrebbe essere tremendamente difficile da fare.


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

Un'installazione abbastanza manuale sarebbe quella di cambiare la configurazione che chiama iptablesper aggiornare le regole in modo che chiami uno script di tua ideazione che scorre attraverso un elenco di host (letto da un file?) Ed effettua iptableschiamate su ciascuno tramite SSH. Avresti bisogno di un'autorizzazione basata su chiave tra tutti gli host configurati affinché funzioni. Gli strumenti di automazione dell'amministratore come le marionette possono semplificare l'impostazione e la manutenzione. Questo non sarebbe terribilmente efficiente, ma a meno che tu non veda un'enorme quantità di traffico sondaggio (e / o abbia un numero enorme di host), sono sicuro che sarebbe abbastanza buono. Se hai solo pochi host, non è nemmeno necessario eseguire il ciclo di un file: configura ciascuno per chiamare semplicemente gli altri in ordine. Lo sforzo di scripting sarà minimo.

Is there a way to share banned IPs publicly?

Non ci sono dubbi in molti modi. Chiedi agli script sopra di rilasciare i dati in un DB e fai in modo che i client leggano da essi, eseguano il polling per le nuove regole e le eseguano quando arrivano. Il semplice "esegui una regola come la vedi" non sarà perfetto se molti gli host inviano informazioni, ad esempio questo caso:

  1. Alle 12:00 il server 1 dice "ban host X now" e "unban host X in un'ora".
  2. Alle 12:45 il server 2 dice "ban host X now" e "unban host X in un'ora".
  3. La sovrapposizione significa che il server 3 vieterà l'host X per un'ora, non un'ora + 45 minuti se si seguono le istruzioni in ordine.

ma questo non dovrebbe essere un problema significativo e, se diventi un po 'più intelligente con il database, puoi gestire più invii in modo più pulito se decidi che ne vale la pena.

Eseguirlo come servizio pubblico ti aprirebbe a un mondo di problemi di amministrazione però:

  • Gestire la larghezza di banda e altre risorse se guadagni molti utenti.
  • Organizzare e applicare metodi di pagamento se si tenta di affrontare il problema delle risorse addebitando l'accesso in qualche modo.
  • Affrontando i tentativi di inquinare il tuo database, un cattivo attore sta cercando di far bandire un concorrente dai luoghi che si iscrivono alla lista come inconveniente commerciale o tentativo di ricatto.
  • Gestire i reclami quando qualcuno viene bandito e pensa che non dovrebbero esserlo.
  • Trattare con attacchi DDoS che vi entrano se il servizio è affatto riuscito a disturbare i bot di qualcuno.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.