[Mimedefang] better subnet matching in filter_relay
James Ralston
qralston+ml.mimedefang at andrew.cmu.edu
Thu Apr 3 20:44:00 EST 2003
I noticed that a lot of the discussion about using filter_relay to
bypassing filtering for local subnets involved pattern matching on
$hostip.
That works fine when one's network exclusions fall on traditional
class boundaries (e.g., 10.*, 192.168.*), but it doesn't work well for
CIDR blocks (e.g., 172.16.0.0 through 172.31.255.255). Our site was
in the latter situation.
Attached is a way to perform the matching by specifying subnet/netmask
pairs, and then using inet_aton and bitwise operations. It's fast,
it's byte-order independent, and (IMHO) it's a better solution than
performing pattern matching on $hostip.
Regards,
--
James Ralston, Information Technology
Software Engineering Institute
Carnegie Mellon University, Pittsburgh, PA, USA
-------------- next part --------------
#***********************************************************************
# %PROCEDURE: filter_relay
# %ARGUMENTS:
# hostip -- the IP address of the relay host (e.g. "127.0.0.1")
# hostname -- the hostname if known (e.g. "localhost"), else a copy of
# $hostip
# helo -- the argument that was given to the SMTP HELO/EHLO command
# %RETURNS:
# a two-element list: ($code, $msg)
# (see the man page for possible return codes/messages)
# %DESCRIPTION:
# If the -r flag is passed to mimedefang, then the filter_relay function is
# called (early in the SMTP dialog, just after the client issues (or *should*
# issue) the HELO/EHLO command). It can be used to reject messages
# immediately, without having to wait for the client to transmit the entire
# message.
#***********************************************************************
use Socket;
sub filter_relay ($$$) {
my ($hostip, $hostname, $helo) = @_;
my $addr = '';
my $network_string = '';
my $mask_string = '';
# List networks that should be exempt from all filtering by putting their
# network/mask pairs into the exempt_subnets associative array. (Follow
# the example for the loopback.)
my %exempt_subnets = (
'127.0.0.0', '255.0.0.0', # loopback
);
# If the address of the connecting client falls within one of the subnets
# defined by %exempt_subnets, then bypass all further filtering.
$addr = inet_aton $hostip;
while (($network_string, $mask_string) = each %exempt_subnets) {
my $network = inet_aton $network_string;
my $mask = inet_aton $mask_string;
if (($addr & $mask) eq $network) {
return ('ACCEPT_AND_NO_MORE_FILTERING', 'ok');
}
}
# The client isn't in an exempt subnet; filtering should continue.
return ('CONTINUE', 'ok');
}
More information about the MIMEDefang
mailing list