fail2banで禁止されたIPの共有


18

私は一般公開されているサービスを備えたすべてのサーバーでfail2banを使用していますが、

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

このサーバーをセットアップしてから1日目から、無数のログイン試行があります。


2
インターネットへようこそ。このリストを投稿しても意味がありません-私たちは皆、この状況をよく知っています。
スヴェン

1
ありがとう。何かを説明するときに例があればいいと思います。よく知っている場合は無視してください。
ndemou

私はIPリストを削除し、あなたの質問を質問に変える機会を得ました。リストを投稿する意味がないだけでなく、質問を混乱させ、急速に時代遅れになります。
gparent

2
また、私が提案するのは、fail2banを削除し、これを気にしないことです。パスワード認証をオフにしている場合、他にできることはほとんどありません。fail2banは過去に悪用されており、まったく利益をもたらさない潜在的なセキュリティホールを追加することは純損失です。
gparent

@gparent:ご提案について:ありがとう-以前にfail2banエクスプロイト履歴を見たことはありません。セキュリティのために、S / WIはより良い実績を期待しています。編集について:質問をそれほど変更するのは良いことではないと思います。それが悪い質問であれば、ポスターが結果を被ることにしましょう。とにかく、今のままにしておきます。
ndemou 14

回答:


8

このサイトで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");
    
    } // $id contains the last banned host, add it to the config file 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つのホストが禁止されるたびに、他のすべてのサーバーも禁止されます。


3

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

最初にお勧めするのは、一時的にSELinuxを無効にすることです。最後に対処します。私はSELinuxの専門家ではありませんが、今までやってきたことはうまくいきます。

主な要件は共有ファイルソースです。AWSEFSを使用しています。新しいドライブをプロビジョニングしてマウントしたら、/ 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を再び有効にすることを忘れないでください!


あなたと同じように、私は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です。インストールはかなり似ています。詳細についてはfail2banCyber​​citiのチュートリアルを参照してください

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


0

はい、はい。両方を行うことができます。

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

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


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

かなり手動のセットアップではiptables、更新ルールを呼び出す構成を変更して、ホストのリストをループする(ファイルから読み取られます)独自のスクリプトを呼び出し、iptablesSSHを介してそれぞれの呼び出しを行うようにします。これが機能するように設定されたすべてのホスト間でキーベースの認証が必要になります。puppetなどの管理自動化ツールを使用すると、これを設定して保守しやすくなります。これはそれほど効率的ではありませんが、大量のプローブトラフィック(および/または膨大な数のホスト)がなければ、それで十分だと確信しています。少数のホストしかない場合は、ファイルをループする必要さえありません。各ホストを順番に他のホストを呼び出すように設定します。スクリプト作成の労力は最小限に抑えられます。

Is there a way to share banned IPs publicly?

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

  1. 12:00に、サーバー1は「ホストXを今すぐ禁止」、「ホストXを1時間で禁止解除」と言います。
  2. 12:45に、サーバー2は「ホストXを今すぐ禁止」、「ホストXを1時間で禁止解除」と言います。
  3. オーバーラップとは、サーバー3がホストXを1時間禁止することを意味します。指示に従った場合、1時間+ 45分ではありません。

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

それを公共サービスとして実行すると、管理者の面倒な世界が開きます:

  • 多くのユーザーを獲得する場合の帯域幅およびその他のリソースの管理。
  • 何らかの方法でアクセス料金を請求することにより、リソースの問題に対処しようとする場合の支払い方法の手配と実施。
  • データベースを汚染しようとする試みに対処します。商業的な不便または恐mailの試みとして、リストに登録している場所から競合他社を禁止しようとする悪役。
  • 誰かが禁止されていて、そうすべきではないと考えている場合の苦情への対処。
  • DDoS攻撃への対処しますあなたのサービスが誰かのボットを煩わせる内のすべての成功である場合に来ます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.