fail2ban 금지 된 IP 공유


18

공개적으로 보이는 서비스가있는 모든 서버에서 fail2ban을 사용하고 있습니다.

  1. 내가 제어하는 ​​호스트간에 금지 된 IP를 공유 하는 쉬운 방법이 있습니까?
  2. 해당 데이터를 수집하고 게시하는 서비스가 있습니까?

이 서버를 설정 한 1 일 이후로 수많은 로그인 시도가있었습니다.


2
인터넷에 오신 것을 환영합니다. 이 목록을 게시 할 필요는 없습니다. 우리 모두이 상황을 너무 잘 알고 있습니다.
Sven

1
감사. 나는 무언가를 묘사 할 때 예제가 좋을 것이라고 생각합니다. 더 잘 알고 있다면 무시하십시오.
ndemou

IP 목록을 삭제하고 귀하의 질문을 질문으로 바꾸는 기회를 가졌습니다. 목록을 게시 할 필요가 없을뿐만 아니라 문제를 복잡하게 만들고 빠르게 구식이 될 것입니다.
gparent

2
또한 내 제안은 fail2ban을 제거하고 이것에 대한 관심을 멈추는 것입니다. 비밀번호 인증을 해제 한 경우 수행 할 수있는 작업이 거의 없습니다. fail2ban은 과거에 악용되어 왔으며 잠재적 인 이점을 제공하지 않는 잠재적 인 보안 허점을 추가하는 것은 순 손실입니다.
gparent

@gparent : 제안에 대해 : 감사합니다. 전에 fail2ban 익스플로잇 이력을 본 적이 없습니다. 보안을 위해 S / WI는 더 나은 실적을 기대할 것입니다. 편집 내용과 관련하여 : 질문을 많이 변경하는 것이 좋지 않다고 생각합니다. 나쁜 질문이라면 포스터가 결과를 겪게하십시오. 어쨌든 지금 그대로 두겠습니다.
ndemou

답변:


8

한때이 사이트 에서 fail2ban 데이터를 중앙 집중화하는 시스템을보고 수정 된 버전을 만들었습니다. 데이터베이스는 동일하지만 bu를 변경하고 스크립트를 만들었습니다.

내 시스템에는 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. 크론

    이것을 매분마다 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>

모든 서버에서이 구조를 사용하면 한 호스트에서 한 호스트가 금지 될 때마다 다른 모든 서버에서도 해당 서버가 금지됩니다.


3

그래서 동일한 IP 주소가 웹 서버의 클러스터에 하나씩 충돌하는 것을 보면서이 작업을 수행하는 방법에 대한 많은 연구를했습니다. AWS를 사용하고 있기 때문에 5 일 동안 서버를 테스트 한 첫 이틀 동안 쉬운 방법이 있고 아름답게 작동 할 것이라고 생각했습니다.

가장 먼저 권하는 것은 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를 다시 켜는 것을 잊지 마십시오!


당신처럼, fail2ban에 많은 노력을 투자했지만 (이 질문을 게시했습니다) 조금 더 연구 한 후에 fail2ban을 제거하기 위해 gparent의 조언을 얻었습니다 (질문에 대한 의견 참조)
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 동기화 기능을 제공한다. 설치는 상당히 유사합니다 . 자세한 내용fail2banCyberciti의 자습서를 참조하십시오 .

문제는 동기화 서비스 가 중앙 집중화되어 있고 서버 측의 소스 코드를 사용할 수없는 것 같습니다. 따라서 자체 DenyHosts 서비스를 쉽게 시작할 수 없으며 타사에 의존해야합니다 (일부 경우에 적합 할 수 있음) 사용 사례).


FWIW는 동기화 서비스에 대한 링크가 다운 오늘날
ndemou

0

그렇습니다. 둘 다 할 수 있습니다.

IP 목록을 공유하려면 적절한 메커니즘을 찾아야합니다. 예를 들어 AWS를 사용하는 경우 s3을 활용할 수 있습니다. Linux 호스트간에 rsync를 사용하거나 모든 호스트에 공통 인 데이터베이스를 사용할 수 있습니다. 편안한 API를 제공하는 자주 사용하는 프로그래밍 언어로 서비스를 중단 할 수 있습니다.

목록을 공개적으로 공유하는 경우 웹 사이트를 만들고 간단한 텍스트 파일을 호스팅 할 수 있다는 점에서 일부는 이미 그러한 목록을 제공합니다 (내가 아는 크라우드 소스는 아님). 자신의 사이트 / 서비스를 만드는 방법은 답변의 범위를 벗어나지 만, 그렇게 어려운 일이 아닙니다.


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

상당히 수동 설정은 iptables규칙을 업데이트 하는 구성을 변경하여 호스트 목록 (파일에서 읽은 것입니까?)을 반복하고 iptablesSSH를 통해 각 호출 을하는 자체 고안 스크립트를 호출하는 것 입니다. 이를 위해 구성된 모든 호스트간에 키 기반 인증이 필요합니다. 꼭두각시와 같은 관리자 자동화 도구를 사용하면이를 설정하고 쉽게 유지할 수 있습니다. 이것은 매우 효율적이지는 않지만 대량의 프로빙 트래픽 (및 / 또는 많은 수의 호스트가없는)을 보지 않으면 충분할 것입니다. 호스트가 몇 개인 경우 파일을 반복 할 필요조차 없습니다. 순서대로 다른 호스트를 호출하도록 각각을 구성하십시오. 스크립팅 노력은 최소화 될 것입니다.

Is there a way to share banned IPs publicly?

의심 할 여지없이 여러 가지 방법이 있습니다. 위의 스크립트를 사용하여 데이터를 DB에 삭제하고 클라이언트가 그 데이터를 읽도록하여 새 규칙을 폴링하고 들어오는 규칙을 실행하도록하십시오. 호스트가 정보를 제출하고 있습니다 (예 :이 경우).

  1. 12:00시에 서버 1은 "지금 호스트 X 금지"및 "시간 내에 호스트 X 금지 해제"라고 말합니다.
  2. 12시 45 분에 서버 2는 "지금 호스트 X 금지"및 "시간 내에 호스트 X 금지 해제"라고 말합니다.
  3. 겹침은 서버 3이 지시에 따라 순서대로 수행 할 경우 1 시간 +45 분이 아니라 1 시간 동안 호스트 X를 금지 함을 의미합니다.

그러나 이것은 중대한 문제가되어서는 안되며, 데이터베이스에 대해 조금 더 영리한 경우에는 노력할만한 가치가 있다고 판단되면 여러 제출물을보다 깨끗하게 관리 할 수 ​​있습니다.

공공 서비스로 운영하면 관리자의 번거 로움이 생길 수 있습니다.

  • 많은 사용자를 확보 한 경우 대역폭 및 기타 자원 관리
  • 어떤 방법 으로든 액세스 비용을 청구하여 리 소싱 문제를 해결해야하는 경우 지불 방법을 준비하고 시행해야합니다.
  • 데이터베이스를 오염시키려는 시도를 처리하는 악의적 인 행위자는 경쟁 업체를 상업적인 불편이나 협박 시도로 목록에 등록한 장소에서 금지 시키려고합니다.
  • 누군가가 금지되어 있고해서는 안된다고 생각할 때 불만 처리
  • DDoS 공격을 다루는 것입니다 서비스가 사람의 봇을 불편의 모든 성공에있는 경우 온다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.