我如何教fail2ban检测并阻止来自整个网络块的攻击?

我如何教fail2ban检测并阻止来自整个网络块的攻击?

我已正确安装在我的计算机中,激活、和fail2ban的规则;一切正常。sshssh-dosrecidive

最近,我发现来自同一网络的不同主机的重复攻击模式越来越多,这些攻击通过在禁止后切换 IP 来规避“重复”规则:

2015-01-25 11:12:11,976 fail2ban.actions: WARNING [ssh] Ban XXX.41.124.29
2015-01-25 11:12:13,165 fail2ban.actions: WARNING [ssh] Ban XXX.41.124.42
2015-01-25 11:12:16,297 fail2ban.actions: WARNING [ssh] Ban XXX.41.124.28
2015-01-25 11:12:20,446 fail2ban.actions: WARNING [ssh] Ban XXX.41.124.104

我想检测它并制定一个“recidive24”规则来阻止所有这些类型的攻击,从而禁止整个/24块。

我在中找到了一个建议Debian 错误档案对于fail2ban,我已经应用了它,但是:

  1. /24如果我在触发监狱时应用全面禁令ssh,我会遇到一个问题,即我的同一网络上的某人很容易通过从一个 IP 进行攻击来阻止我;

  2. 监狱recidive是完美的,但它不是由风暴改变IP触发的......

所以我想更改recidive过滤器规范,以便它只查看IP的前三个字节,但我在这里不知所措......执行禁令的正则表达式是(来自/etc/fail2ban/recidive.conf)是

# The name of the jail that this filter is used for. In jail.conf, name the 
# jail using this filter 'recidive', or change this line!
_jailname = recidive

failregex = ^(%(__prefix_line)s|,\d{3} fail2ban.actions:\s+)WARNING\s+\[(?!%(_jailname)s\])(?:.*)\]\s+Ban\s+<HOST>\s*$

...它将匹配完整的IP。

问题:如何更改此failregex,使其仅匹配主机IP 的前三个字节?

请注意,当检测到垃圾邮件 IP 时,问题并不是阻塞整个子网 -- 这相对容易。问题是当同一子网subnet-recidive有五个或更多命中时会触发某种情况......recidive


我虽然用另一个守护进程过滤fail2ban日志文件并写入第二个文件,其中最后一个字节每次都是0,并使用它触发累犯监狱,但它看起来真的很笨拙......

答案1

/24将这个魔法(有些人可能甚至喜欢/22)添加到所有监狱的命令中的最简单方法iptables是添加两个文件:

/etc/fail2ban/action.d/iptables-multiport.local
/etc/fail2ban/action.d/iptables-allports.local

包含以下内容:

[Definition]
actionban = <iptables> -I f2b-<name> 1 -s <ip>/24 -j <blocktype>
actionunban = <iptables> -D f2b-<name> -s <ip>/24 -j <blocktype>

为了检测您需要修改过滤器的部分......这有点棘手。但好的部分是——没有必要!这个子网阻塞的东西效果很好。

答案2

Fail2ban 没有自动阻止来自整个子网的攻击的简洁功能。不过,使用最新版本的fail2ban(我使用v0.11)、一些简单的fail2ban脚本和一个小型的纯python3脚本是可以做到的。

注意:问题涉及“整个子网”(我将其称为 CIDR 块或 IP 范围)。这是一件困难的事情,因为我们不知道攻击者控制了多大的地址块。攻击者甚至可能偶然控制同一块中的少数地址,而中间地址是合法的。

步骤1.获取主机的CIDR

fail2ban 监控的日志文件通常显示主机(例如 127.0.0.1),而不是 CIDR 块(127.0.0.0/24)或 IP 范围(127.0.0.0 - 127.0.0.255)。

解决方案可能是首先假设一个小的 CIDR 块,然后随着日志报告更多行为不当的主机而扩大它。显然,如果这些主机来自相邻地址,则只应增加 CIDR。但这很复杂,无论算法多么复杂,合法地址都可能会被捕获。

相反,我们也可以简单地在whois中查找CIDR。这会导致 whois 查找出现一些延迟,并产生一些流量。但是解析whois的脚本,可以将CIDR写入syslog,然后可以再次被fail2ban捕获。

注意:不要忘记将此脚本挂接到您首选的 action.d/lorem-ipsum.conf 脚本的 actionban 中。请注意,如果其 maxretry > 1,那么您将无法捕获主机仅失败一次的 CIDR 块!

#!/usr/bin/python

import sys, subprocess, ipaddress, syslog

def narrowest_cidr(cidrA, cidrB):
    _ip, subA = cidrA.split('/')
    _ip, subB = cidrB.split('/')

    if int(subA) > int(subB):
        return cidrA
    else:
        return cidrB

bad_ip = sys.argv[1]
cidrs = []
inetnums = []
ret = None

whois = subprocess.run(['whois', bad_ip], text=True,
        stdout=subprocess.PIPE, check=True)

for line in whois.stdout.split('\n'):
    if 'CIDR:' in line:
        cidrs.append(line.replace('CIDR:', '').strip())
    if 'inetnum:' in line:
        inetnums.append(line.replace('inetnum:', '').strip())

if len(cidrs) >= 1:
    if len(cidrs) == 1:
        cidr = cidrs[0]
    else:
        cidr = narrowest_cidr(cidrs[0], cidrs[-1])
elif len(inetnums) > 0:
    if len(inetnums) == 1:
        inetnum = inetnums[0]
        startip, endip = inetnum.split(' - ')
        cidrs = [ipaddr for ipaddr in ipaddress.summarize_address_range(ipaddress.IPv4Address(startip), ipaddress.IPv4Address(endip))]
        if len(cidrs) == 1:
            cidr = cidrs[0]
        else:
            cidr = narrowest_cidr(cidrs[0], cidrs[-1])
else:
    cidr = "no CIDR found"

syslog.openlog(ident="suspectrange")
syslog.syslog("{} has CIDR {}".format(bad_ip, cidr))

步骤 2. 确定何时阻止 CIDR

如果我们有动态 CIDR 确定,这可能会变得有点复杂,因为我们必须更改我们所禁止的内容。但通过 whois 查找,我们可以根据我们认为合适的 maxretry 和 findtime 简单地禁止我们找到的 CIDR 块。这是我使用的监狱:

[fail2ban-cidr-recidive]
filter = fail2ban-cidr-recidive
action = nftables-common[name=BADRANGE]
logpath = /var/log/everything/current

#5 bans in 12hrs is 48hr ban
maxretry = 5
findtime = 12h
bantime = 2d

以及附带的过滤器

[Definition]

failregex = \[suspectrange\] .* has CIDR <SUBNET>

步骤 3. 实际阻止 CIDR

您可能已经注意到,我使用 action.d/nft-common.conf。 nftables 允许阻止 CIDR 块而不是单个主机。这需要对操作脚本的 actionstart 部分的第一行进行一些小更改:

actionstart = nft add set netdev f2b <set_name> \{ type ipv4_addr\; \}

应修改为:

actionstart = nft add set netdev f2b <set_name> \{ type ipv4_addr\; flags interval\; \}

答案3

fail2ban在Centos 7中尝试过,发现有时无法阻止IP地址。它不断将他们添加到监狱,但他们仍然能够访问 sshd。与firewalld 存在一些不兼容性。

我现在使用不同的方法。我/etc/hosts.deny这样修改:

sshd: 43.*.*.*
sshd: 58.*.*.*

只是不要意外地将您自己的 IP 网络添加到那里。

要从安全日志中 grep IP 地址,请使用:

grep sshd /etc/hosts.deny

要从 sshd 日志中获取 10 个最活跃的 IP 地址及其访问计数,请使用:

d=[0-9]{1,3}
s=[\.\-]
n=[^0-9]
ip="$d$s$d$s$d$s$d"
egrep $ip /var/log/secure | sed -r "s/^.*$n($ip).*$/\1/g" | sed s/-/./g | sort | uniq -c | sort -g | tail -10

(来源:http://whoishacking.com

答案4

Python 中的这个脚本运行良好,在 crontab */5 分钟内,将相似的 IP 分组到网络范围中,从 CIDR /23 到 /32;它调用fail2ban,但也可以直接调用IPTABLE。

https://github.com/WKnak/fail2ban-block-ip-range

它将这些 IP 分组

151 193.56.28.160
108 45.142.120.135
107 45.142.120.62
105 45.142.120.99
105 45.142.120.93
105 45.142.120.192
104 45.142.120.87
104 45.142.120.60
104 45.142.120.209
104 45.142.120.200
104 45.142.120.133
103 45.142.120.180
103 45.142.120.149
102 45.142.120.59
100 45.142.120.215
 78 45.142.120.57
 78 45.142.120.11
 77 45.142.120.82
 77 45.142.120.20
 76 45.142.120.63
 76 45.142.120.34
 76 45.142.120.138
 73 45.142.120.65
 60 78.128.113.66
  6 45.150.206.113
  3 123.30.50.91
  2 5.188.206.204
  2 45.150.206.119
  2 45.150.206.115
  2 45.150.206.114
  1 51.210.127.200

作为

fail2ban-client set postfix-sasl banip 78.128.113.66/32
fail2ban-client set postfix-sasl banip 45.142.120.0/24
fail2ban-client set postfix-sasl banip 193.56.28.160/32
fail2ban-client set postfix-sasl banip 45.150.206.112/29

相关内容