On May 3, 2006, at 5:43 AM, David F. Skoll wrote:

For what it's worth, this is my code to detect a likely-looking dynamic
IP address, based on the PTR record.


and, here's my filter_sender (where I do my similar checks) ...



sub filter_sender {
   my ($sender, $ip, $hostname, $helo) = @_;
my ($iaddr, $name, $aliases, $addrtype, $length, @addrs, $addr, $tmp);
   my $found = 0;

   if ($sender =~ /\.local$/) {
# no .local senders, even from my own IP addrs or authenticated senders
      # CGP does weird things with .local addresses

      md_syslog('warning', "Rejecting .local sender address $sender");
      return ('REJECT', "We do not accept .local sender addresses");
      }

   elsif (authenticated_user() || exempt_ip_addr($ip)) {
# exempt certain IP addrs or authenticated senders from further checks

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

   elsif ($helo =~ /(\@|\.)rudd\.cc\>?$/i) {
      # if it got here, then it's not one of my ip addrs, so reject
      # it if it claims a helo/ehlo of *.rudd.cc

md_syslog('warning', "Rejecting forged helo address $helo $ip $hostname");
      return ('REJECT', "You're not actually in the rudd.cc domain");
      }

   elsif ($sender =~ /(\@|\.)rudd\.cc\>?$/i) {
# if they really are from my domain, they'd be caught by my exemptions
      # or use my webmail system if they can't use SMTP-AUTH that moment

md_syslog ('warning', "Rejecting forged local sender $sender $ip");
      return ('REJECT', "You're not actually from the rudd.cc domain");
      }

   elsif ( ($sender =~ /^\<?noreply\@/i) &&
($sender !~ /(\@|\.)freshmeat\.net\>?$/i) && # freshmeat uses it ($sender !~ /(\@|\.)adc\.apple\.com\>?$/i) && # apple adc uses it ($sender !~ /(\@|\.)google\.com\>?$/i) ) { # google uses it
      # noreply@ seems to mostly be used by spammers these days
      # with just a couple known exceptions

      md_syslog ('warning', "Rejecting noreply sender $sender $ip");
      return ('REJECT', "We don't accept noreply senders");
      }

   elsif ($hostname ne "[$ip]") {
      # assume that $hostname was created from a rDNS check of $ip
      # so, we don't need to do that again with the gethostbyaddr
      # what we're doing is checking that $hostname isn't forged
      # by being sure that the @addrs it returns has $ip in it
# (and, again, my own blocks or authentic senders are exempted above)

($name, $aliases, $addrtype, $length, @addrs) = gethostbyname($hostname);

      unless (defined ($name)) {
         md_syslog('warning',
"Tempfail can't verify reverse DNS for $hostname $ip");
         return ('TEMPFAIL',
"Can't verify that your reverse DNS matches your forward DNS" . " - either your PTR record returns something that doesn't" . " exist, or DNS for it is timing out - try again later");
         }

      foreach $addr (@addrs) {
         $tmp = join (".",  unpack('C4', $addr));
         if ($tmp eq $ip) {
            $found = 1;
            }
         }

      if (! ($found) ) { # we got an answer, it doesn't include $ip
# ! $found should mean that the rDNS is forged to some other hostname

md_syslog('warning', "Forged rDNS - $hostname doesn't return $ip");
         md_syslog('warning', "rDNS mismatch for $ip $name $hostname");
         return ('REJECT',
                 "Forged DNS: reverse DNS doesn't match forward DNS " .
                     "- fix your PTR and A records.");
         }
      else {
# verified their reverse DNS matches, now lets do some checking.

         # IP address components that might be in the hostname:
         my ($a, $b, $c, $d) = split(/\./, $ip);
         # decimal encoded IP address that might be in the hostname:
my $e = ($a * 256 * 256 * 256) + ($b * 256 * 256) + ($c * 256) + $d;
         # hexadecimal encoded versions of IP address components:
         my $f = lc(sprintf("%x", $a));
         my $g = lc(sprintf("%x", $b));
         my $h = lc(sprintf("%x", $c));
         my $i = lc(sprintf("%x", $d));
my $j = lc(sprintf("%x", $e)); # should be redundant to "$f$g$h$i"

         $hostname = lc($hostname); # instead of lots of //i matches

         if ($hostname =~ /\.kr$/) {
            # korean hostnames only seem to send me spam
            md_syslog('warning', "Blocking .kr relay $hostname");
return ('REJECT', "We don't accept email from .kr hostnames");
            }
         elsif ($hostname =~ /\.mx$/) {
            # mexican hostnames only seem to send me spam
            md_syslog('warning', "Blocking .mx relay $hostname");
return ('REJECT', "We don't accept email from .mx hostnames");
            }
         elsif ( ($hostname =~ /(catv|cable|dsl|ddns|dhcp)/   ) ||
                 ($hostname =~ /(dial-?up|dynamic|$e|$j)/     ) ||
                 ($hostname =~ /($a.?0*$b|$b.?0*$c|$c.?0*$d)/ ) ||
                 ($hostname =~ /($d.?0*$c|$c.?0*$b|$b.?0*$a)/ ) ||
                 ($hostname =~ /($f.?0*$g|$g.?0*$h|$h.?0*$i)/ ) ||
                 ($hostname =~ /($i.?0*$h|$h.?0*$g|$g.?0*$f)/ ) ) {
# The IP has a few key words in its hostname, or it has components # of its IP address in its hostname, then its probably an ISP # assigned dynamic or dial-up host, and should either get specific # DNS to avoid looking like a client, or use its ISP's mail server md_syslog('warning', "Blocking end-client host $hostname $ip");
            return ('REJECT',
"ISP clients IPs should use their ISPs mail server");
            }
         else { # otherwise, accept it
            return ('CONTINUE', "ok");
            }
         }
      }

   elsif ($hostname eq "[$ip]") {
# everyone else better have valid rDNS, or use an ISP whose customer
      # relay that has valid rDNS.  Tempfail in case it was a  transient
      # DNS error.

      md_syslog('warning', "Tempfail for no reverse DNS $ip");
      return ('TEMPFAIL',
              "You don't have valid reverse DNS - get a PTR record");
      }

   # we shouldn't get here ... the last two if conditions should cover
   # _every_ message that wasn't caught by the first 5, so, tempfail
   # if we get here
   return ('TEMPFAIL', "This shouldn't happen.");
   }



_______________________________________________
NOTE: If there is a disclaimer or other legal boilerplate in the above
message, it is NULL AND VOID.  You may ignore it.

Visit http://www.mimedefang.org and http://www.roaringpenguin.com
MIMEDefang mailing list MIMEDefang@lists.roaringpenguin.com
http://lists.roaringpenguin.com/mailman/listinfo/mimedefang

Reply via email to