hosts_allow: added logging, POD, deploy notes

added LOGINFO logging for denials, and LOGDEBUG for other results
added SEE ALSO pod
improved readability
This commit is contained in:
Matt Simerson 2012-05-11 01:50:03 -04:00 committed by Robert
parent ae3fe2e4d5
commit c4b8a7a395
2 changed files with 54 additions and 25 deletions

View File

@ -1,4 +1,4 @@
# #
# Example configuration file for plugins # Example configuration file for plugins
# #
@ -6,6 +6,9 @@
# plugins/http_config for details. # plugins/http_config for details.
# http_config http://localhost/~smtpd/config/ http://www.example.com/smtp.pl?config= # http_config http://localhost/~smtpd/config/ http://www.example.com/smtp.pl?config=
# hosts_allow does not work with the tcpserver deployment model!
# perldoc plugins/hosts_allow for an alternative.
#
# The hosts_allow module must be loaded if you want the -m / --max-from-ip / # The hosts_allow module must be loaded if you want the -m / --max-from-ip /
# my $MAXCONNIP = 5; # max simultaneous connections from one IP # my $MAXCONNIP = 5; # max simultaneous connections from one IP
# settings... without this it will NOT refuse more than $MAXCONNIP connections # settings... without this it will NOT refuse more than $MAXCONNIP connections
@ -48,12 +51,12 @@ virus/klez_filter
# You can run the spamassassin plugin with options. See perldoc # You can run the spamassassin plugin with options. See perldoc
# plugins/spamassassin for details. # plugins/spamassassin for details.
# #
spamassassin spamassassin
# rejects mails with a SA score higher than 20 and munges the subject # rejects mails with a SA score higher than 20 and munges the subject
# of the score is higher than 10. # of the score is higher than 10.
# #
# spamassassin reject_threshold 20 munge_subject_threshold 10 # spamassassin reject_threshold 20 munge_subject_threshold 10

View File

@ -1,24 +1,29 @@
#!perl -w #!perl -w
=head1 NAME =head1 NAME
hosts_allow - decide if a host is allowed to send mail hosts_allow - decide if a host is allowed to connect
=head1 DESCRIPTION =head1 DESCRIPTION
The B<hosts_allow> module decides before the SMTP-Greeting if a host is The B<hosts_allow> module decides before the SMTP-Greeting if a host is
allowed to connect. It checks for too many (running) connections from one allowed to connect. It checks for too many (running) connections from one
host (see -m/--max-from-ip options in qpsmtpd-forkserver) and the config host (see -m/--max-from-ip options in qpsmtpd-forkserver) and the config
file I<hosts_allow>. file I<hosts_allow>.
The plugin takes no arguments.
The plugin takes no config/plugin arguments.
This plugin only works with the forkserver and prefork deployment models. It
does not work with the tcpserver deployment model. See SEE ALSO below.
=head1 CONFIG =head1 CONFIG
The config file contains lines with two or three items. The first is either The I<hosts_allow> config file contains lines with two or three items. The
an IP address or a network/mask pair. The second is a (valid) return code first is an IP address or a network/mask pair. The second is a (valid) return
from Qpsmtpd::Constants. The last is a comment which will be returned to the code from Qpsmtpd::Constants. The last is a comment which will be returned to
connecting client if the return code is DENY or DENYSOFT (and of course the connecting client if the return code is DENY or DENYSOFT (and of course
DENY_DISCONNECT and DENYSOFT_DISCONNECT). DENY_DISCONNECT and DENYSOFT_DISCONNECT).
Example: Example:
192.168.3.4 DECLINED 192.168.3.4 DECLINED
@ -26,8 +31,28 @@ Example:
This would exclude 192.168.3.4 from the DENY of 192.168.3.0/24. This would exclude 192.168.3.4 from the DENY of 192.168.3.0/24.
=head1 SEE ALSO
To get similar functionality for the tcpserver deployment model, use
tcpserver's -x feature. Create a tcp.smtp file with entries like this:
70.65.227.235:deny
183.7.90.207:deny
:allow
compile the tcp.smtp file like this:
/usr/local/bin/tcprules tcp.smtp.cdb tcp.smtp.tmp < tcp.smtp
and add the file to the chain of arguments to tcpserver in your run file.
See also: http://cr.yp.to/ucspi-tcp.html
=cut =cut
use strict;
use warnings;
use Qpsmtpd::Constants; use Qpsmtpd::Constants;
use Socket; use Socket;
@ -39,41 +64,42 @@ sub hook_pre_connection {
# local_ip => inet_ntoa($laddr), # local_ip => inet_ntoa($laddr),
# local_port => $lport, # local_port => $lport,
# max_conn_ip => $MAXCONNIP, # max_conn_ip => $MAXCONNIP,
# child_addrs => [values %childstatus], # child_addrs => [values %childstatus],
my $remote = $args{remote_ip}; my $remote = $args{remote_ip};
my $max = $args{max_conn_ip};
if ($args{max_conn_ip}) { if ( $max ) {
my $num_conn = 1; # seed with current value my $num_conn = 1; # seed with current value
my $raddr = inet_aton($remote); my $raddr = inet_aton($remote);
foreach my $rip (@{$args{child_addrs}}) { foreach my $rip (@{$args{child_addrs}}) {
++$num_conn if (defined $rip && $rip eq $raddr); ++$num_conn if (defined $rip && $rip eq $raddr);
} }
if ($num_conn > $args{max_conn_ip}) { if ($num_conn > $max ) {
$self->log(LOGINFO, my $err_mess = "too many connections from $remote";
"Too many connections from $remote: " $self->log(LOGINFO, "fail: $err_mess ($num_conn > $max)");
. "$num_conn > " . $args{max_conn_ip} return (DENYSOFT, "Sorry, $err_mess, try again later");
. "Denying connection.");
return (DENYSOFT, "Sorry, too many connections from $remote, "
."try again later");
} }
} }
foreach ($self->qp->config("hosts_allow")) { foreach ($self->qp->config("hosts_allow")) {
s/^\s*//; s/^\s*//;
my ($ipmask, $const, $message) = split /\s+/, $_, 3; my ($ipmask, $const, $message) = split /\s+/, $_, 3;
next unless defined $const; next unless defined $const;
my ($net,$mask) = split '/', $ipmask, 2; my ($net,$mask) = split '/', $ipmask, 2;
if (!defined $mask) { $mask = 32 if !defined $mask;
$mask = 32;
}
$mask = pack "B32", "1"x($mask)."0"x(32-$mask); $mask = pack "B32", "1"x($mask)."0"x(32-$mask);
if (join(".", unpack("C4", inet_aton($remote) & $mask)) eq $net) { if (join(".", unpack("C4", inet_aton($remote) & $mask)) eq $net) {
$const = Qpsmtpd::Constants::return_code($const) || DECLINED; $const = Qpsmtpd::Constants::return_code($const) || DECLINED;
if ( $const =~ /deny/i ) {
$self->log( LOGINFO, "fail: $message" );
};
$self->log( LOGDEBUG, "pass: $const, $message" );
return($const, $message); return($const, $message);
} }
} }
$self->log( LOGDEBUG, "pass" );
return (DECLINED); return (DECLINED);
} }