Совместное использование fail2ban запрещенных IP-адресов


18

Я использую fail2ban на всех серверах с общедоступными службами, и мне интересно:

  1. Существует ли простой способ обмена запрещенными IP-адресами между хостами, которые я контролирую?
  2. Есть ли служба сбора и публикации этих данных?

Я получаю бесчисленные попытки входа в систему с первого дня установки этого сервера.


2
Добро пожаловать в интернет. Нет смысла публиковать этот список - мы все слишком хорошо знаем эту ситуацию.
Свен

1
Благодарю. Я считаю, что примеры хороши для описания чего-либо. Не стесняйтесь игнорировать их, если вы знаете лучше.
ndemou

Я удалил список IP-адресов и воспользовался возможностью, чтобы превратить ваш вопрос в вопрос. Не только нет смысла публиковать список, но также загромождает вопрос и быстро устареет.
gparent

2
Также я предлагаю удалить fail2ban и перестать беспокоиться об этом. Если вы отключили аутентификацию по паролю, вы можете сделать очень мало. В прошлом использовался fail2ban, и добавление потенциальной дыры в безопасности, которая не дает абсолютно никаких преимуществ, является чистым убытком.
gparent

@gparent: Что касается ваших предложений: Спасибо - я никогда не смотрел историю эксплойтов fail2ban. Для безопасности S / WI ожидал бы лучшего послужного списка. Что касается ваших правок: я не верю, что это хорошо, если вы так сильно меняете вопрос. Если это плохой вопрос, пусть постер пострадает от последствий. В любом случае, я оставлю все как есть.
ndemou

Ответы:


8

Однажды я увидел систему централизации данных fail2ban на этом сайте и создал модифицированную версию. База данных такая же, но я изменил и создал несколько скриптов.

Моя система имеет 4 компонента:

  1. база данных fail2ban

    Это база данных MySQL, содержащая только одну таблицу 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

    Каждый раз, когда хост забанен, он заполняет базу данных:

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

    Вы помещаете это в crontab каждую минуту. Он извлечет последние добавленные хосты и забанит их.

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

    Этот файл идет в / etc / fail2ban и имеет конфигурацию базы данных и выбор тюрьмы.

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

Создайте эти файлы и измените конфигурацию с fail2ban:

После строки с actionban = .....новой строкой, вставленной для вызова скрипта PHP:

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

Использование этой структуры на всех ваших серверах гарантирует, что каждый раз, когда один хост блокируется на одном сервере, все остальные серверы также будут его блокировать.


3

Поэтому я провел ряд исследований о том, как это сделать после того, как один и тот же ip-адрес попал в мой кластер веб-серверов один за другим. Поскольку я использую AWS, я подумал, что может быть простой способ, и он прекрасно работает в первые два дня тестирования 5 серверов.

Первое, что я рекомендую, это временно отключить SELinux, мы разберемся с ним в конце. Я не эксперт SELinux, но то, что я сделал, работает до сих пор.

Основное требование - общий источник файлов, я использую AWS EFS. Как только новый диск подготовлен и смонтирован, я изменил logtarget в /etc/fail2ban/fail2ban.conf на подпапку на диске EFS.

logtarget = /efsmount/fail2ban/server1.log

Затем я написал простой фильтр и поместил его в /etc/fail2ban/filter.d/fail2ban-log.conf

[Definition]

failregex = .* Ban <HOST>

ignoreregex =

Добавлен фильтр в /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

Потом перезапустил fail2ban

sudo fail2ban-client reload

Все идет нормально! Нет, самая болезненная часть - это SELinux. После того, как я позволил fail2ban немного поработать, я запустил эту команду, которая пропустит fail2ban через фильтры.

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

Audit2allow скажет вам, чтобы запустить эту команду

sudo semodule -i fail2ban-nfs.pp

Я все еще проверяю свои журналы SELinux тут и там, чтобы увидеть, есть ли еще отказы. Если у кого-нибудь есть совет, как получить этот чистый SELinux другим методом, это было бы здорово.

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

На этом этапе я все еще получал ошибки при перезапуске fail2ban. Существует ошибка при использовании action = action_mwl в jail.local. После небольшого поиска я нашел это, которое работает до сих пор. Из того, что я прочитал, из-за разрывов строк в директиве logpath, указывающих на несколько файлов. Я пробовал с запятыми, пробелами и т. Д. С 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

Не забудьте снова включить SELinux!


Как и вы, я вложил много усилий в fail2ban (я разместил этот вопрос), но после небольшого исследования я воспользовался советом gparent по удалению fail2ban (см. Комментарии к вопросу)
ndemou

2

Я только что реализовал это, и до сих пор, кажется, работает хорошо. Однако мне пришлось обновить некоторые из php, потому что сценарии в исходном ответе используют устаревшие функции.

Вот обновленные скрипты

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

Кроме того, где бы вы ни размещали действие fail2ban.php, оно должно иметь отступ, равный строке над ним. Например:

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

В противном случае fail2ban не запустится. Я надеюсь, что это помогает любому, кто пытается развернуть это.


1

Альтернативой fail2banявляется DenyHosts, который поставляется с функцией синхронизации. Установка очень похожа fail2ban, см . Учебник Cyberciti для более подробной информации .

Проблема заключается в том, что служба синхронизации централизована, а исходный код на стороне сервера, по-видимому, недоступен, поэтому вы не можете легко запустить собственную службу DenyHosts, и вам приходится полагаться на сторонних разработчиков (что может подойти для некоторых случаи использования).


FWIW ссылка на службу синхронизации не работает сегодня
ndemou

0

Да и да. Оба могут быть сделаны.

Вам нужно найти подходящий механизм, чтобы поделиться списком IP-адресов. Например, если вы используете AWS, вы можете воспользоваться s3. Вы можете использовать rsync между хостами Linux или базу данных, общую для всех хостов. Вы можете запустить сервис с вашим любимым языком программирования, который предоставляет спокойный API, выбор за вами.

С точки зрения совместного использования списка общедоступным союзником, вы можете создать веб-сайт и разместить простой текстовый файл, некоторые уже предоставляют такие списки (не из источников, которые я знаю). Как создать свой собственный сайт / сервис, было бы за рамками ответа, однако это не должно быть очень сложно сделать.


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

Достаточно ручная настройка будет состоять в том, чтобы изменить конфигурацию, которая вызывает iptablesобновление правил, чтобы она вызывала собственный сценарий, который просматривает список хостов (считывается из файла?) И выполняет iptablesвызовы для каждого через SSH. Вам потребуется авторизация на основе ключей между всеми хостами, настроенными для этого. Инструменты автоматизации администратора, такие как puppet, могут упростить настройку и обслуживание. Это будет не очень эффективно, но если вы не увидите огромное количество зондирующего трафика (и / или у вас не будет большого количества хостов), то я уверен, что это будет достаточно хорошо. Если у вас есть только несколько хостов, вам даже не нужно перебирать файл: настройте каждый так, чтобы он вызывал только остальных по порядку. Сценарий будет минимальным.

Is there a way to share banned IPs publicly?

Без сомнения, есть много способов. Пусть приведенный выше скрипт (-ы) перенесет данные в БД, и клиенты будут с них читать, опрашивая новые правила и запуская их по мере их поступления. Простое «запустить правило таким, каким вы его видите» не будет идеальным, если многие хосты предоставляют информацию, например, в этом случае:

  1. В 12:00 сервер 1 говорит «запретить хост X сейчас» и «разблокировать хост X через час».
  2. В 12:45 сервер 2 говорит «запретить хост X сейчас» и «разблокировать хост X через час».
  3. Перекрытие означает, что сервер 3 запретит хост X на час, а не на час + 45 минут, если будет следовать инструкциям по порядку.

но это не должно быть серьезной проблемой, и если вы станете немного умнее с базой данных, вы сможете более аккуратно управлять несколькими отправками, если решите, что это того стоит.

Запуск этого как общедоступной службы откроет вам мир административных хлопот, хотя:

  • Управление пропускной способностью и другими ресурсами, если вы получаете много пользователей.
  • Организация и обеспечение способов оплаты, если вы попытаетесь решить проблему с ресурсами, взимая плату за доступ каким-либо образом.
  • Имея дело с попытками загрязнить вашу базу данных, плохой актер пытается исключить конкурента из мест, подписывающихся на этот список, из-за коммерческих неудобств или попытки шантажа.
  • Работа с жалобами, когда кто-то забанен и думает, что это не должно быть.
  • Борьба с DDoS-атаками, которые начнутся, если ваш сервис вообще сможет причинить неудобства чьим-то ботам.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.