Blocklist script mit ipset

Anleitungen zu Fail2Ban, blocklist.de und x-arf
Antworten
Virus2500@me.com
Beiträge: 8
Registriert: 26. Mai 2011, 01:54

Blocklist script mit ipset

Beitrag von Virus2500@me.com » 27. Dez 2013, 11:26

Hallo,

vielleicht interessiert es ja den ein oder anderen :)

Hab ein perl script geschrieben das sich per wget die all.txt von blocklist.de holt und das ganze in eine ipset blocklist schreibt.
ipset muss ggf. nachinstalliert werden

Ausserdem erstellt das script eine iptables chain BLOCKLIST und verweist auf diese in der INPUT Chain (iptables -I INPUT) damit die Rule ganz vorne steht.
In der Blocklist Chain wird geloggt und gedropt :)

Beim ersten mal dauert es ein bisschen alle IPs einzulesen. Danach wird mittels hash die ipset liste mit der all.txt verglichen.
Das dauert dann nur noch Sekunden.

Habe es bei mir jede Stunde als cronjob laufen
0 */1 * * * /usr/bin/perl /scripts/blocklist.pl

so aber jetzt zum script [EDIT: Bitte über den Github Link unten beziehen... Es hat sich mittlerweile einiges geändert :) ]

Code: Alles auswählen

#!/usr/bin/perl
use strict; use warnings;
################################################################
###### Script to check Blocklist.de list. Block new IP    ######
###### and unblock old delete entrys                      ######
################################################################

## config ##
my $listUrl = "http://lists.blocklist.de/lists/all.txt";
my $fileName = "Blocklist.txt";
my $tmpDir = "/tmp";
my $file = "$tmpDir/$fileName";

## binarys ##
my $iptables = "/sbin/iptables";
my $ipset = "/usr/sbin/ipset";
my $grep = "/bin/grep";
my $rm = "/bin/rm";
my $wget = "/usr/bin/wget";

## plain variables ##
my($row, $Blocklist, $line, $check, $checkLine, $result, $output, $ipRegex, $ipToRegex);

my ($added, $removed, $skipped);
$added = $removed = $skipped = 0;

## init arrays ##
my @fileArray = ();
my @ipsetArray = ();

## init hashes for faster searching
my %ipsetArray;
my %fileArray;

#****************************#
#*********** MAIN ***********#
#****************************#
&iptablesCheck();
&getFileArray();
&getIpsetArray();
&addIpsToBlocklist();
&remIpsFromBlocklist();
&cleanup();

exit;
#***** END MAIN *****#


#****************************#
#******* Subroutines ********#
#****************************#



############# iptablesCheck ###############
## checks if all necessary               ##
## iptable/ipset Settings have been set  ##
###########################################

sub iptablesCheck {
    ## Do we have an BLOCKLIST/DROP Chain?
    if (`$iptables -L -n | $grep BLOCKLIST` =~ m/Chain BLOCKLIST/) {
    } else {
        print "Creating Chain BLOCKLIST \n";
        `$iptables -N BLOCKLIST`;
        `$iptables -A BLOCKLIST -m limit --limit 2/min -j LOG --log-prefix "Blocklist Dropped: " --log-level 4`;
        `$iptables -A BLOCKLIST -j DROP`;
    }

    ## Do we have an ipset list called blocklist?
    if(`$ipset list -n | $grep blocklist` =~ m/blocklist/) {
    } else {
        `$ipset create blocklist hash:ip hashsize 4096`;
        print "Created ipset list blocklist\n";
    }

    ## Is there an forwarded from INPUT to BLOCKLIST?
    if (`$iptables -L INPUT | $grep BLOCKLIST`=~ m/BLOCKLIST/) {
    } else {
        print "Creating forward to BLOCKLIST chain \n";
        `$iptables -I INPUT -m set --match-set blocklist src -j BLOCKLIST`;
    }
}

######## END iptablesCheck ########


########## getFileArray #############
## downloads the Blocklist.txt and ##
## pushes it into an array         ##
#####################################
sub getFileArray {
    `$wget -q -O $tmpDir/$fileName $listUrl && echo "Downloaded temp file to $tmpDir/$fileName" || echo "Can not download file.... stopping"`;

    open(INFO, $file) or die("Could not open file.");
    foreach $line (<INFO>) {
        push(@fileArray, $line);
    }

    close(INFO);
    chomp(@fileArray);
    %fileArray = map {$_ => 1 } @fileArray;
}
####### END getFileArray ##########

######### getIpsetArray ##########
## runs ipset list blocklist    ##
## and pushes it into           ##
## array ipsetList              ##
##################################

sub getIpsetArray {
    $output = `$ipset list blocklist`;
    @ipsetArray = split("\n", $output);
#    %ipsetArray = map { $_ => 1} @ipsetArray;
    #remove the first 6 Elements of our Array using splice (ipset header info)
    splice @ipsetArray, 0, 6;
    %ipsetArray = map { $_ => 1} split("\n", $output);
}

##### END getIpsetArray #########

######## addIpsToBlocklist ######
## adds IPs to our blocklist   ##
#################################

sub addIpsToBlocklist {
    foreach $line (@fileArray) {
        if (exists $ipsetArray{"$line"}) {
            $skipped++;
        } else {
            if ($line eq &isIpv4($line)) {
                $result = `$ipset add blocklist $line`;
                $added++;
                print "added $line\n"
            } else {
                $skipped++;
            }
        }
    }
}
######## END addIpsToBlocklist ######

########## remIpsFromBlocklist ########
## remove IPs from our blocklist   ##
#####################################
sub remIpsFromBlocklist {
    foreach $line (@ipsetArray) {
        if (exists $fileArray{"$line"}) {
            $skipped++;
        } else {
            if ($line eq &isIpv4($line)) {
                $result = `$ipset del blocklist $line`;
                print "removed $line\n";
                $removed++;
            } else {
                $skipped++;
            }
        }
    }
}

######## END remIpsFromBlocklist ########


################## cleanup ###################
#### Cleanup: move tmp file to new place #####
##############################################
sub cleanup {
    $result = `$rm $tmpDir/$fileName && echo "Deleted file $tmpDir/$fileName" || echo "Can\t delete file $tmpDir/$fileName"`;
    print "\nWe added $added, removed $removed, skipped $skipped Rules\n";
}
############### END cleanup ######################

########## ipToRegex ##########
## converts an ip to regex   ##
## e.g. 192.168.0.1 to       ##
##      192\.168\.0\.1       ##
###############################
sub ipToRegex {
    my ($ip) = @_;
    $ip =~ s/\./\\./g;
    return "$ip";
}
######## END ipToRegex ########

############ isIpv4 #############
## check if given value looks  ##
## like an ipv4 ip address     ##
#################################
sub isIpv4 {
    my ($isIp) = @_;
    if ($isIp =~ m/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/) {
        #print "It's an IPv4\n";
        return $isIp;
    } else {
        return 0;
    }
}
######### END isIpv4 ##########

######### EOF ###########
Ist mein erstes public projekt. Also ja ich bin nicht der große Programmierer. Wer was verbessern kann oder will, gerne!
Projekt ist auch auf github ( https://github.com/virus2500/blocklist-with-ipset/ )

lg
Zuletzt geändert von Virus2500@me.com am 29. Apr 2014, 22:39, insgesamt 1-mal geändert.

mfritsche
Beiträge: 1
Registriert: 13. Apr 2014, 19:50

Re: Blocklist script mit ipset

Beitrag von mfritsche » 13. Apr 2014, 19:57

Moin Virus,

Danke für das Script!

Ich habe es als Ausgangspunkt genommen, um meine eigene Lösung in Lua zu schreiben (da ich auch IPv6-Addressen blockieren möchte).

Zu haben unter: http://reauktion.de/blocklist.tar.gz

Aus meinem Blog (shameless plug): http://reauktion.de/flugphase/?p=2059

Um das Skript zu verwenden, müssen iptables, ip6tables und ipset installiert sein. Weiterhin muss die “nixio”-Library von Lua installiert werden – z.B. via “sudo luarocks install nixio” (das hat bei mir nicht auf Anhieb funktioniert, deswegen habe ich mir die nixio-Bibliothek von Luci geborgt; Luci per subversion gezogen und per make übersetzt, danach mittels ‘find -name “nixio.so” -type f’ die Bibliothek ausfinding gemacht und ins Verzeichnis von blocklist.lua kopiert).

Nun wird das Skript einmal in der Stunde per cron ausgeführt:

21 */1 * * * /root/blocklist.lua > /dev/null 2>&1
Außerdem wird die Datei /root/bannedips.txt ausgewertet, die mit einem Leerzeichen starten muss (so blocke ich Pixray von der IP 2001:4ba0:ffe1:76::2).

Das Script liest dle blocklist aus, trägt die neu hinzugekommenen IPs in die Firewall ein und entfernt die IPs, die nicht mehr auf der Blocklist stehen. Für IPv4 wird auf Host-Ebene gesperrt, bei IPv6 mindestens das 64er-Subnet (es sei denn, in der Blocklist ist ein größerer Netzbereich eingetragen).

cabal
Beiträge: 17
Registriert: 11. Mär 2012, 14:12

Re: Blocklist script mit ipset

Beitrag von cabal » 17. Apr 2014, 14:14

ich versuche das gerade auf einem debian squeeze, scheint aber irgendetwas nicht zu klappen, woran könnte das liegen?

Code: Alles auswählen

Chain BLOCKLIST (0 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere            limit: avg 2/min burst 5 LOG level warning prefix `Blocklist Dropped: ' 
DROP       all  --  anywhere             anywhere 

Code: Alles auswählen

ipset list -t
Bad argument `list'
IPSET habe ich wie folgt installiert:

Code: Alles auswählen

apt-get install ipset xtables-addons-source xtables-addons-common
module-assistant auto-install xtables-addons
dann das Script aufgerufen, dabei kamen dann eine Menge dieser Fehlermeldungen:

Code: Alles auswählen

Try `ipset -H' or 'ipset --help' for more information.
added 188.95.234.6
Try `ipset -H' or 'ipset --help' for more information.
added 188.143.235.21
Try `ipset -H' or 'ipset --help' for more information.
added 95.134.130.182
Try `ipset -H' or 'ipset --help' for more information.
added 95.143.192.159

cabal
Beiträge: 17
Registriert: 11. Mär 2012, 14:12

Re: Blocklist script mit ipset

Beitrag von cabal » 18. Apr 2014, 15:26

OK, ich habe das ganze jetzt mal fuer ein Debian Squeeze angepasst:

Code: Alles auswählen

apt-get install ipset xtables-addons-source
module-assistant auto-install xtables-addons
testen:

Code: Alles auswählen

ipset --version
ipset -N test iphash
ipset --list
ipset -X test
ipset --list
nano /root/blocklist.pl

Code: Alles auswählen

#!/usr/bin/perl
use strict; use warnings;
################################################################
###### Script to check Blocklist.de list. Block new IP    ###### 
###### and unblock deleted entrys                         ###### 
################################################################

## config ##
my $listUrl = "http://lists.blocklist.de/lists/all.txt";
my $fileName = "Blocklist.txt";
my $tmpDir = "/tmp";
my $file = "$tmpDir/$fileName";
my $logFile = "/var/log/blocklist";

## binarys ##
my $iptables = "/sbin/iptables";
my $ipset = "/usr/sbin/ipset";
my $grep = "/bin/grep";
my $rm = "/bin/rm";
my $wget = "/usr/bin/wget";

## plain variables ##
my($row, $Blocklist, $line, $check, $checkLine, $result, $output, $ipRegex, $message);

my ($added, $removed, $skipped); 
$added = $removed = $skipped = 0;

## init arrays ##
my @fileArray = ();
my @ipsetArray = ();

## init hashes for faster searching
my %ipsetArray;
my %fileArray;

my $dateTime;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
my @months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my @days = qw(Sun Mon Tue Wed Thu Fri Sat Sun);

#****************************#
#*********** MAIN ***********#
#****************************#
logging("Starting blocklist refresh");
&iptablesCheck();
&getFileArray();
&getIpsetArray();
&addIpsToBlocklist();
&remIpsFromBlocklist();
&cleanup();

exit;
#***** END MAIN *****#


#****************************#
#******* Subroutines ********#
#****************************#



############# iptablesCheck ###############
## checks if all necessary               ##
## iptable/ipset Settings have been set  ##
###########################################

sub iptablesCheck {
    ## Do we have an BLOCKLIST/DROP Chain?
    if (`$iptables -L -n | $grep BLOCKLIST` =~ m/Chain BLOCKLIST/) {
    } else {
        $message = "Creating Chain BLOCKLIST";
        logging($message);
        `$iptables -N BLOCKLIST`;
        `$iptables -A BLOCKLIST -m limit --limit 2/min -j LOG --log-prefix "Blocklist Dropped: " --log-level 4`;
        `$iptables -A BLOCKLIST -j DROP`;
    }
    
    ## Do we have an ipset list called blocklist?
    if(`$ipset list -n | $grep blocklist` =~ m/blocklist/) {
    } else {
        `$ipset -N blocklist iphash --hashsize 4096`;
        $message = "Created ipset list blocklist";
        logging($message);
    }
    
    ## Is there an forwarded from INPUT to BLOCKLIST?
    if (`$iptables -L INPUT | $grep BLOCKLIST`=~ m/BLOCKLIST/) {
    } else {
        `$iptables -I INPUT -m set --match-set blocklist src -j BLOCKLIST`;
        $message = "Creating forward to BLOCKLIST chain";
        logging($message);
    }
}

######## END iptablesCheck ########


########## getFileArray #############
## downloads the Blocklist.txt and ##
## pushes it into an array         ##
#####################################
sub getFileArray {
    `$wget -q -O $tmpDir/$fileName $listUrl && echo "Downloaded temp file to $tmpDir/$fileName" || echo "Can not download file.... stopping"`;

    open(INFO, $file) or die("Could not open file.");
    foreach $line (<INFO>) {
        push(@fileArray, $line);
    }

    close(INFO);
    chomp(@fileArray);
    %fileArray = map {$_ => 1 } @fileArray;
}
####### END getFileArray ##########

######### getIpsetArray ##########
## runs ipset list blocklist    ##
## and pushes it into           ##
## array ipsetList              ##
##################################

sub getIpsetArray {
    $output = `$ipset list blocklist`;
    @ipsetArray = split("\n", $output);
#    %ipsetArray = map { $_ => 1} @ipsetArray;
    #remove the first 6 Elements of our Array using splice (ipset header info)
    splice @ipsetArray, 0, 6;
    %ipsetArray = map { $_ => 1} split("\n", $output);
}

##### END getIpsetArray #########

######## addIpsToBlocklist ######
## adds IPs to our blocklist   ##
#################################

sub addIpsToBlocklist {
    foreach $line (@fileArray) { 
        if (exists $ipsetArray{"$line"}) {
            $skipped++;
        } else {
            if ($line eq &isIpv4($line)) { 
                $result = `$ipset -A blocklist $line`;
                $added++;
                $message = "added $line";
                logging($message);
            } else {
                $skipped++;
            }
        }
    }
}
######## END addIpsToBlocklist ######

########## remIpsFromBlocklist ########
## remove IPs from our blocklist   ##
#####################################
sub remIpsFromBlocklist {
    foreach $line (@ipsetArray) {
        if (exists $fileArray{"$line"}) {
            $skipped++;   
        } else {
            if ($line eq &isIpv4($line)) {
                $result = `$ipset -D blocklist $line`;
                $message = "removed $line";
                logging($message);
                $removed++;
            } else {
                $skipped++;
            }
        }
    }
}

######## END remIpsFromBlocklist ########


################## cleanup ###################
#### Cleanup: move tmp file to new place #####
##############################################
sub cleanup {
    $result = `$rm $tmpDir/$fileName && echo "Deleted file $tmpDir/$fileName" || echo "Can\t delete file $tmpDir/$fileName"`;
    $message = "We added $added, removed $removed, skipped $skipped Rules";
    logging($message);
}
############### END cleanup ######################

############ isIpv4 #############
## check if given value looks  ##
## like an ipv4 ip address     ##
#################################
sub isIpv4 {
    my ($isIp) = @_;
    if ($isIp =~ m/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/) {
        #print "It's an IPv4\n";
        return $isIp;
    } else {
        return 0;
    }
}
######### END isIpv4 ##########

###### log #######
## log $message ##
##################
sub logging {
    my ($message) = @_;

    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();

    open my $fh, ">>", $logFile
        or die "Can't open logfile: $!";
    $dateTime = sprintf("$months[$mon]  %02d %02d:%02d:%02d ", $mday,$hour,$min,$sec);
    print $fh "$dateTime $message\n";
    print "$message\n";

    close($fh);
}
#### end log #####
######### EOF ###########
chmod +x /root/blocklist.pl

cronjob jede stunde:

Code: Alles auswählen

0 */1 * * * /usr/bin/perl /root/blocklist.pl
testen und auflisten:
ipset --list

Virus2500@me.com
Beiträge: 8
Registriert: 26. Mai 2011, 01:54

Re: Blocklist script mit ipset

Beitrag von Virus2500@me.com » 28. Apr 2014, 14:48

Hello zusammen.

Irgendwie hab ich vermutet das ich eine Benachrichtung bekomme wenn sich hier was tut.. scheinbar hab ich irgendwas nicht richtig eingestellt :)

@mfritsche Hab mit lua noch nicht gearbeitet. Äusserst interessant wenn man "sein" Script in einer anderen Sprache sieht :)
@cabal musstest du diese Änderungen, wie z.b. ipset add durch ipset -A ersetzen wg. squeeze machen oder war das eine optische anpassung?

P.s. Die Github version ist schon etwas aktueller. Beinhaltet u.a. auch eine Black und Whitelist...

danke und lg
Mike

thaliruth
Beiträge: 1
Registriert: 10. Jan 2015, 14:55

Re: Blocklist script mit ipset

Beitrag von thaliruth » 14. Jan 2015, 09:28

Hallo, und erst einmal danke für das wunderbare Script. Aber wie genau Funkioniert dies? Ich kann es ausführen, es werden auch die Listen genommen und die IP Adressen geaddet so steht es in meiner Konsole. Aber in IPTables werden scheinbar diese IPs nicht eingetragen. Ich habe zum testen einfach mal eine Blacklist von mir genommen mit meiner IP drauf um zu testen ob es geht. Obwohl in der Shell steht IP Adresse wurde hinzugefügt, kann ich ohne weiteres meine Seiten ansteuern und werde nicht geblockt.

Virus2500@me.com
Beiträge: 8
Registriert: 26. Mai 2011, 01:54

Re: Blocklist script mit ipset

Beitrag von Virus2500@me.com » 14. Jan 2015, 21:53

Hallo, erstmal bitte bitte :)

Hast du die letzte Version, wie oben beschrieben, von Github geladen?

Das du in iptables "nichts siehst" ist gut. Vorrausgesetzt du siehst zumindestens diese Einträge.

Code: Alles auswählen

Chain INPUT
target     prot opt source               destination
BLOCKLIST  all  --  anywhere             anywhere             match-set blocklist-v6 src
BLOCKLIST  all  --  anywhere             anywhere             match-set blocklist src

Chain BLOCKLIST (2 references)
target     prot opt source               destination
LOG        all  --  anywhere             anywhere             limit: avg 2/min burst 5 LOG level warning prefix "Blocklist Dropped: "
DROP       all  --  anywhere             anywhere
Der Vorteil an dem Script ist eben das die IPs nicht direkt im iptables landen sondern in zwei ipset listen. Solch lange Blocklisten wie hier auf blocklist.de führen dazu daß das System merklich ausgebremst wird. Das kann mit ipset umgangen werden. Hierzu ladet man die Liste in ipset und übergibt iptables dann "match-set [name der blocklist] src/dst"

Um die IP listen zu sehen kann man"ipset list" ausführen also z.b.

Code: Alles auswählen

root@home:~# ipset list -n
blocklist
blocklist-v6
oder

Code: Alles auswählen

root@home:~# ipset list blocklist
<riesiger haufen ips>
probier bitte einfach mal was bei dir bei "ipset list blocklist" rauskommt und ob die Filter in der INPUT list landen bzw. ob nicht davor vielleicht ein allow drinnen ist.

lg
Mike

Antworten