my server is currently attacked by some script kiddies. I have set up fail2ban
which correctly bans the 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
Which is the first rule
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
But as you see the IP is already banned and the attacker still can access.
I wonder how this is possible?
I tested this for my local net and found out that I can still access the domain but not the IP. I think thats because it uses IPv6 then. But why I don't get an IPv6 log entry then?
My domain is set up using CNAME. Does that mather? I don't know if the attacker knows the domain but he might be forwarded to it.
This issue is similar https://github.com/fail2ban/fail2ban/issues/2545
Shortly: keep-alive vs. ufw (so I suggest don't use it, or extend an action to kill a connection).
There are 2 reasons:
UPD 1:
Note this expecting modern kernel (version >= 4.9 I suppose).
You can also add it directly in jail.local (without creating new local action config-file):
keepalive_timeout 0;
, which can also write an error into different log-file in order to avoid "parasite" traffic in sense of fail2ban, see fail2ban/wiki/Best-practice#reduce-parasitic-log-traffic for more info);or simply make
return 444;
in corresponding location, that will cause a close the connection (see http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return for documentation)As @sebres pointed out (Thanks a lot!!), keep alive connections are the cause for this behavior.
You can limit the number of keepalive requests in nginx.
Edit
/etc/nginx/nginx.conf
and addin the
http
section.This should limit the keepalive connections to 20s and 20 requests per connection.
There should be similar rules for Apache.
Additional, you can also add these rules to ufw. Advantage is then that you can use these rules on any port you want. But most of these attack scripts use port 80 and 443.
I'm not sure if these rules could lead to problems!
As @sebres remarked in his answer, this behaviour must be cause by
HTTP Keep-Alive
. If you want fail2ban to block requests from the remote client immediately can add a user-defined chain (e.g.before-established
) to your iptables and place it just before theESTABLISHED,RELATED
rule in chainufw-before-input
(runiptables -nv --line-numbers ufw-before-input
to list them):and do the same for
ip6tables
. If you stop UFW, the rules should end up in/etc/ufw/before.rules
and be reestablished between UFW restarts. Otherwise add the two lines manually (iptables-save -t ufw-before-input
for the syntax).To use the new chain with fail2ban you can create a new action file in
/etc/fail2ban/action.d
(let's call itbefore-established.conf
) with the following content:and use this action instead of the ufw one.