]>
Raphaƫl G. Git Repositories - binary/blob - blacklist
   6 #Load IPC::System::Simple 
   7 use IPC
::System
::Simple 
qw(capturex); 
   9 #Load Data::Validate::IP 
  10 use Data
::Validate
::IP 
qw(is_ipv4 is_ipv6); 
  12 #Load NetAddr::IP::Util 
  13 use NetAddr
::IP
::Util 
qw(shiftleft inet_4map6 ipv4to6); 
  16 use NetAddr
::IP 
qw(:nofqdn Ones); 
  19 use POSIX 
qw(EXIT_SUCCESS EXIT_FAILURE); 
  24 #use Net::CIDR qw(range2cidr); 
  26 #use Data::Dump qw(dump); 
  45         if ($_ eq '-b' || $_ eq '--blocklist') { 
  47         } elsif ($_ eq '-nb' || $_ eq '--noblocklist') { 
  49         } elsif ($_ eq '-s' || $_ eq '--spamlist') { 
  51         } elsif ($_ eq '-ns' || $_ eq '--nospamlist') { 
  58 #Show usage with invalid argument 
  60         print "Usage: $0 [-b|--blocklist|-nb|--noblocklist|-s|--spamlist|-ns|--nospamlist]\n"; 
  65 #my $iplist = qr/^(?:127\.|::1|2a01:4f8:190:22a6:|5\.9\.143\.173|85\.68\.|81\.67\.|89\.157\.|82\.241\.255\.46)/; 
  78                 #Hotel recamier (because of port scan) 
  80                 #Ygg tracker (tracker.yggtracker.cc) 
  82                 #Coppersurfer tracker (tracker.coppersurfer.tk) 
  84                 #Pussytorrent tracker (tracker.pussytorrents.org) 
  91                 '2a01:4f8:191:1405::/64' 
 109 #Create a new NetAddr::IP object without calling slow gethostbyname (load /etc/resolv.conf) 
 112         my ($ip, $mask) = split('/', shift); 
 116                 mask 
=> !defined($mask)||$mask==32?Ones
:shiftleft
(Ones
, 32 - $mask), 
 119                 #Generate fake address 
 120                 #XXX: NetAddr::IP expect a faked Socket6 gethostbyname struct 
 121                 #XXX: see /usr/lib64/perl5/vendor_perl/NetAddr/IP/Util.pm +235 
 122                 addr 
=> inet_4map6
(ipv4to6
(pack('C4', split('\.', $ip)))) 
 124         #Return fake NetAddr::IP object 
 125         return bless $self, 'NetAddr::IP'; 
 129 my @userlist = ('rapsys', 'airlibre'); 
 133         tcp 
=> [ 80, 443, 8000, 8080, 8443 ], 
 137 #Extract sshd.service scan 
 139 #       #Extract user and ip 
 140 #       if (/Failed password for (?:invalid user )?(.+) from (.+) port [0-9]+ ssh2/ && grep($_ ne $1, @userlist)) { 
 143 #               #Check if v4 ip and not in whitelist 
 144 #               if (is_ipv4($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) { 
 145 #                       #Add ip in v4 blacklist 
 148 #               } elsif (is_ipv6($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6}}) { 
 152 #} capturex('journalctl', '-u', 'sshd.service'); 
 154 #Extract kernel port scan 
 156         #XXX to ignore: net-fw DROP IN=enp3s0 OUT= MAC=50:46:5d:a1:a1:85:0c:86:10:f5:c6:4b:08:00 SRC=1.39.26.11 DST=144.76.27.210 LEN=348 TOS=0x00 PREC=0x00 TTL=51 ID=52475 PROTO=ICMP TYPE=3 CODE=3 [SRC=144.76.27.210 DST=1.39.26.11 LEN=320 TOS=0x00 PREC=0x00 TTL=47 ID=52473 PROTO=UDP SPT=6700 DPT=40992 LEN=300 ] 
 157         #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 
 158         #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 
 159         if (/net-fw DROP .* SRC=([^\s]+) [^\[]* PROTO=(TCP|UDP) .* DPT=([^\s]+)/ && (! defined ${portlist
}{lc($2)} || ! scalar map { unless ($_ eq $3) { (); } } @{$portlist{lc($2)}})) { 
 166                 #Check if v4 ip and not in whitelist 
 167                 #if (is_ipv4($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) { 
 168                 if (is_ipv4
($ip) && not scalar map { my $network = new_ipv4
($_); my $netip = new_ipv4
($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4
}}) { 
 169                         if (!defined $ip4s{$ip}) { 
 170                                 %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 172                         #Add ip in v4 blacklist 
 173                         $ip4s{$ip}{$proto}{$dpt}=1; 
 174                 } elsif (is_ipv6
($ip) && not scalar map { my $network = NetAddr
::IP-
>new($_); my $netip = NetAddr
::IP-
>new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6
}}) { 
 175                         if (!defined $ip6s{$ip}) { 
 176                                 %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 178                         #Add ip in v6 blacklist 
 179                         $ip6s{$ip}{$proto}{$dpt}=1; 
 181         #XXX to ignore: imap-login: Disconnected: Inactivity (no auth attempts in 180 secs): user=<>, rip=92.154.96.153, lip=144.76.27.210, TLS handshaking, session=<86h+BZAE1VdcmmCZ> 
 182         #From journalctl -f -m -t dovecot -o cat --no-hostname | grep -E '^imap-login: Disconnected: .+ user=<(.+)>, .*rip=([^,]+)' 
 183         #imap-login: Disconnected: Aborted login by logging out (auth failed, 1 attempts in 6 secs): user=<laurence.gertz>, method=PLAIN, rip=103.199.18.128, lip=144.76.27.210, TLS, session=<D7/6qNABW7FnxxKA> 
 184         } elsif (/^imap-login: Disconnected: (?:Too many invalid commands|Aborted login by logging out|Connection closed \((?:auth failed, [0-9]+ attempts in [0-9]+ secs|tried to use unsupported auth mechanism)\)|Connection closed: (?:read\(size=[0-9]+\)|SSL_accept\(\)|SSL_read) failed).*? user=<(.*?)>, .*?rip=(.+?), / && grep($_ ne $1, @userlist)) { 
 187                 #Set blacklist for 143, 993, 4190 dest ports on tcp 
 188                 my %blacklist = ('tcp' => [ 143, 993, 4190 ]); 
 189                 #Check if v4 ip and not in whitelist 
 190                 if (is_ipv4
($ip) && not scalar map { my $network = new_ipv4
($_); my $netip = new_ipv4
($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4
}}) { 
 191                         if (!defined $ip4s{$ip}) { 
 192                                 %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 194                         #Add ip tuples in v4 blacklist 
 195                         map { my $proto = $_; map { $ip4s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 197                 } elsif (is_ipv6
($ip) && not scalar map { my $network = NetAddr
::IP-
>new($_); my $netip = NetAddr
::IP-
>new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6
}}) { 
 198                         if (!defined $ip6s{$ip}) { 
 199                                 %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 201                         #Add ip tuples in v6 blacklist 
 202                         map { my $proto = $_; map { $ip6s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 204         #XXX to ignore: warning: non-SMTP command from lputeaux-656-1-79-153.w92-154.abo.wanadoo.fr[92.154.96.153]: GET / HTTP/1.1 
 205         #sudo journalctl -f -m -t postfix/smtpd -t postfix/submission/smtpd -t postfix/submissions/smtpd -t postfix/smtps/smtpd -o cat --no-hostname | grep -E '^(warning: Illegal address syntax from [^ ]+\[|warning: numeric hostname: |warning: [^ ]+\[|SSL_accept error from [^ ]+\[)([0-9a-f:\.]+)(|\]:? .*)$' 
 206         #sudo journalctl -f -m -t postfix/smtpd -t postfix/submission/smtpd -t postfix/submissions/smtpd -t postfix/smtps/smtpd -o cat --no-hostname | perl -pne 'if (/^(?:warning: Illegal address syntax from [^ ]+\[|warning: numeric hostname: |warning: [^ ]+\[|SSL_accept error from [^ ]+\[)([0-9a-f:\.]+)(?:|\]:? .*)$/) { print $1.":".$_; } else { }; undef $_;' 
 207         #warning: Illegal address syntax from unknown[113.80.102.166] in MAIL command: <quentin@blower,net> 
 208         #warning: numeric hostname: 187.145.20.160 
 209         #warning: non-SMTP command from unknown[2001:41d0:8:ed7b::1]: * 
 210         #warning: unknown[80.94.95.184]: SASL LOGIN authentication failed: UGFzc3dvcmQ6 
 211         #SSL_accept error from 162.194.196.104.bc.googleusercontent.com[104.196.194.162]: lost connection 
 212         #} elsif (/^warning: (?:.*\[(.+)\]: .+ authentication failed:.*|numeric hostname: (.+)|non-SMTP command from .*\[(.+)\]: .*|Illegal address syntax from .*\[(.+)\] in .+ command: .*)$/) { 
 213         } elsif (/^(?:warning: Illegal address syntax from [^ ]+\[|warning: numeric hostname: |warning: [^ ]+\[|SSL_accept error from [^ ]+\[)([0-9a-f:\.]+)(?:|\]:? .*)$/) { 
 216                 #Set blacklist for 25, 465, 587 dest ports on tcp 
 217                 my %blacklist = ('tcp' => [ 25, 465, 587 ]); 
 218                 #Check if v4 ip and not in whitelist 
 219                 if (is_ipv4
($ip) && not scalar map { my $network = new_ipv4
($_); my $netip = new_ipv4
($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4
}}) { 
 220                         if (!defined $ip4s{$ip}) { 
 221                                 %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 223                         #Add ip tuples in v4 blacklist 
 224                         map { my $proto = $_; map { $ip4s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 226                 } elsif (is_ipv6
($ip) && not scalar map { my $network = NetAddr
::IP-
>new($_); my $netip = NetAddr
::IP-
>new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6
}}) { 
 227                         if (!defined $ip6s{$ip}) { 
 228                                 %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 230                         #Add ip tuples in v6 blacklist 
 231                         map { my $proto = $_; map { $ip6s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 233         #From journalctl -m -t sshd -o cat --no-hostname | grep -E '^Failed .+ for( invalid user)? (.+) from (.+) port [0-9]+ (ssh)2$' 
 234         #Failed keyboard-interactive/pam for invalid user supervisor from 168.0.232.246 port 26468 ssh2 
 235         #Failed password for invalid user mc from 103.38.4.238 port 37738 ssh2 
 236         } elsif (/^Failed .+ for(?: invalid user)? (.+) from (.+) port [0-9]+ ssh2$/ && grep($_ ne $1, @userlist)) { 
 239                 #Set blacklist for 22 dest port on tcp 
 240                 my %blacklist = ('tcp' => [ 22 ]); 
 241                 #Check if v4 ip and not in whitelist 
 242                 if (is_ipv4
($ip) && not scalar map { my $network = new_ipv4
($_); my $netip = new_ipv4
($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4
}}) { 
 243                         if (!defined $ip4s{$ip}) { 
 244                                 %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 246                         #Add ip tuples in v4 blacklist 
 247                         map { my $proto = $_; map { $ip4s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 249                 } elsif (is_ipv6
($ip) && not scalar map { my $network = NetAddr
::IP-
>new($_); my $netip = NetAddr
::IP-
>new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6
}}) { 
 250                         if (!defined $ip6s{$ip}) { 
 251                                 %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 253                         #Add ip tuples in v6 blacklist 
 254                         map { my $proto = $_; map { $ip6s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 257 } capturex
('journalctl', '-m', '-t', 'kernel', '-t', 'dovecot', '-t', 'postfix/smtpd', '-t', 'postfix/submission/smtpd', '-t', 'postfix/submissions/smtpd', '-t', 'postfix/smtps/smtpd', '-t', 'sshd', '-o', 'cat', '--no-hostname'); 
 261         #Extract originating ip in spam 
 263                 #Open spam file for reading 
 264                 open (my $fh, '<', $_) or die "Can't open < $_: $!"; 
 266                 #Lookup for X-Originating-IP header 
 268                         if (/X-Originating-IP: (.+)$/) { 
 272                                 #Set blacklist for 80 and 443 dest ports on tcp 
 273                                 #my %blacklist = ('tcp' => [ 80, 443, 8000, 8080, 8443 ]); 
 274                                 my %blacklist = %portlist; 
 276                                 #Check if v4 ip and not in whitelist 
 277                                 #if (is_ipv4($ip) && not scalar map { my $network = NetAddr::IP->new($_); my $netip = NetAddr::IP->new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4}}) { 
 278                                 if (is_ipv4
($ip) && not scalar map { my $network = new_ipv4
($_); my $netip = new_ipv4
($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv4
}}) { 
 279                                         if (!defined $ip4s{$ip}) { 
 280                                                 %{$ip4s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 282                                         #Add ip tuples in v4 blacklist 
 283                                         map { my $proto = $_; map { $ip4s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 284                                 } elsif (is_ipv6
($ip) && not scalar map { my $network = NetAddr
::IP-
>new($_); my $netip = NetAddr
::IP-
>new($ip); unless ($network->contains($netip)) { (); } } @{$iplist{ipv6
}}) { 
 285                                         if (!defined $ip6s{$ip}) { 
 286                                                 %{$ip6s{$ip}} = ('tcp' => {}, 'udp' => {}); 
 288                                         #Add ip tuples in v6 blacklist 
 289                                         map { my $proto = $_; map { $ip6s{$ip}{$proto}{$_}=1; } @{$blacklist{$proto}}; } keys %blacklist; 
 295                 close $fh or die "Can't close fh: $!"; 
 296         } glob('/var/spool/mail/*/.Junk/{new,cur,tmp}/*'); 
 299 #Process each ipv4s keys 
 301         #Set proto as either tcp or udp 
 302         for my $proto (('tcp', 'udp')) { 
 303                 #Check if branch is empty 
 304                 if (!scalar keys %{$ip4s{$_}{$proto}}) { 
 306                         delete $ip4s{$_}{$proto}; 
 311 #Process each ipv6s keys 
 313         #Set proto as either tcp or udp 
 314         for my $proto (('tcp', 'udp')) { 
 315                 #Check if branch is empty 
 316                 if (!scalar keys %{$ip6s{$_}{$proto}}) { 
 318                         delete $ip6s{$_}{$proto}; 
 323 #Open blrule4s file for reading 
 324 open (my $fh, '<', '/etc/shorewall/blrules') or die "Can't open < /etc/shorewall/blrules: $!"; 
 326 #Populate with comments 
 327 @blrule4s = map { chomp($_); if (/^#/) { $_; } else { (); } } <$fh>; 
 329 #Prepend each specific ip from whitelist 
 330 map { push @blrule4s, "WHITELIST\tnet:$1\tall" if (/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/32$/); } @{$iplist{ipv4
}}; 
 332 #Prepend each specific ip from blacklist 
 333 #TODO: check that blacklist range is not in a whitelisted one !!! 
 334 map { push @blrule4s, "DROP\tnet:$1\tall" if (/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d
{1,2})$/); } @{$ipblist{ipv4
}}; 
 337 close $fh or die "Can't close fh: $!"; 
 341         #Open bt_blocklists.ipv4 file for reading 
 342         open ($fh, '<', '/usr/local/share/blacklist/shorewall.ipv4') or die "Can't open < /usr/local/share/blacklist/shorewall.ipv4: $!"; 
 344         #Prepend bt_blocklists.ipv4 drop 
 345         map { chomp $_; push @blrule4s, "DROP\t\tnet:$_\tfw"; } <$fh>; 
 347         #Close bt_blocklists.ipv4 file 
 348         close $fh or die "Can't close fh: $!"; 
 354         for my $proto (sort keys %{$ip4s{$_}}) { 
 356                 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}}); 
 360 #Open blrule4s file for writing 
 361 open ($fh, '>', '/etc/shorewall/blrules') or die "Can't open > /etc/shorewall/blrules: $!"; 
 363 #Inject content of blacklist 
 364 map { print $fh $_."\n"; } @blrule4s; 
 367 close $fh or die "Can't close fh: $!"; 
 369 #Print ipv6 to update hash 
 370 #XXX; right now it don't seems scanned at all... 
 371 for (sort keys %ip6s) { 
 373         for my $proto (keys %{$ip6s{$_}}) { 
 374                 #Print the ipv6 scanner 
 375                 print $_."\t$proto\t".join(",", keys %{$ip6s{$_}{$proto}})."\n"; 
 381 #Restart shorewall service 
 382 capturex
('systemctl', 'restart', 'shorewall.service');