[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