[Mimedefang] filter snippet to reject sender addresses with bad MX entries?

Albert Croft acroft at cyber-wizard.com
Sat Apr 2 09:05:54 EST 2005


Recently, I set up a sendmail/MIME-Defang/SpamAssassin/Razor 
installation to act as a spam gateway/filter for several domains. From 
time to time I have noticed emails using sender addresses whose MX point 
to addresses in the localhost (127.0.0.0/8 ) or localnetwork ( 0.0.0.0/8 
) ranges, RFC-1918 private network space, or other address space that 
should not be appearing. I would like to reject these as early as 
possible, and have been looking for code to do so since my earlier 
posting to the list (18-March-2005).

I had hoped there would be a good example of code to do this already, 
and if so, I would appreciate it if someone could point me in that 
direction. In the mean time, I hacked together the following variation 
of the code segment from the CheckforMX entry on the Wiki, and would 
appreciate any feedback regarding the code segment (as I have NOT had 
the opportunity to test it completely, or to put it into operation yet).

use Net::DNS;
use NetAddr::IP;

# GetHostAddress and GetDomainMXAddresses routines
#   taken from http://www.mimedefang.org/kwiki/index.cgi?CheckForMX

sub GetHostAddresses {
    my ($hostname) = @_;
    my @addresses;
    if ( $hostname =~ m/^\s*(\d{1,3}\.){3}\d{1,3}\s*$/ ) {
        push( @addresses, $hostname );    # Host was an IP address, not 
a hostname
    }
    else {
        my $resolver = Net::DNS::Resolver->new;
        my $received = $resolver->search($hostname);
        foreach my $rr ( $received->answer ) {
            next unless $rr->type eq "A";
            push( @addresses, $rr->address );
        }
    }
    return @addresses;
}

# GetDomainMXAddresses(resolver,domain)
#   returns array of IP addresses for domain's MX list
#   if no MX records, returns array of IP addresses for this hostname

sub GetDomainMXAddresses {
    my ($domain) = @_;
    my $resolver = Net::DNS::Resolver->new;
    my @mxlist = mx( $resolver, $domain );
    my @mxaddresses;
    if (@mxlist) {
        push( @mxaddresses, map { GetHostAddresses( $_->exchange ); } 
@mxlist );
    }
    else {    # check for an A record for the domain...
        push( @mxaddresses, GetHostAddresses( $domain ) );
    }
    return @mxaddresses;
}

sub filter_sender {
    my ( $sender, $ipaddr, $hostname, $helo ) = @_;
    my ( undef, $sender_domain ) = split( /\@/, $sender );

    # Block information taken from RFC 3330. Remove any in use locally.
    my %specialized_blocks = (
        "0.0.0.0/8"      => { comment => qq{local network 
block},           rfc => 1700 },
        "10.0.0.0/8"     => { comment => qq{class A private network 
block}, rfc => 1918 },
        "127.0.0.0/8"    => { comment => qq{loopback address 
block},        rfc => 1700 },
        "169.254.0.0/16" => { comment => qq{"LINK LOCAL" 
block},            rfc => 3330 },
        "172.16.0.0/12"  => { comment => qq{class B private network 
block}, rfc => 1918 },
        "192.0.2.0/24"   => { comment => qq{"TEST-NET" 
block},              rfc => 3330 },
        "192.168.0.0/16" => { comment => qq{class C private network 
block}, rfc => 1918 },
        "224.0.0.0/4"    => { comment => qq{IPv4 multicast 
range},          rfc => 3171 },
    );

    foreach my $address ( GetDomainMXAddresses($sender_domain) ) {
        my $ip = new NetAddr::IP $address;
        foreach my $range ( keys %specialized_blocks ) {
            if ( $ip->within( new NetAddr::IP($range) ) ) {
                return ( "REJECT",
                        "Addresses from domains with MX entries whose 
addresses fall within a "
                      . $specialized_blocks{$range}{comment}
                      . " not accepted (see also RFC "
                      . $specialized_blocks{$range}{rfc}
                      . ")." );
            }
        }
    }

    #
    # Other sender checks here.
    #

    return ( "CONTINUE", "ok" );
}

The modification to the GetHostAddress routine, to check for an IP 
address in place of a hostname from MX records, was in response to two 
recently-seen domains in (probably forged) email addresses 
('jsctech.com' and 'romymichele.com'). These two domains appeared as 
follows when examined with dig(1):

$ dig +nostats +nocomments any jsctech.com

; <<>> DiG 9.2.3 <<>> +nostats +nocomments any jsctech.com
;; global options:  printcmd
;jsctech.com.                   IN      ANY
jsctech.com.            83749   IN      NS      ns1.nameresolve.com.
jsctech.com.            83749   IN      NS      ns2.nameresolve.com.
jsctech.com.            83749   IN      NS      ns3.nameresolve.com.
jsctech.com.            83749   IN      NS      ns4.nameresolve.com.
jsctech.com.            83749   IN      MX      0 127.0.1.50.
jsctech.com.            86238   IN      TXT     "v=spf1 mx -all"
jsctech.com.            1644    IN      A       66.150.161.133
jsctech.com.            1644    IN      A       66.150.161.141
jsctech.com.            1644    IN      A       66.150.161.136
jsctech.com.            1644    IN      A       66.150.161.134
jsctech.com.            1644    IN      A       69.25.27.173
jsctech.com.            1644    IN      A       69.25.27.171
jsctech.com.            1644    IN      A       69.25.27.172
jsctech.com.            1644    IN      A       69.25.27.170
jsctech.com.            83749   IN      NS      ns1.nameresolve.com.
jsctech.com.            83749   IN      NS      ns2.nameresolve.com.
jsctech.com.            83749   IN      NS      ns3.nameresolve.com.
jsctech.com.            83749   IN      NS      ns4.nameresolve.com.
ns1.nameresolve.com.    58537   IN      A       64.94.117.196
ns2.nameresolve.com.    58537   IN      A       63.251.83.77
ns3.nameresolve.com.    30591   IN      A       66.150.161.132
ns4.nameresolve.com.    58537   IN      A       216.52.121.240

$ dig +nostats +nocomments any romymichele.com

; <<>> DiG 9.2.3 <<>> +nostats +nocomments any romymichele.com
;; global options:  printcmd
;romymichele.com.               IN      ANY
romymichele.com.        15540   IN      NS      ns1.e-access.net.
romymichele.com.        15540   IN      MX      0 mail.romymichele.com.
romymichele.com.        15540   IN      NS      ns1.e-access.net.
ns1.e-access.net.       151939  IN      A       63.229.32.2
mail.romymichele.com.   15540   IN      A       0.0.0.0



Your time in considering this posting, and any 
advice/suggestions/feedback provided, are greatly appreciated in advance.

Sincerely,
Albert C.




More information about the MIMEDefang mailing list