我的服务器目前正受到一些脚本小子的攻击。我已设置fail2ban
正确禁止 IP。
2020-01-07 05:51:45,639 fail2ban.actions [1656]: WARNING [nginx-botsearch] 123.207.92.128 already banned
2020-01-07 05:51:47,802 fail2ban.filter [1656]: INFO [nginx-botsearch] Found 123.207.92.128 - 2020-01-07 05:51:47
2020-01-07 05:51:48,026 fail2ban.filter [1656]: INFO [nginx-botsearch] Found 123.207.92.128 - 2020-01-07 05:51:48
2020-01-07 05:51:48,242 fail2ban.actions [1656]: WARNING [nginx-botsearch] 123.207.92.128 already banned
2020-01-07 05:51:49,228 fail2ban.filter [1656]: INFO [nginx-botsearch] Found 123.207.92.128 - 2020-01-07 05:51:49
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----
Anywhere DENY IN 123.207.92.128
哪一个是第一的规则
2020-01-07 05:51:45,639 fail2ban.actions [1656]: WARNING [nginx-botsearch] 123.207.92.128 already banned
2020-01-07 05:51:47,802 fail2ban.filter [1656]: INFO [nginx-botsearch] Found 123.207.92.128 - 2020-01-07 05:51:47
2020-01-07 05:51:48,026 fail2ban.filter [1656]: INFO [nginx-botsearch] Found 123.207.92.128 - 2020-01-07 05:51:48
2020-01-07 05:51:48,242 fail2ban.actions [1656]: WARNING [nginx-botsearch] 123.207.92.128 already banned
2020-01-07 05:51:49,228 fail2ban.filter [1656]: INFO [nginx-botsearch] Found 123.207.92.128 - 2020-01-07 05:51:49
但正如您所看到的,该 IP 已被禁止,但攻击者仍然可以访问。
我很奇怪这是怎么可能的?
我在本地网络上测试了这一点,发现我仍然可以访问领域但不是 IP。我想那是因为它使用了 IPv6。但为什么我没有得到 IPv6 日志条目呢?
我的域名是使用 CNAME 设置的。这有关系吗?我不知道攻击者是否知道该域名,但他可能会被转发到该域名。
答案1
正如@sebres 指出的那样(非常感谢!!),保持活动连接是导致这种行为的原因。
您可以限制 nginx 中的 keepalive 请求的数量。
编辑/etc/nginx/nginx.conf
和添加
keepalive_timeout 20; # this was already here but set to 65.
keepalive_requests 20;
在http
部分中。
这应该将保持连接限制为 20 秒和每个连接 20 个请求。
Apache 应该也有类似的规则。
此外,您还可以添加这些规则到 ufw。优点是您可以在任何您想要的端口上使用这些规则。但大多数这些攻击脚本都使用端口 80 和 443。
我不确定这些规则是否会导致问题!
答案2
正如 @sebres 在他的回答中所说,这种行为一定是由 引起的HTTP Keep-Alive
。如果你想失败2ban要立即阻止来自远程客户端的请求,可以将用户定义的链(例如)添加到您的 iptables 中,并将其放在链中规则before-established
之前(运行以列出它们):ESTABLISHED,RELATED
ufw-before-input
iptables -nv --line-numbers ufw-before-input
iptables -N before-established
iptables -I ufw-before-input <desired_position> -p tcp --dport 80 -j before-established
并对 执行相同操作ip6tables
。如果您停止 UFW,规则应该在 中结束/etc/ufw/before.rules
,并在 UFW 重新启动之间重新建立。否则,请手动添加这两行(iptables-save -t ufw-before-input
语法)。
要使用新链条失败2ban/etc/fail2ban/action.d
您可以在(我们称之为)中创建一个新的操作文件,before-established.conf
其内容如下:
[INCLUDES]
before = iptables-common.conf
[Definition]
blocktype = DROP
actionflush = <iptables> -F before-established
actionstart = <actionflush>
actionstop = <actionflush>
actioncheck = <iptables> -n -L before-established >/dev/null
actionban = <iptables> -I before-established 1 -s <ip> -j DROP
actionunban = <iptables> -D before-established -s <ip> -j DROP
[Init]
并使用此操作代替联邦快递一。
答案3
但正如您所看到的,该 IP 已被禁止,但攻击者仍然可以访问。
这个问题类似https://github.com/fail2ban/fail2ban/issues/2545
简而言之:keep-alive 与 ufw(所以我建议不要使用它,或者扩展操作来终止连接)。
但为什么我没有得到 IPv6 日志条目呢?
原因有二:
- 你的 fail2ban 版本 <= 0.9 (IPv6 支持在 0.10 中首次实现);
- 或者记录的消息对于 IPv6 看起来有点不同,因此 failregex 不再匹配它(重写 failregex 以兼容这两个系列);
更新 1:
- 或者 (更好) 将已建立连接的规则放在与 fail2ban 规则链接之后,或者简单地删除白监听已建立连接的规则;
- 或者你可以使用类似的方法来终止从 IP 到本地 http/https 端口的所有已建立的连接:
ss -o state established -K dst $ip 'sport = 80 or sport = 443'
请注意,这需要现代内核(我认为版本 >= 4.9)。
您也可以直接在 jail.local 中添加它(无需创建新的本地操作配置文件):
[some-nginx-jail]
_killstmt = ss -o state established -K dst <ip> 'sport = 80 or sport = 443'
banaction = %(known/banaction)s[actionban="<known/actionban><br>%(_killstmt)s"]
- 或者强制 nginx 通过身份验证失败来关闭连接(例如使用自己的 40x 位置
keepalive_timeout 0;
,它也可以将错误写入不同的日志文件,以避免 fail2ban 意义上的“寄生”流量,请参阅fail2ban/wiki/最佳实践#reduce-parasitic-log-traffic了解更多信息);
或者简单地return 444;
在相应的位置进行操作,这将导致关闭连接(参见http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return用于文档)