#!/usr/bin/perl # Export DNSBL data ## # $Id$ # Copyright 2009-2012,2014,2018 Kris Deugau # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ## use strict; use warnings; use DBI; # push "the directory the script is in" into @INC use FindBin; use lib "$FindBin::RealBin/"; use DNSBL 2.2; my $dnsbl = new DNSBL; # default DB info - all other settings should be loaded from the DB. my $dbhost = "localhost"; my $dbname = "dnsbl"; my $dbuser = "dnsbl"; my $dbpass = "spambgone"; die "Need config argument\n" if !$ARGV[0]; my $cfgname = shift @ARGV; # Load a config ref containing DB host, name, user, and pass info based on # from the server name + full script web path. This allows us to host # multiple instances without having to duplicate the code. # This file is a Perl fragment to be processed inline. if (-e "/etc/dnsbl/$cfgname.conf") { my $cfg = `cat /etc/dnsbl/$cfgname.conf`; ($cfg) = ($cfg =~ /^(.+)$/s); # avoid warnings, failures, and general nastiness with taint mode eval $cfg; } my $dbh = $dnsbl->connect($dbhost, $dbname, $dbuser, $dbpass); my %config; my $sth = $dbh->prepare("SELECT key,value FROM misc"); $sth->execute; while (my ($key,$value) = $sth->fetchrow_array) { $config{$key} = $value; } my %iplist; my $ipref = \%iplist; my $mode = $ARGV[0] || 'tiny'; $dnsbl->initexport; #$dnsbl->export($ipref,$mode,1,'50.22.0.0/15'); $dnsbl->export($ipref,$mode); ##fixme - mode should pick actual output, not just export mode if ($mode eq 'cidr') { # SOA, NS records. Maybe dnscache needs them? print "\$SOA 900 ".($config{blzone} ? $config{blzone} : 'company.dnsbl')." ". ($config{bladmin} ? $config{bladmin} : 'systems.company.com')." 0 1200 600 600 900\n". "\$NS 3600 127.0.0.1\n". "\$TTL ".($config{ttl} ? $config{ttl} : '900')."\n"; # more or less raw CIDR block-and-IP info. rbldnsd format for convenience. foreach (sort ipcmp keys %iplist) { my $entry; if ($iplist{$_} == -1) { print "!$_\n"; next; } if ($iplist{$_} >= 256) { if ($iplist{$_} >= 65536) { $entry .= int($iplist{$_}/65536)."."; $iplist{$_} = $iplist{$_} % 65536; } else { $entry .= "0."; } $entry .= int($iplist{$_}/256)."."; $iplist{$_} = $iplist{$_} % 256; } else { $entry .= "0.0."; } $entry .= $iplist{$_}; my $out = "$_:127.$entry:". ($iplist{$_} & 2 ? ($config{iplisted} ? $config{iplisted} : '$ relayed a reported spam') : ($config{blocklisted} ? $config{blocklisted} : 'Netblock listed on one or more criteria') )."\n"; $out =~ s/:ENTITY:/$_/; print $out; } } else { # default "mode"; tinyDNS data format foreach (sort ipcmp keys %iplist) { my $entry; if ($iplist{$_} > 256) { if ($iplist{$_} > 65536) { $entry .= int($iplist{$_}/65536)."."; $iplist{$_} = $iplist{$_} % 65536; } else { $entry .= "0."; } $entry .= int($iplist{$_}/256)."."; $iplist{$_} = $iplist{$_} % 256; } else { $entry .= "0.0."; } $entry .= $iplist{$_}; my ($o1,$o2,$o3,$o4) = (/^(\d+)\.([\d*]+)(?:\.([\d*]+)(?:\.([\d*]+))?)?$/); print "+".(defined($o4) ? "$o4." : '').(defined($o3) ? "$o3." : '').(defined($o2) ? "$o2." : ''). "$o1.".($config{blzone} ? $config{blzone} : 'spamhosts.company.dnsbl').":127.0.0.$entry:". ($config{ttl} ? $config{ttl} : '900').":::\n"; } } exit 0; # IP address comparison sub sub ipcmp { my ($a1,$a2,$a3,$a4,$a5) = ($a =~ /^(\d+)\.([\d*]+)(?:\.([\d*]+)(?:\.([\d*]+))?)?(?:\/(\d+))?$/); my ($b1,$b2,$b3,$b4,$b5) = ($b =~ /^(\d+)\.([\d*]+)(?:\.([\d*]+)(?:\.([\d*]+))?)?(?:\/(\d+))?$/); # le sigh. knew it wasn't going to be simple... $b2 = -1 if $b2 && $b2 eq '*'; $b3 = -1 if $b3 && $b3 eq '*'; $b4 = -1 if $b4 && $b4 eq '*'; $b5 = 128 if !defined($b5); $a2 = -1 if $a2 && $a2 eq '*'; $a3 = -1 if $a3 && $a3 eq '*'; $a4 = -1 if $a4 && $a4 eq '*'; $a5 = 128 if !defined($a5); return 1 if $a1 > $b1; return -1 if $a1 < $b1; return 1 if $a2 > $b2; return -1 if $a2 < $b2; return 1 if $a3 > $b3; return -1 if $a3 < $b3; return 1 if $a4 > $b4; return -1 if $a4 < $b4; return 1 if $a5 > $b5; return -1 if $a5 < $b5; return 0; }