On Wed, Feb 27, 2008 at 2:50 PM, Bob Proulx <[EMAIL PROTECTED]> wrote: > Marc Perkel wrote: > > It appears that Postfix only does DNS blacklists and not whitelists > > then. I was going to publish my whitelist and Postfix instructions but I > > guess I can't do that. > > That would be a better question for the postfix-users list. Probably > the way to do this is with the check_policy_service functionality. > The "permit" action should permit the request. I haven't created my > own policy daemon though and so this is an academically derived > answer. According to the manual "Policy delegation is now the > preferred method for adding policies to Postfix." > > Bob > >
Here's a hacked up version of postfix-policyd that uses the results from the hostkarma rbl. I'm sure it can be improved upon, but it works for me. # postfix-policyd-spf-perl # http://www.openspf.org/Software # version 2.004 # # (C) 2007 Scott Kitterman <[EMAIL PROTECTED]> # (C) 2007 Julian Mehnle <[EMAIL PROTECTED]> # (C) 2003-2004 Meng Weng Wong <[EMAIL PROTECTED]> # # 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 2 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # hacked up to query hostkama # by aaron <[EMAIL PROTECTED]> use strict; use IO::Handle; use IO::Socket; use Sys::Syslog qw(:DEFAULT setlogsock); use NetAddr::IP; use Net::DNS; use Fcntl; require "/etc/eps/config.pl"; # ---------------------------------------------------------- # configuration # ---------------------------------------------------------- # Adding more handlers is easy: my @HANDLERS = ( { name => 'hostkarma_lookup', code => \&hostkarma_lookup }, ); my $VERBOSE = 0; my $DEFAULT_RESPONSE = 'DUNNO'; # # Syslogging options for verbose mode and for fatal errors. # NOTE: comment out the $syslog_socktype line if syslogging does not # work on your system. # my $syslog_socktype = 'unix'; # inet, unix, stream, console my $syslog_facility = 'mail'; my $syslog_options = 'pid'; my $syslog_ident = 'postfix/hk_lookup'; use constant localhost_addresses => map( NetAddr::IP->new($_), qw( 127.0.0.0/8 ::ffff:127.0.0.0/104 ::1 ) ); # Does Postfix ever say "client_address=::ffff:<ipv4-address>"? use constant relay_addresses => map( NetAddr::IP->new($_), qw( 69.13.218.0/25 72.35.73.193/32 ) ); # add addresses to qw ( ) above separated by spaces using CIDR notation. my %results_cache; # by message instance my $dns = Net::DNS::Resolver->new; # ---------------------------------------------------------- # initialization # ---------------------------------------------------------- # # Log an error and abort. # sub fatal_exit { syslog(err => "fatal_exit: @_"); syslog(warning => "fatal_exit: @_"); syslog(info => "fatal_exit: @_"); die("fatal: @_"); } # # Unbuffer standard output. # STDOUT->autoflush(1); # # This process runs as a daemon, so it can't log to a terminal. Use # syslog so that people can actually see our messages. # setlogsock($syslog_socktype); openlog($syslog_ident, $syslog_options, $syslog_facility); # ---------------------------------------------------------- # main # ---------------------------------------------------------- # # Receive a bunch of attributes, evaluate the policy, send the result. # my %attr; while (<STDIN>) { chomp; if (/=/) { my ($key, $value) =split (/=/, $_, 2); $attr{$key} = $value; next; } elsif (length) { syslog(warning => sprintf("warning: ignoring garbage: %.100s", $_)); next; } if ($VERBOSE) { for (sort keys %attr) { syslog(debug => "Attribute: %s=%s", $_, $attr{$_}); } } my $message_instance = $attr{instance}; my $cache = defined($message_instance) ? $results_cache{$message_instance} ||= {} : {}; my $action = $DEFAULT_RESPONSE; foreach my $handler (@HANDLERS) { my $handler_name = $handler->{name}; my $handler_code = $handler->{code}; my $response = $handler_code->(attr => \%attr, cache => $cache); if ($VERBOSE) { syslog(debug => "handler %s: %s", $handler_name, $response); } # Pick whatever response is not 'DUNNO' if ($response and $response !~ /^DUNNO/i) { # syslog(info => "handler %s: is decisive.", $handler_name); $action = $response; last; } } syslog(info => "%s: Policy action=%s", $attr{queue_id}, $action); STDOUT->print("action=$action\n\n"); %attr = (); } # --------------------------------------- # hostkarma lookup # --------------------------------------- sub hostkarma_lookup { local %_ = @_; my %attr = %{ $_{attr} }; my $result = "DUNNO"; my $color = "pink"; if ( $attr{client_address} =~ m/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/ ) { my $laddr = "$4.$3.$2.$1.hostkarma.junkemailfilter.com"; my $query = $dns->query($laddr, "A"); if ($query) { foreach my $rr (grep { $_->type eq 'A' } $query->answer) { if ($rr->address eq '127.0.0.1') { # whitelisted $result = "OK"; $color = "white"; } elsif ($rr->address eq '127.0.0.2') { # blacklisted $result = "REJECT $attr{client_address} is blacklisted at hostkarma.junkemailfilter.com"; $color = "black"; } elsif ($rr->address eq '127.0.0.3') { # yellow listed $result = "PREPEND X-Hostkarma: Yellowlisted ($attr{client_address})"; $color = "yellow"; } elsif ($rr->address eq '127.0.0.4') { # brown listed $result = "PREPEND X-Hostkarma: Brownlisted ($attr{client_address})"; $color = "brown"; } # syslog(info => "%s: HostKarma says %s is %s listed", $attr{queue_id}, $attr{client_address}, $color ); } } } return($result); }