web-dev-qa-db-ja.com

fail2ban禁止IPの共有

公開されているサービスを備えたすべてのサーバーでfail2banを使用しています。

  1. 私が制御するホスト間で禁止IPを共有する簡単方法はありますか?
  2. そのデータを収集して公開するサービスはありますか?

このサーバーをセットアップした1日目から、私は無数のログイン試行を繰り返してきました。

18
ndemou

Fail2banデータを集中化するシステム このサイト上 を見て、修正バージョンを作成したことがあります。データベースは同じですが、いくつかのスクリプトを変更して作成しました。

私のシステムには4つのコンポーネントがあります。

  1. fail2banデータベース

    これは、1つのテーブルのみを含む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");
     </ code>
     
    } 
     
     // $ idは最後に禁止されたホストを含​​み、それを設定ファイルに追加します
     file_put_contents($ lastbanfile、$ id) ; 
    ?> 
    
  4. phpconfig

    このファイルは/ etc/fail2banに移動し、データベース構成と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');
    
    ?>
    

それらのファイルを作成し、fail2banから構成を変更します。

actionban = .....のある行の後に、PHPスクリプトを呼び出すために挿入された新しい行:

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

すべてのサーバーでこの構造を使用すると、1つのホストが1つのサーバーで禁止されるたびに、他のすべてのサーバーでも禁止されます。

8
ThoriumBR

そのため、同じIPアドレスがWebサーバーのクラスターに次々とヒットするのを見た後、これを行う方法について多くの調査を行いました。私はAWSを使用しているので、簡単な方法があり、5台のサーバーをテストする最初の2日間でうまく機能する可能性があると考えました。

私が最初にお勧めするのは、SELinuxを一時的に無効にすることです。最後に対処します。私はSELinuxのエキスパートではありませんが、これまでのところうまくいきます。

主な要件は共有ファイルソースです。私はAWS EFSを使用しています。新しいドライブをプロビジョニングしてマウントしたら、/ etc/fail2ban/fail2ban.conf内のlogtargetを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を再起動するとエラーが発生しました。 jail.localでaction = action_mwlを使用するとバグが発生します。少しグーグルで調べたところ、これは今のところ機能しています。複数のファイルを指す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をオンに戻すことを忘れないでください!

3
prophoto

私はこれを実装しましたが、これまでのところ、うまく機能しているようです。ただし、元の回答のスクリプトでは非推奨の関数が使用されているため、一部の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は開始されません。これがこれをデプロイしようとしている人を助けることを願っています。

2
Simba Lion

fail2banの代替は、同期機能に付属する DenyHosts です。インストールはfail2banとかなり似ています。詳細については、 Cyber​​citiのチュートリアルを参照してください

問題は、 同期サービス が集中化されており、サーバー側のソースコードが利用できないように見えるので、簡単に開始できませんDenyHostsサービスを所有していて、サードパーティに依存する必要がある(一部のユースケースでは問題ない場合があります)。

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

かなり手動のセットアップでは、iptablesを呼び出す構成を変更してルールを更新し、ホストのリストをループして(ファイルから読み取る)を考案する独自のスクリプトを呼び出してiptablesはSSH経由でそれぞれを呼び出します。これが機能するために構成されたすべてのホスト間で、鍵ベースの認証が必要になります。パペットなどの管理自動化ツールを使用すると、この設定と保​​守が簡単になります。これはそれほど効率的ではありませんが、大量のプローブトラフィックが見られない(および/または膨大な数のホストがある)場合を除いて、それで十分だと私は確信しています。ホストの数が少ない場合は、ファイルをループ処理する必要もありません。それぞれを構成して、順番に他のホストを呼び出すだけです。スクリプト作成の労力は最小限になります。

Is there a way to share banned IPs publicly?

間違いなく多くの方法があります。上記のスクリプトでデータをDBにドロップし、クライアントからデータを読み取って、新しいルールをポーリングし、それらが実行されたときに実行します。単純な「見たとおりにルールを実行する」というのは、多くの場合完璧ではありません。ホストは情報を送信しています、たとえばこの場合:

  1. 12:00にサーバー1は「Host Xを今すぐ禁止」と「Host Xを1時間で禁止解除」と言います。
  2. 12:45に、サーバー2は「Host Xを今すぐ禁止」と「Host Xを1時間で禁止解除」と言います。
  3. オーバーラップは、サーバー3がホストXを1時間禁止することを意味します。

しかし、これは重大な問題ではないはずです。データベースをもう少し巧妙にすると、努力する価値があると判断した場合、複数の送信をよりきれいに管理できます。

しかし、それをパブリックサービスとして実行すると、管理者の煩わしさの世界が開かれます。

  • 多くのユーザーを獲得する場合の帯域幅とその他のリソースの管理。
  • 何らかの方法でアクセスに対して課金することにより、リソースの問題に対処しようとする場合は、支払い方法を調整して適用します。
  • データベースを汚染しようとする試みに対処し、商業上の不便または恐喝の試みとしてリストに登録している場所から競争相手を禁止しようとする悪役。
  • 誰かが禁止されてはならないと思っているときに苦情に対処する。
  • willであるDDoS攻撃への対処は、サービスが誰かのボットを不便にすることにまったく成功した場合に発生します。
0
David Spillett

はい、はい。どちらも行うことができます。

IPのリストを共有するには、適切なメカニズムを見つける必要があります。たとえばAWSを使用している場合は、s3を利用できます。 Linuxホスト間、またはすべてのホストに共通のデータベース間でrsyncを使用できます。お気に入りのプログラミング言語を使用して、安らかなAPIを提供するサービスを利用して、選択肢を選ぶことができます。

リストを公に同盟国と共有する場合、ウェブサイトを作成して簡単なテキストファイルをホストすることができます。一部はすでにそのようなリストを提供しています(私が知っているクラウドソースではありません)。独自のサイト/サービスを作成する方法は回答の範囲外ですが、実行するのはそれほど難しくありません。

0
Drew Khoury