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?
CodePudding user response:
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:
gsubfunction strips starting[and seconds value from timestampfq[$4,$1]increments array elementfqby 1 where each element is composite key$4,$1i.e.$4 SUBSEP $1string- In the
ENDblock we loop throughfqarray. Whenfq[i] >= 4we remove starting text followed by SUBSEP from array index to leave onlyIP. - Finally we print full
iptablescommand line using theipwe just extracted - Finally we pipe
awkoutput toshto run all commands
CodePudding user response:
You can block the ip like this :
iptables -A INPUT -s <ip-address-to-block> -j DROP
Adapt your bash script to use this command whenever you see an ip requesting more than you want. The idea is to read your log file with a given frequency and parse the number each ip appears. If it appears more than you want, you drop it.
To unblock the ip, you can use this command:
iptables -D INPUT -s <ip-address-to-unblock> -j DROP
