App-BlockWebFlooders
view release on metacpan or search on metacpan
script/block-web-flooders view on Meta::CPAN
#!perl
our $DATE = '2019-01-29'; # DATE
our $VERSION = '0.010'; # VERSION
use 5.010001;
use strict;
use warnings;
use Getopt::Long::Modern;
use IPC::System::Options qw(system);
use Regexp::Pattern 'Net::ipv4';
use Term::ANSIColor;
use Tie::Array::Expire;
use Time::HiRes 'sleep';
my $PROG = 'block-web-flooders';
my $Dbspec = {
latest_v => 1,
install => [
'CREATE TABLE blocked (ip TEXT NOT NULL PRIMARY KEY, ctime INT NOT NULL)',
],
};
my $action = "run";
my $opt_detail;
my %Opts = (
limit => undef,
has => [],
lacks => [],
has_pattern => [],
lacks_pattern => [],
period => 300,
block_period => 86400,
whitelist_ip => [],
# ports => [80, 443],
spanel_site => undef,
);
my %Whitelisted; # key = ip address
my $Dbh;
my %Blocked; # key = ip address, value = unix time (time blocked)
my %Ips; # key = ip address, value = expiring array
tie my @Messages, "Tie::Array::Expire", 15;
sub read_config {
require Config::IOD::Reader;
my $iod = Config::IOD::Reader->new();
for my $dir ("$ENV{HOME}/.config", $ENV{HOME}, "/etc") {
my $path = "$dir/$PROG.conf";
next unless -f $path;
my $hoh = $iod->read_file($path);
for my $sect (keys %$hoh) {
unless ($sect eq 'GLOBAL') {
warn "$PROG: Unknown config section '$sect', ignored\n";
next;
}
my $h = $hoh->{$sect};
for my $k (keys %$h) {
unless (exists $Opts{$k}) {
die "$PROG: Unknown config parameter '$k', please fix it first\n";
}
my $v = $h->{$k};
$Opts{$k} = $v;
}
}
}
$Opts{whitelist_ip} = [$Opts{whitelist_ip}]
if defined $Opts{whitelist_ip} && ref $Opts{whitelist_ip} ne 'ARRAY';
}
sub parse_options {
Getopt::Long::GetOptions(
'help|h|?' => sub {
print "Usage: $PROG [options]\n";
print <<EOT;
Usage: $PROG [options]
Options:
--has=S Only consider lines which have string 'S'. Can be specified
multiple times. If specified multiple times, it means lines
must match *all* strings to be considered.
--lacks=S The opposite of --has. Only consider lines which do not have
string 'S'. Can be specified multiple times. If specified
multiple times, it means lines must lack *all* strings to be
considered.
--has-pattern=REGEX
Like --has, but you can specify regex pattern.
--lacks-pattern=REGEX
Like --lacks, but you can specify regex pattern.
--limit=N Start blocking IP which has requested more than N times
during the period.
--period=N Period to count speed limit, in seconds (default: 300,
which means 5 minutes).
--block-period=N
Period of blocking an IP, in seconds (default: 86400, which
means 24 hours a.k.a. 1 day).
--dry-run Do not actually block with iptables, simulation mode.
--spanel-site=NAME
Instead of piping output of tail -f manually, you can use this
( run in 1.218 second using v1.01-cache-2.11-cpan-39bf76dae61 )