UFW + fail2ban not working with `nginx` to block attack scripts

cname-recordfail2banipv6ufw

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.

Best Answer

But as you see the IP is already banned and the attacker still can access.

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).

But why I don't get an IPv6 log entry then?

There are 2 reasons:

  • either your fail2ban version <= 0.9 (IPv6 support got first time implemented in 0.10);
  • or the logged message looks a bit different for IPv6, so failregex doesn't match that anymore (rewrite failregex compatible for both families);

UPD 1:

  • either (better) place the rule for established connections after chain with fail2ban rules, or simply remove the rule whitelistening established connection;
  • or you can use something like this to kill all established connection from IP to both local http/https ports:
ss -o state established -K dst $ip 'sport = 80 or sport = 443'

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):

[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"]