fail2ban would surely be the best bet here. It's based on Python but does exactly what you're describing and does it well...as long as your web app logs requests in a file somewhere.
On Jan 23, 2018 17:39, "SurfShop" <contactat...@surfshopcart.com> wrote: > I'm working on adding anti-hammering code to SurfShop to be able > to temporarily ban visitors if they enter certain "keywords" into the query > string, or if they repeatedly hammer the cart. I've also set it up to be > able to permanently block foreign IP's of the store owner's choosing. Each > country's IPs are in separate text files and the temp IPs are in another, > so there could be quite a few files. The temporary IPs also have a date > associated with them, so they can be deleted later on. > > I decided to go with Net::Netmask for CIDR blocks but it's > excruciatingly slow - it adds 2+ seconds to each page load in the cart. > That's a deal breaker. If I remove the Net::Netmask section, the delay > drops to about 1 second per page, but that's still visibly slower than > without this sub. > > So I got the idea to keep track of the last 10?, 30?, 50? good IP > addresses and not process those again after the first visit. The first > page view gets the delay, but subsequent page speeds are normal. I've > included my code below and I'm wondering what the problem is. Did I code > something wrong? Did I choose the wrong module? Perhaps I'm looking at > this incorrectly. Is there a better way to do what I'm after? > > The lines in the IP text files can be in any of these formats: > > 23.254.251.87 > 60.1.33. > 41.96.0.0/12 > 11.22.33.44 2018-01-23 > > Thanks, > Frank > > > > sub banned_ip_check($current_ip) { > return unless $current_ip; > my @ips = read_last_visitor_ips(); ## Last X visitors. > foreach my $ip (@ips) { > chomp $ip; > return if $ip eq $current_ip; ## Only check the IP on first visit. > } > my $t2 = Time::Piece->new(); ## Today's date to compare with saved date. > my @files = File::Find::Rule->file() > ->name('*.txt') > ->in("${data_dir}/banned_ips"); > foreach my $ip_file (@files) { > open (my $ip_fh, '<', $ip_file) || SSLib::error("Xtras::banned_ip_check: > Can't open $ip_file"); > while (my $line = <$ip_fh>) { > chomp $line; > my ($ip, $date) = split (/\s/, $line); > my $process = 'yes'; > if ($date =~ m/\d+/) { > $t1 = Time::Piece->strptime($date, "%Y-%m-%d"); > if (($t2 - $t1) > 2_600_000) { $process = 'no' } > } > my $long = length($ip); > my $found; > if ($ip =~ m|/\d{2}$|) { > ## CIDR IP Addresses > my $block = Net::Netmask->new($ip); > $found = 'yes' if $block->match($current_ip); > } > if ($found || $process eq 'yes' && substr($current_ip, 0, $long) > eq $ip) { ## Match partial IP's, too. > deny_entry($current_ip, 'IP address', $ip_file); > } > } > close ($ip_fh); > } > } > > -- > To unsubscribe, e-mail: beginners-unsubscr...@perl.org > For additional commands, e-mail: beginners-h...@perl.org > http://learn.perl.org/ > > >