]> Raphaël G. Git Repositories - tools/commitdiff
Add spamlist and bloclist options
authorRaphaël Gertz <git@rapsys.eu>
Mon, 30 Jan 2023 15:13:03 +0000 (16:13 +0100)
committerRaphaël Gertz <git@rapsys.eu>
Mon, 30 Jan 2023 15:13:03 +0000 (16:13 +0100)
Use ports list for each service
Cleanup

blacklist

index e950ba087832414a2920a6ceed8200c5eae933b1..a8d27ba1c4a493f9d2a83998e78ca456d31e074c 100755 (executable)
--- a/blacklist
+++ b/blacklist
@@ -3,11 +3,21 @@
 use strict;
 use warnings;
 
+#Load IPC::System::Simple
 use IPC::System::Simple qw(capturex);
+
+#Load Data::Validate::IP
 use Data::Validate::IP qw(is_ipv4 is_ipv6);
+
+#Load NetAddr::IP::Util
 use NetAddr::IP::Util qw(shiftleft inet_4map6 ipv4to6);
+
+#Load NetAddr::IP
 use NetAddr::IP qw(:nofqdn Ones);
 
+#Load POSIX
+use POSIX qw(EXIT_SUCCESS EXIT_FAILURE);
+
 #IP v4 hash
 my %ip4s = ();
 #IP v6 hash
@@ -17,23 +27,62 @@ my @blrule4s = ();
 #Blacklist v6 array
 my @blrule6s = ();
 
+#Init block list
+my $blocklist = 0;
+
+#Init spam list
+my $spamlist = 1;
+
+#Filter options
+@ARGV = map {
+       if ($_ eq '-b' || $_ eq '--blocklist') {
+               $blocklist = 1; ();
+       } elsif ($_ eq '-nb' || $_ eq '--noblocklist') {
+               $blocklist = 0; ();
+       } elsif ($_ eq '-s' || $_ eq '--spamlist') {
+               $spamlist = 1; ();
+       } elsif ($_ eq '-ns' || $_ eq '--nospamlist') {
+               $spamlist = 0; ();
+       } else {
+               $_;
+       }
+} @ARGV;
+
+#Show usage with invalid argument
+if (scalar(@ARGV)) {
+       print "Usage: $0 [-b|--blocklist|-nb|--noblocklist|-s|--spamlist|-ns|--nospamlist]\n";
+       exit EXIT_FAILURE;
+}
+
+#TODO: add google/microsoft/etc mail range ?
+
+#TODO: add all configuration in a json config ?
+
 #IP whitelist
 #my $iplist = qr/^(?:127\.|::1|2a01:4f8:190:22a6:|5\.9\.143\.173|85\.68\.|81\.67\.|89\.157\.|82\.241\.255\.46)/;
 my %iplist = (
        ipv4 => [
-               # Localhost
+               #Localhost
                '127.0.0.0/8',
-               # Aurae
+               #Aurae
                '144.76.27.210/32',
-               # Toulouse
+               #Toulouse
                '82.241.255.46/32',
-               # Akasha
-               '89.3.145.115/32'
+               #Akasha
+               #'89.157.132.244/32'
+               #'89.3.145.115/32'
+               '89.3.147.209/32',
+               #Ygg tracker (tracker.yggtracker.cc)
+               '31.220.0.116/32',
+               #Coppersurfer tracker (tracker.coppersurfer.tk)
+               '31.14.40.30/32',
+               #Pussytorrent tracker (tracker.pussytorrents.org)
+               '217.23.12.105/32'
        ],
        ipv6 => [
-               # Localhost
+               #Localhost
                '::1/32',
-               # Aurae
+               #Aurae
                '2a01:4f8:191:1405::/64'
        ]
 );
@@ -45,14 +94,13 @@ sub new_ipv4($) {
        #Build base struct
        my $self = {
                #Set mask
-               mask    => !defined($mask)||$mask==32?Ones:shiftleft(Ones, 32 - $mask),
+               mask => !defined($mask)||$mask==32?Ones:shiftleft(Ones, 32 - $mask),
                #Mark as ipv4
-               isv6    => 0,
+               isv6 => 0,
                #Generate fake address
                #XXX: NetAddr::IP expect a faked Socket6 gethostbyname struct
                #XXX: see /usr/lib64/perl5/vendor_perl/NetAddr/IP/Util.pm +235
-               #addr   => scalar ($ip, '', AF_INET, 16, NetAddr::IP::Util::inet_4map6(NetAddr::IP::Util::ipv4to6(pack('C4', split('\.', $ip)))))
-               addr    => inet_4map6(ipv4to6(pack('C4', split('\.', $ip))))
+               addr => inet_4map6(ipv4to6(pack('C4', split('\.', $ip))))
        };
        #Return fake NetAddr::IP object
        return bless $self, 'NetAddr::IP';
@@ -63,15 +111,15 @@ my @userlist = ('rapsys');
 
 #Extract sshd.service scan
 #map {
-#      # Extract user and ip
+#      #Extract user and ip
 #      if (/Failed password for (?:invalid user )?(.+) from (.+) port [0-9]+ ssh2/ && grep($_ ne $1, @userlist)) {
-#              # Save ip
+#              #Save ip
 #              my $ip = $2;
-#              # Check if v4 ip and not in whitelist
+#              #Check if v4 ip and not in whitelist
 #              if (is_ipv4($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) {
-#                      # Add ip in v4 blacklist
+#                      #Add ip in v4 blacklist
 #                      $ip4s{$ip}=1;
-#              # Check if v6 ip
+#              #Check if v6 ip
 #              } elsif (is_ipv6($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6}}) {
 #                      $ip6s{$ip}=1;
 #              }
@@ -81,47 +129,63 @@ my @userlist = ('rapsys');
 #Extract kernel port scan
 map {
        #oct. 04 19:10:30 aurae.aoihime.eu kernel: net-fw DROP IN=enp3s0 OUT= MAC=50:46:5d:a1:a1:85:0c:86:10:f5:c6:4b:08:00 SRC=61.227.52.153 DST=144.76.27.210 LEN=52 TOS=0x00 PREC=0x00 TTL=116 ID=29123 DF PROTO=TCP SPT=64349 DPT=445 WINDOW=8192 RES=0x00 SYN URGP=0
-       if (/kernel: net-fw DROP .* SRC=([^\s]+) .* PROTO=([^\s]+) .* DPT=([^\s]+)/) {
-               # Save ip
+       #net-fw DROP IN=enp3s0 OUT= MAC=50:46:5d:a1:a1:85:0c:86:10:f5:c6:4b:08:00 SRC=110.34.70.110 DST=144.76.27.210 LEN=40 TOS=0x00 PREC=0x00 TTL=50 ID=17488 PROTO=TCP SPT=58225 DPT=34567 WINDOW=53283 RES=0x00 SYN URGP=0
+       if (/net-fw DROP .* SRC=([^\s]+) .* PROTO=([^\s]+) .* DPT=([^\s]+)/) {
+               #Save ip
                my $ip = $1;
-               # Save proto
+               #Save proto
                my $proto = lc($2);
-               # Save dpt
+               #Save dpt
                my $dpt = $3;
-               # Check if v4 ip and not in whitelist
+               #Check if v4 ip and not in whitelist
+               #if (is_ipv4($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) {
                if (is_ipv4($ip) && not scalar map { my $network = new_ipv4($_); my $netip = new_ipv4($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) {
                        if (!defined $ip4s{$ip}) {
                                %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {});
                        }
+                       #Add ip in v4 blacklist
                        $ip4s{$ip}{$proto}{$dpt}=1;
                } elsif (is_ipv6($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6}}) {
                        if (!defined $ip6s{$ip}) {
                                %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {});
                        }
+                       #Add ip in v6 blacklist
                        $ip6s{$ip}{$proto}{$dpt}=1;
                }
-               print $ip."\n";
        #oct. 04 19:17:10 aurae.aoihime.eu kernel: audit: type=1100 audit(1570209430.543:17321294): pid=5890 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=? acct="root" exe="/usr/sbin/sshd" hostname=195.154.112.70 addr=195.154.112.70 terminal=ssh res=failed'
+       #audit: type=1100 audit(1570291573.615:8660): pid=3225 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=? acct="root" exe="/usr/sbin/sshd" hostname=222.186.180.9 addr=222.186.180.9 terminal=ssh res=failed'
        } elsif (/op=PAM:authentication grantors=\? acct="(.+)" exe="\/usr\/(?:libexec\/dovecot\/auth|sbin\/sshd)" hostname=.+ addr=(.+) terminal=(dovecot|ssh) res=failed/ && grep($_ ne $1, @userlist)) {
-               # Save ip
+               #Save ip
                my $ip = $2;
-               # Save proto
-               my $proto = 'tcp';
-               # Save dpt
-               my $dpt = $3 eq 'ssh' ? 22 : 445;
-               # Check if v4 ip and not in whitelist
+               #Init blacklist
+               my %blacklist = ('tcp' => [], 'udp' => []);
+               #Set ssh proto and port tuple
+               if ($3 eq 'ssh') {
+                       #Set blacklist for 22 dest port on tcp
+                       #$blacklist{'tcp'}[$#{$blacklist{'tcp'}}+1] = 22;
+                       %blacklist = ('tcp' => [ 22 ]);
+               #Set dovecot proto and port tuples
+               } elsif ($3 eq 'dovecot') {
+                       #Set blacklist for 25, 143, 587, 993 dest ports on tcp and udp
+                       %blacklist = ('tcp' => [ 25, 143, 587, 993 ], 'udp' => [ 25, 143, 587, 993 ]);
+               #Set other proto and port tuples
+               } else {
+               }
+
+               #Check if v4 ip and not in whitelist
                if (is_ipv4($ip) && not scalar map { my $network = new_ipv4($_); my $netip = new_ipv4($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) {
                        if (!defined $ip4s{$ip}) {
                                %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {});
                        }
-                       # Add ip in v4 blacklist
-                       $ip4s{$ip}{$proto}{$dpt}=1;
-               # Check if v6 ip
+                       #Add ip tuples in v4 blacklist
+                       map { my $proto = $_; map { $ip4s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist;
+               #Check if v6 ip
                } elsif (is_ipv6($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6}}) {
                        if (!defined $ip6s{$ip}) {
                                %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {});
                        }
-                       $ip6s{$ip}{$proto}{$dpt}=1;
+                       #Add ip tuples in v6 blacklist
+                       map { my $proto = $_; map { $ip6s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist;
                }
        #nov. 30 15:30:07 aurae.aoihime.eu kernel: audit: type=1100 audit(1575124207.371:38129): pid=685 uid=985 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=? acct="toto" exe="/usr/bin/pwauth" hostname=? addr=? terminal=? res=failed'
        #XXX: Until mod_authnz pass to pwauth the (SERVER_NAME|SERVER_ADDR) + REMOTE_ADDR+REMOTE_PORT in env it's impossible to know who did a failed auth
@@ -131,6 +195,45 @@ map {
        }
 } capturex('journalctl', '-m', '-t', 'kernel', '-o', 'cat', '--no-hostname');
 
+#With spamlist
+if ($spamlist) {
+       #Extract originating ip in spam
+       map {
+               #Open spam file for reading
+               open (my $fh, '<', $_) or die "Can't open < $_: $!";
+
+               #Lookup for X-Originating-IP header
+               while (<$fh>) {
+                       if (/X-Originating-IP: (.+)$/) {
+                               #Set ip
+                               my $ip = ${1};
+
+                               #Set blacklist for 80 and 443 dest ports on tcp
+                               my %blacklist = ('tcp' => [ 80, 443, 8000, 8080, 8443 ]);
+
+                               #Check if v4 ip and not in whitelist
+                               #if (is_ipv4($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) {
+                               if (is_ipv4($ip) && not scalar map { my $network = new_ipv4($_); my $netip = new_ipv4($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) {
+                                       if (!defined $ip4s{$ip}) {
+                                               %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {});
+                                       }
+                                       #Add ip tuples in v4 blacklist
+                                       map { my $proto = $_; map { $ip4s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist;
+                               } elsif (is_ipv6($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6}}) {
+                                       if (!defined $ip6s{$ip}) {
+                                               %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {});
+                                       }
+                                       #Add ip tuples in v6 blacklist
+                                       map { my $proto = $_; map { $ip6s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist;
+                               }
+                       }
+               }
+
+               #Close spam file
+               close $fh or die "Can't close fh: $!";
+       } glob('/var/spool/mail/*/.Junk/{new,cur,tmp}/*');
+}
+
 #Process each ipv4s keys
 map {
        #Set proto as either tcp or udp
@@ -164,19 +267,30 @@ open (my $fh, '<', '/etc/shorewall/blrules') or die "Can't open < /etc/shorewall
 #Prepend each specific ip from whitelist
 map { push @blrule4s, "WHITELIST\tnet:$1\tall" if (/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/32$/); } @{$iplist{ipv4}};
 
+#Close blrule4s file
+close $fh or die "Can't close fh: $!";
+
+#With blocklist
+if ($blocklist) {
+       #Open bt_blocklists.ipv4 file for reading
+       open ($fh, '<', '/usr/local/share/blacklist/shorewall.ipv4') or die "Can't open < /usr/local/share/blacklist/shorewall.ipv4: $!";
+
+       #Prepend bt_blocklists.ipv4 drop
+       map { chomp $_; push @blrule4s, "DROP\t\tnet:$_\tfw"; } <$fh>;
+
+       #Close bt_blocklists.ipv4 file
+       close $fh or die "Can't close fh: $!";
+}
 
 #Build blacklist
 map {
        #Set proto from hash
-       for my $proto (keys %{$ip4s{$_}}) {
+       for my $proto (sort keys %{$ip4s{$_}}) {
                #Push rule
-               push @blrule4s, "DROP\t\tnet:".$_.(length($_)<12?"\t":'')."\tfw\t$proto\t".(scalar keys %{$ip4s{$_}{$proto}}>5||defined $ip4s{$_}{$proto}{0}?'#':'').join(",", keys %{$ip4s{$_}{$proto}});
+               push @blrule4s, "DROP\t\tnet:".$_.(length($_)<12?"\t":'')."\tfw\t$proto\t".(scalar keys %{$ip4s{$_}{$proto}}>5||defined $ip4s{$_}{$proto}{0}?'#':'').join(",", sort { $a <=> $b } keys %{$ip4s{$_}{$proto}});
        }
 } sort keys %ip4s;
 
-#Close blrule4s file
-close $fh or die "Can't close fh: $!";
-
 #Open blrule4s file for writing
 open ($fh, '>', '/etc/shorewall/blrules') or die "Can't open > /etc/shorewall/blrules: $!";
 
@@ -196,5 +310,7 @@ for (sort keys %ip6s) {
        }
 }
 
-# Restart shorewall service
+#TODO: add ipv6 ?
+
+#Restart shorewall service
 capturex('systemctl', 'restart', 'shorewall.service');