I want to block IPs that requested more than N times/min using iptables
.
I've sorted the log file using this script:
cat $log_path | awk '{print $1, $4}' | sort -n -k 1,4 | sed "s/\[//g"
10.200.3.120 20/May/2021:21:05:04
10.200.3.120 20/May/2021:21:05:17
10.200.3.120 20/May/2021:21:05:18
10.200.3.120 20/May/2021:21:05:19
10.200.3.120 20/May/2021:21:05:20
10.200.3.120 20/May/2021:22:05:39
104.131.19.181 20/May/2021:19:05:31
107.23.7.76 20/May/2021:20:05:16
119.252.76.162 20/May/2021:22:05:00
119.252.76.162 20/May/2021:22:05:01
119.252.76.162 20/May/2021:22:05:01
119.252.76.162 20/May/2021:22:05:04
119.252.76.162 20/May/2021:22:05:04
119.252.76.162 20/May/2021:21:05:10
119.252.76.162 20/May/2021:21:05:44
⋮
In the example log above, two IPs requested more than 4 times in a minute (10.200.3.120
, 119.252.76.162
) and they should be blocked.
How can I get the number of requests in a time interval for each IP and block those IPs?
You can try this solution:
awk '
{
gsub(/\[|:[0-9]+$/, "", $4)
++fq[$4,$1]
}
END {
for (i in fq)
if (fq[i] >= 4) {
sub(".*" SUBSEP, "", i)
print "iptables -A INPUT -s", i, "-j DROP"
}
}' "$log_path" | sh
Here:
gsub
function strips starting [
and seconds value from timestamp++fq[$4,$1]
increments array element fq
by 1 where each element is composite key $4,$1
i.e. $4 SUBSEP $1
stringEND
block we loop through fq
array. When fq[i] >= 4
we remove starting text followed by SUBSEP from array index to leave only IP
.iptables
command line using the ip
we just extractedawk
output to sh
to run all commands