qpsmtpd/plugins/hosts_allow

80 lines
2.4 KiB
Plaintext
Raw Normal View History

#!perl -Tw
=head1 NAME
hosts_allow - decide if a host is allowed to send mail
=head1 DESCRIPTION
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
host (see -m/--max-from-ip options in qpsmtpd-forkserver) and the config
file I<hosts_allow>.
The plugin takes no arguments.
=head1 CONFIG
The config file contains lines with two or three items. The first is either
an IP address or a network/mask pair. The second is a (valid) return code
from Qpsmtpd::Constants. The last is a comment which will be returned to the
connecting client if the return code is DENY or DENYSOFT (and of course
DENY_DISCONNECT and DENYSOFT_DISCONNECT).
Example:
192.168.3.4 DECLINED
192.168.3.0/24 DENY Sorry, known spam only source
This would exclude 192.168.3.4 from the DENY of 192.168.3.0/24.
=cut
use Qpsmtpd::Constants;
use Socket;
sub hook_pre_connection {
my ($self,$transaction,%args) = @_;
# remote_ip => inet_ntoa($iaddr),
# remote_port => $port,
# local_ip => inet_ntoa($laddr),
# local_port => $lport,
# max_conn_ip => $MAXCONNIP,
# child_addrs => [values %childstatus],
my $remote = $args{remote_ip};
if ($args{max_conn_ip}) {
my $num_conn = 1; # seed with current value
my $raddr = inet_aton($remote);
foreach my $rip (@{$args{child_addrs}}) {
++$num_conn if (defined $rip && $rip eq $raddr);
}
if ($num_conn > $args{max_conn_ip}) {
$self->log(LOGINFO,
"Too many connections from $remote: "
. "$num_conn > " . $args{max_conn_ip}
. "Denying connection.");
return (DENYSOFT, "Sorry, too many connections from $remote, "
."try again later");
}
}
foreach ($self->qp->config("hosts_allow")) {
s/^\s*//;
my ($ipmask, $const, $message) = split /\s+/, $_, 3;
next unless defined $const;
my ($net,$mask) = split '/', $ipmask, 2;
if (!defined $mask) {
$mask = 32;
}
$mask = pack "B32", "1"x($mask)."0"x(32-$mask);
if (join(".", unpack("C4", inet_aton($remote) & $mask)) eq $net) {
$const = Qpsmtpd::Constants::return_code($const) || DECLINED;
return($const, $message);
}
}
return (DECLINED);
}