Compartilhamento de IPs proibidos fail2ban


18

Estou usando fail2ban em todos os servidores com serviços publicamente visíveis e me pergunto:

  1. Existe uma maneira fácil de compartilhar IPs proibidos entre hosts que eu controle?
  2. Existe um serviço lá fora, coletando e publicando esses dados?

Venho recebendo inúmeras tentativas de login desde o primeiro dia de configuração deste servidor.


2
Bem-vindo à internet. Não faz sentido publicar esta lista - todos conhecemos muito bem essa situação.
Sven

1
Obrigado. Acredito que é bom ter exemplos ao descrever algo. Sinta-se livre para ignorá-los, se você souber melhor.
Ndemou 2/09/14

Eu removi a lista de IPs e aproveitei a oportunidade para transformar sua pergunta em uma pergunta. Além de não adiantar a publicação da lista, ela também atrapalha a questão e fica desatualizada rapidamente.
gparent

2
Também minha sugestão é remover fail2ban e parar de se preocupar com isso. Se você desativou a autenticação de senha, há muito pouco a fazer. O fail2ban foi explorado no passado e adicionar uma potencial falha de segurança que não oferece absolutamente nenhum benefício é uma perda líquida.
precisa saber é

@ gparent: Em relação às suas sugestões: Obrigado - nunca vi o histórico de exploração fail2ban antes. Por segurança, a S / WI esperaria um melhor histórico. Em relação às suas edições: não acredito que seja bom alterar tanto uma pergunta. Se for uma pergunta ruim, deixe o cartaz sofrer as consequências. De qualquer forma, vou deixar como está agora.
Ndemou 2/09/14

Respostas:


8

Uma vez vi um sistema para centralizar os dados do fail2ban neste site e criei uma versão modificada. O banco de dados é o mesmo, mas mudei e criei alguns scripts.

Meu sistema possui 4 componentes:

  1. banco de dados fail2ban

    É um banco de dados MySQL contendo apenas uma tabela 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

    Toda vez que um host é banido, ele preenche o banco de dados:

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

    Você coloca isso para rodar no crontab, a cada minuto. Ele recuperará os últimos hosts adicionados e os banirá.

    
    <?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 arquivo vai para / etc / fail2ban e possui configuração de banco de dados e seleção de prisão.

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

Crie esses arquivos e altere a configuração de fail2ban:

Após a linha com actionban = .....uma nova linha inserida para chamar o script PHP:

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

O uso dessa estrutura em todos os seus servidores garantirá que toda vez que um host for banido em um servidor, todos os outros servidores também o banirão.


3

Então, fiz uma série de pesquisas sobre como fazer isso depois de assistir o mesmo endereço IP atingir meu cluster de servidores da Web, um após o outro. Como estou usando a AWS, achei que poderia ser uma maneira fácil e funcionaria perfeitamente nos meus dois primeiros dias de teste de 5 servidores.

A primeira coisa que recomendo é desativar temporariamente o SELinux; lidaremos com isso no final. Não sou especialista em SELinux, mas o que fiz funcionou até agora.

O requisito principal é uma fonte de arquivo compartilhada, eu uso o AWS EFS. Depois que a nova unidade é provisionada e montada, alterei o logtarget dentro de /etc/fail2ban/fail2ban.conf para uma subpasta na unidade EFS.

logtarget = /efsmount/fail2ban/server1.log

Então eu escrevi um filtro simples e coloquei em /etc/fail2ban/filter.d/fail2ban-log.conf

[Definition]

failregex = .* Ban <HOST>

ignoreregex =

Adicionado o filtro para /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

Em seguida, reiniciou o fail2ban

sudo fail2ban-client reload

Por enquanto, tudo bem! Não, a parte dolorosa é o SELinux. Depois de deixar o fail2ban rodar um pouco, executei este comando que permitiria o fail2ban através dos filtros.

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

O Audit2allow solicitará que você execute este comando

sudo semodule -i fail2ban-nfs.pp

Ainda estou checando meus logs do SELinux aqui e ali para ver se há mais negações. Se alguém tiver uma dica sobre como obter esse SELinux claro com outro método, isso seria incrível.

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

Neste ponto, eu ainda estava recebendo erros ao reiniciar o fail2ban. Há um erro ao usar action = action_mwl no jail.local. Depois de pesquisar um pouco, achei isso que está funcionando até agora. Pelo que li, por causa das quebras de linha na diretiva de caminho de log, apontando para vários arquivos. Eu tentei com vírgulas, espaços, etc, nada mais funcionou com 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ão se esqueça de ativar o SELinux novamente!


Como você, eu tenho investido muito esforço em fail2ban (eu postei esta pergunta), mas depois de o conselho de gparent um pouco mais pesquisas eu tenho tomado para remover fail2ban (ver comentários sobre a questão)
ndemou

2

Acabei de implementar isso e, até agora, parece estar funcionando bem. No entanto, tive que atualizar parte do php porque os scripts na resposta original usam funções obsoletas.

Aqui estão os scripts atualizados

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

Além disso, onde quer que você coloque a ação fail2ban.php, ela deve ser recuada tanto quanto a linha acima dela. Por exemplo:

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

Caso contrário, o fail2ban não será iniciado. Espero que isso ajude quem estiver tentando implantar isso.


1

Uma alternativa fail2bané o DenyHosts, que vem com uma funcionalidade de sincronização. A instalação é bastante semelhante à fail2ban, consulte o tutorial da Cyberciti para obter mais detalhes .

O problema é que o serviço de sincronização é centralizado e o código-fonte do lado do servidor não parece estar disponível; portanto, você não pode iniciar facilmente seu próprio serviço DenyHosts e precisa confiar em terceiros (o que pode ser bom para alguns casos de uso).


0

Sim e sim. Ambos podem ser feitos.

Você precisa encontrar um mecanismo adequado para compartilhar a lista de IPs. Se você estiver usando a AWS, por exemplo, poderá aproveitar o s3. Você pode usar o rsync entre hosts Linux ou um banco de dados comum a todos os hosts. Você pode contratar um serviço com sua linguagem de programação favorita que forneça uma API tranquila, a escolha é sua.

Em termos de compartilhamento da lista publicamente, você pode criar um site e hospedar um arquivo de texto simples, alguns já fornecem essas listas (não é uma fonte que conheço). Como criar seu próprio site / serviço estaria fora do escopo de uma resposta, no entanto, não deve ser muito difícil de fazer.


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

Uma configuração razoavelmente manual seria alterar a configuração que chama iptablespara atualizar as regras, para que ele chame um script de sua preferência, que percorra uma lista de hosts (lidos de um arquivo?) E faça oiptables chamadas em cada um deles via SSH. Você precisaria de autenticação baseada em chave entre todos os hosts configurados para que isso funcionasse. Ferramentas de automação de administradores, como o fantoche, podem facilitar a configuração e a manutenção. Isso não seria muito eficiente, mas, a menos que você veja uma quantidade enorme de tráfego de análise (e / ou tenha um grande número de hosts), tenho certeza de que seria bom o suficiente. Se você possui apenas alguns hosts, nem precisa percorrer um arquivo: configure cada um para chamar os outros em ordem. O esforço de script será mínimo.

Is there a way to share banned IPs publicly?

Não há dúvida de muitas maneiras. Faça com que os scripts acima coloquem os dados em um banco de dados e os clientes os leiam, pesquisando novas regras e executando-as à medida que entram. O simples "executar uma regra como você vê" não será perfeito se muitos hosts estão enviando informações, por exemplo, este caso:

  1. Às 12:00, o servidor 1 diz "banir o host X agora" e "desbanir o host X em uma hora".
  2. Às 12:45, o servidor 2 diz "banir o host X agora" e "desbanir o host X em uma hora".
  3. A sobreposição significa que o servidor 3 banirá o host X por uma hora, não uma hora e 45 minutos se seguir as instruções em ordem.

mas isso não deve ser um problema significativo e, se você ficar um pouco mais inteligente com o banco de dados, poderá gerenciar vários envios de maneira mais limpa, se decidir que vale a pena o esforço.

Executar isso como um serviço público abriria você para um mundo de aborrecimentos administrativos:

  • Gerenciando largura de banda e outros recursos, se você ganhar muitos usuários.
  • Organizando e aplicando métodos de pagamento, você deve tentar lidar com o problema de recursos cobrando pelo acesso de alguma forma.
  • Ao lidar com tentativas de poluir seu banco de dados, um ator ruim tenta banir um concorrente dos lugares que assinam a lista como uma inconveniência comercial ou tentativa de chantagem.
  • Lidar com reclamações quando alguém é banido e pensa que não deveria.
  • Lidar com ataques DDoS que ocorrerão se o seu serviço for bem-sucedido em incomodar os bots de alguém.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.