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.

_______________________________________________
Visit http://www.mimedefang.org and http://www.canit.ca
MIMEDefang mailing list
[email protected]
http://lists.roaringpenguin.com/mailman/listinfo/mimedefang

Reply via email to