[Mimedefang] Bogus HELO filtering

Chris Myers chris at by-design.net
Wed Jul 7 10:21:30 EDT 2004


----- Original Message -----
From: "Jeff Rife" <mimedefang at nabs.net>
To: <mimedefang at lists.roaringpenguin.com>
Sent: Tuesday, July 06, 2004 11:42 PM
Subject: [Mimedefang] Bogus HELO filtering


> I've seen a bit about this subject lately on the list, so I thought I
> throw in my solution and see what people think.
>
> In filter_sender:
>
> ###############################################################
> if ($ip =~ /^(127\.0\.0\.1|$TrustedNetworks)/)
>   {
>   return ('ACCEPT_AND_NO_MORE_FILTERING', "OK");
>   }

If you use stream_by_domain() or stream_by_recipient(), you really really
don't want to have the 127.0.0.1 in the IP regexp.  Incoming spam and
viruses (if you do virus-scanning) addressed to multiple users could bypass
your filter.  The stream_by_ functions actually resend the message as a new
mail message, so $ip will be 127.0.0.1.  See also the manpage for
mimedefang-filter(5) and search for RealRelayAddr.

> my $MyDomains = '\.(domain1\.tld|domain2\.tld|domain3\.tld)$';

You might want:

    my $MyDomains = '(^||\.)(domain1\.tld|domain2\.tld|domain3\.tld)$';

Since mail.domain1.tld would match the regexp, but domain1.tld would not.

If you want to do more complicated regexp work, you can extract the domain
from the HELO and see if that exists() in a hash:

<WARNING: untested off-the-cuff code, debugging may be required>

    my %MyDomains = (
        "domain1.tld" => undef,
        "domain2.tld" => undef,
        "domain3.tld" => undef,
    );

    my $rhs = $helo;
    $rhs =~ s/^(.*\.)?([a-z0-9-]\.[a-z0-9-])$/$2/i;
    if ( exists($rhs) ) {
        # bad HELO
    }

The only advantage to the above code vs. the regexp you use now is
readability.  You still have to enumerate all of your 20 domains.

> # Bogus IPs...I'm using my real ones in the actual filter
> my $MyPublicIPs = '^434\.300\.377\.38[789])$';

Since you own the entire Class C, just match on the first three octets:

     my $MyPublicIPs = '^434\.300\.377\.';

> if (($helo =~ /($MyDomains|$MyPublicIPs)/) and ($ip !~ /$MyPublicIPs/))
>   {
>   md_syslog('info', "md_info: bad HELO ($helo): $hostname [$ip]");
>
>   # don't really reject for now...just log it
> # return ('REJECT', "Bad HELO: $hostname [$ip] is not $helo");
>   }
> [...]
> Questions:
>
>  1. Does this get the job done?

Yup.

>  2. Is there a more efficient way that doesn't involve listing out all
>     legal machines?  I have 3 public class C IP blocks, so that would be
>     some real work.
> 2a. The real domain list is 20 or so, and growing.  Is there a better
>     way to deal with that list?

See above.

>  3. Am I breaking any rules by doing this?

There aren't any rules about parsing HELO commands, really.  The RFC's say
that the HELO command should meet certain requirements, but this is so
widely ignored that you don't dare try to enforce them.  There is one rule
that applies: your users complaining that real mail is being blocked... you
probably can't ignore that one.  Don't get too tight in your enforcement -- 
and the above code isn't "too tight" -- and you'll be fine.

Chris Myers
Networks By Design




More information about the MIMEDefang mailing list