package Mail::SpamAssassin::Spamd::Apache2::AclIP; use strict; use Apache2::Connection (); use Apache2::Const -compile => qw(OK FORBIDDEN SERVER_ERROR); use Apache2::Module (); use Apache2::ServerRec (); use Apache::Test; use constant APACHE24 => have_min_apache_version('2.4.0'); use Mail::SpamAssassin::Logger; =head1 NAME Mail::SpamAssassin::Spamd::Apache2::AclIP - host-based spamd access control =head1 SYNOPSIS ##### in httpd.conf: PerlLoadModule Mail::SpamAssassin::Spamd::Apache2::Config SAallow from 127.0.0.1 192.168.0.0/24 =head1 DESCRIPTION Allows / denies access to spamd basing on client's network address. This is a simple version of C (which, unfortunately, is too HTTP-centric to use here). Should be before C in the handler chain. =head1 NOTE This module doesn't prevent Apache from accepting a connection; child (and therefore we) get control after client actually sends something. It's possible to open C<$toomany> connections to the parent server and DoS this way. =head1 BUGS See Ehttp://bugzilla.spamassassin.org/E =head1 SEE ALSO C =cut use APR::IpSubnet (); sub handler { my ($c) = @_; my $srv_cfg = Apache2::Module::get_config('Mail::SpamAssassin::Spamd::Apache2::Config', $c->base_server); # TODO: log it somewhere (or not?) -- means all denied return Apache2::Const::SERVER_ERROR unless $srv_cfg && exists $srv_cfg->{allowed_ips}; # use NetAddr::IP::Lite (); # my $ip = NetAddr::IP::Lite->new($c->remote_ip) # or return Apache2::Const::SERVER_ERROR; # log it, shouldn't happen #use Apache::Test have_min_apache_version to support MP under Apache 2.2 and 2.4 my $remote = APACHE24 ? $c->client_addr : $c->remote_addr; for my $allowed (@{ $srv_cfg->{allowed_networks} }) { # depends on allowed_ips format; TODO; if NetAddr::IP::Lite: # return Apache2::Const::OK if $allowed->contains($ip); return Apache2::Const::OK if $allowed->test($remote); } info(sprintf "access denied for '%s'", APACHE24 ? $c->client_ip : $c->remote_ip); return Apache2::Const::FORBIDDEN; } 1; # vim: ts=8 sw=2 et