Partage d'adresses IP interdites par fail2ban

18

J'utilise fail2ban sur tous les serveurs avec des services visibles publiquement et je me demande:

  1. Existe-t-il un moyen simple de partager des adresses IP interdites entre les hôtes que je contrôle?
  2. Existe-t-il un service qui collecte et publie ces données?

J'ai eu d'innombrables tentatives de connexion depuis le premier jour de configuration de ce serveur.

ndemou
la source
2
Bienvenue sur Internet. Il est inutile de publier cette liste - nous connaissons tous trop bien cette situation.
Sven
1
Merci. Je pense que les exemples sont agréables à avoir quand on décrit quelque chose. N'hésitez pas à les ignorer si vous en savez mieux.
ndemou
J'ai supprimé la liste d'adresses IP et en ai profité pour transformer votre question en question. Non seulement la publication de la liste est inutile, mais elle encombre également la question et sera rapidement dépassée.
gparent
2
Ma suggestion est également de supprimer fail2ban et de cesser de s'en soucier. Si vous avez désactivé l'authentification par mot de passe, vous ne pouvez pas faire grand-chose d'autre. fail2ban a été exploité dans le passé et l'ajout d'un trou de sécurité potentiel qui n'apporte absolument aucun avantage est une perte nette.
gparent
@gparent: Concernant vos suggestions: Merci - Je n'ai jamais regardé l'historique des exploits fail2ban auparavant. Pour la sécurité, S / WI s'attendrait à un meilleur bilan. En ce qui concerne vos modifications: je ne pense pas qu'il soit bon de modifier une question autant. Si c'est une mauvaise question, laissez l'affiche en subir les conséquences. Quoi qu'il en soit, je vais le laisser tel qu'il est maintenant.
ndemou

Réponses:

8

J'ai vu une fois un système de centralisation des données fail2ban sur ce site , et créé une version modifiée. La base de données est la même, mais j'ai changé et créé des scripts.

Mon système a 4 composants:

  1. base de données fail2ban

    C'est une base de données MySQL contenant une seule table 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

    Chaque fois qu'un hôte est banni, il remplira la base de données:

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

    Vous mettez cela à exécuter sur crontab, chaque minute. Il récupérera les derniers hôtes ajoutés et les bannira.

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

    Ce fichier va dans / etc / fail2ban et a une configuration de base de données et une sélection de prison.

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

Créez ces fichiers et modifiez la configuration à partir de fail2ban:

Après la ligne avec actionban = .....une nouvelle ligne insérée pour appeler le script PHP:

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

L'utilisation de cette structure sur tous vos serveurs garantira que chaque fois qu'un hôte sera banni sur un serveur, tous les autres serveurs l'interdiront également.

ThoriumBR
la source
3

J'ai donc fait un tas de recherches sur la façon de le faire après avoir regardé la même adresse IP frapper mon cluster de serveurs Web l'un après l'autre. Étant donné que j'utilise AWS, j'ai pensé qu'il pourrait y avoir un moyen simple et que cela fonctionnerait à merveille au cours de mes deux premiers jours de test de 5 serveurs.

La première chose que je recommande est de désactiver temporairement SELinux, nous nous en occuperons à la fin. Je ne suis pas un expert SELinux mais ce que j'ai fait fonctionne jusqu'à présent.

La principale exigence est une source de fichiers partagée, j'utilise AWS EFS. Une fois le nouveau lecteur provisionné et monté, j'ai changé logtarget dans /etc/fail2ban/fail2ban.conf en un sous-dossier dans le lecteur EFS.

logtarget = /efsmount/fail2ban/server1.log

Ensuite, j'ai écrit un filtre simple et l'ai placé dans /etc/fail2ban/filter.d/fail2ban-log.conf

[Definition]

failregex = .* Ban <HOST>

ignoreregex =

Ajout du filtre à /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

Puis redémarré fail2ban

sudo fail2ban-client reload

Jusqu'ici tout va bien! Non, la partie douloureuse est SELinux. Après avoir laissé fail2ban fonctionner un peu, j'ai exécuté cette commande qui permettrait à fail2ban de passer par les filtres.

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

Audit2allow vous dira d'exécuter cette commande

sudo semodule -i fail2ban-nfs.pp

Je vérifie toujours mes journaux SELinux ici et là pour voir s'il y a d'autres refus. Si quelqu'un a une astuce pour obtenir ce SELinux clair avec une autre méthode, ce serait génial.

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

À ce stade, je recevais toujours des erreurs lors du redémarrage de fail2ban. Il y a un bogue lors de l'utilisation de action = action_mwl dans jail.local. Après un peu de recherche sur Google, j'ai trouvé cela qui fonctionne jusqu'à présent. D'après ce que j'ai lu, c'est à cause des sauts de ligne dans la directive logpath pointant vers plusieurs fichiers. J'ai essayé avec des virgules, des espaces, etc. rien d'autre ne fonctionnait avec 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

N'oubliez pas de réactiver SELinux!

prophoto
la source
Comme vous, j'ai investi beaucoup d'efforts dans fail2ban (j'ai posté cette question) mais après un peu plus de recherche, j'ai suivi les conseils de gparent pour supprimer fail2ban (voir les commentaires sur la question)
ndemou
2

Je viens de l'implémenter et jusqu'à présent, cela semble bien fonctionner. Cependant, j'ai dû mettre à jour une partie du php car les scripts de la réponse d'origine utilisent des fonctions obsolètes.

Voici les scripts mis à jour

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

De plus, partout où vous placez l'action fail2ban.php, elle doit être mise en retrait autant que la ligne au-dessus. Par exemple:

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

Sinon, fail2ban ne démarre pas. J'espère que cela aide quiconque essaie de déployer cela.

Simba Lion
la source
1

Une alternative à fail2banest DenyHosts qui est livré avec une fonctionnalité de synchronisation. L'installation est assez similaire à fail2ban, voir le tutoriel de Cyberciti pour plus de détails .

Le problème est que le service de synchronisation est centralisé et que le code source côté serveur ne semble pas être disponible, donc vous ne pouvez pas facilement démarrer votre propre service DenyHosts et vous devez vous fier à une tierce partie (ce qui pourrait convenir à certains cas d'utilisation).

Tombart
la source
FWIW le lien vers le service de synchronisation est en panne aujourd'hui
ndemou
0

Oui et oui. Les deux peuvent être effectués.

Vous devez trouver un mécanisme approprié pour partager la liste des adresses IP. Si vous utilisez AWS par exemple, vous pouvez profiter de s3. Vous pouvez utiliser rsync entre des hôtes Linux ou une base de données commune à tous les hôtes. Vous pouvez créer un service avec votre langage de programmation préféré qui fournit une API reposante à vous de choisir.

En termes de partage de la liste allié public, vous pouvez créer un site Web et héberger un simple fichier texte, certains fournissent déjà de telles listes (pas de source ouverte que je sache). Comment créer votre propre site / service serait hors de portée d'une réponse, mais ne devrait pas être très difficile à faire.

Drew Khoury
la source
0
Is there an easy way to share banned IPs between hosts I control?

Une configuration assez manuelle serait de changer la configuration qui appelle iptablespour mettre à jour les règles afin qu'elle appelle un script de votre propre conception qui boucle à travers une liste d'hôtes (lue depuis un fichier?) Et effectue les iptablesappels sur chacun via SSH. Vous auriez besoin d'une authentification basée sur des clés entre tous les hôtes configurés pour que cela fonctionne. Les outils d'automatisation d'administration tels que les marionnettes peuvent faciliter la configuration et la maintenance. Ce ne serait pas terriblement efficace, mais à moins que vous ne voyiez une énorme quantité de trafic de sondage (et / ou un nombre énorme d'hôtes), je suis sûr que ce serait suffisant. Si vous n'avez que quelques hôtes, vous n'avez même pas besoin de parcourir un fichier: configurez chacun pour simplement appeler les autres dans l'ordre. L'effort de script sera minime.

Is there a way to share banned IPs publicly?

Il y a sans aucun doute de nombreuses façons. Demandez au (x) script (s) ci-dessus de déposer les données dans une base de données et demandez aux clients de les lire, interrogeant les nouvelles règles et les exécutant au fur et à mesure qu'elles entrent. Le simple "exécuter une règle telle que vous la voyez" ne sera pas parfait si beaucoup les hôtes soumettent des informations, par exemple ce cas:

  1. À midi, le serveur 1 dit «bannir l'hôte X maintenant» et «annuler l'hôte X dans une heure».
  2. À 12 h 45, le serveur 2 dit «bannir l'hôte X maintenant» et «annuler l'hôte X dans une heure».
  3. Le chevauchement signifie que le serveur 3 bannira l'hôte X pendant une heure, pas une heure + 45 minutes s'il suit les instructions dans l'ordre.

mais cela ne devrait pas être un problème important, et si vous devenez un peu plus intelligent avec la base de données, vous pouvez gérer plusieurs soumissions plus proprement si vous décidez que cela en vaut la peine.

L'exécuter en tant que service public vous ouvrirait cependant à un monde de tracas administratifs:

  • Gérer la bande passante et d'autres ressources si vous gagnez beaucoup d'utilisateurs.
  • Organiser et appliquer des méthodes de paiement si vous essayez de résoudre le problème de ressources en facturant l'accès d'une manière ou d'une autre.
  • Traitant des tentatives de polluer votre base de données, un mauvais acteur essaie d'obtenir un concurrent banni des lieux abonnés à la liste comme inconvénient commercial ou tentative de chantage.
  • Traiter les plaintes lorsqu'une personne est interdite et pense qu'elle ne devrait pas l'être.
  • Faire face à des attaques DDoS qui va venir si votre service est tout réussi à incommoder les robots collecteurs de quelqu'un.
David Spillett
la source