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 )