Re: [Mimedefang] sendmail and filter_helo interaction

2006-11-10 Thread Jonas Eckerman

Dirk the Daring wrote:
I've theorized that if the connecting host issues a RSET followed by 
another (valid) HELO, the connection can proceed and be successful. This 
might be why the connection is not immediately dropped. Also, I use 
FEATURE(`delay_checks'), which may have something to do with it.



Ah, yes. Of course. I knew there was something like that about HELO. Time to 
refresh memory from RFCs... Checking... Reading... Ok.



From rfc821, 4.1.1: The first command in a session must be the HELO command. 
The HELO command may be used later in a session as well. If the HELO command 
argument is not acceptable a 501 failure reply must be returned and the 
receiver-SMTP must stay in the same state.



From rfc2821, 4.1.1: If the EHLO command is not acceptable to the SMTP server, 
501, 500, or 502 failure replies MUST be returned as appropriate. The SMTP 
server MUST stay in the same state after transmitting these replies that it was 
in before the EHLO was received.



The SMTP server cannot close the connection after a rejected HELO/EHLO since 
that is simply not allowed by the SMTP RFCs, but if the client sends any 
command except HELO/EHLO without first having sent an *accepted* HELO/EHLO it 
can be rejected because it's sending commands out of order.

So, of course sendmail waits for *something* after a rejected HELO/EHLO.
And as many spam apps seem to have no idea what a rejected HELO/EHLO means they 
go on to send a MAIL command and gets rejected because the only command the 
server will accept is another HELO/EHLO.


Regards
/Jonas
--
Jonas Eckerman, FSDB  Fruktträdet
http://whatever.frukt.org/
http://www.fsdb.org/
http://www.frukt.org/


___
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


[Mimedefang] sendmail and filter_helo interaction

2006-11-09 Thread Dirk the Daring
   Jim McCullars and I have been discussing filter_helo offlist, and 
David's observation (supported by Jim's experimentation) that if 
filter_helo returns a REJECT, the connection is not immediately rejected, 
but rather is rejected after MAIL FROM.


   It happens that I have been using a heavily-logged filter, and examined 
some test connections that Jim made to my mailserver. Some interesting 
results came out of that. I'm using sendmail v8.13.8 and MIMEDefang v2.57 
on Solaris 9 with Perl v5.8.6.


   It is true that even if filter_helo returns REJECT, the connection is 
not immediately dropped. The sending host can still issue another command, 
such as MAIL FROM.


   However, it is also true that if the sending host does issue another 
command, like MAIL FROM, that there is no corresponding MILTER call. 
MIMEDefang never sees a call to filter_sender if filter_helo returns a 
REJECT.


   So it *appears* like the connection is maintained, but it also seems 
that the SMTP conversation *effectively ends* if filter_helo returns 
REJECT. The connecting host can issue another command, but it will be 
ignored.


   I've theorized that if the connecting host issues a RSET followed by 
another (valid) HELO, the connection can proceed and be successful. This 
might be why the connection is not immediately dropped. Also, I use 
FEATURE(`delay_checks'), which may have something to do with it.


   Something else also came out of the experiments. If a connecting host 
violates GREETPAUSE (sends before presentation of the banner), its HELO is 
still passed via MILTER call to MIMEDefang.


   However, if RATECONTROL is tripped, there is no MILTER call. Presumbly, 
this is true of CONNCONTROL.


   Finally, I got asked about my filter_helo code. My current filter has 
a *lot* of logging statements, because I've been experimenting and need 
to meter its function. I'm also not a Perl hacker, so I doubt my code 
is the most-efficient way to write this. Here it is...feel free to 
use/adapt the code as may suit your needs, or ignore my code and write 
your own:


# Some global variables used by the filter* functions
###
# Declare a hash of
#   - Key: IP addresses we consider internal
#   - Value: Flag as to if host is exempt from AV scans (0=No, 1=Yes)
###
%OurHosts=( 127.0.0.1, 0,
192.168.2.2, 0,
10.2.3.4, 0 );

###
# Declare a hash of
#   - Key: Domain Names we host
#   - Value: A flag as to if the Domain should be
#   receiving E-Mail (0=No, 1=Yes)
###
%OurDomains=(   mydomain.tld, 1,
otherdomain.tld, 1,
notadomain.tld, 0 );

[..other code..]

#***
# %PROCEDURE: filter_helo
# %ARGUMENTS:
#  IP address of remote host; hostname of remote host; HELO string
#  presented by remote host
# %RETURNS:
#  2-5 element array (see documentation)
# %DESCRIPTION:
#  Called after SMTP connection has been established and sending host has
#  given a HELO statement, but not MAIL FROM: or RCPT TO:
#***
sub filter_helo ()
{
# Read the parameters passed to the function
my($hostip, $hostname, $helo) = @_;

# Local string for Domain name processing
my($domainstring);
# Local variable for string indexing
my($subindex)=0;

# Search the list of our hosts using the $hostip argument
if ( exists($OurHosts{$hostip}) )
{
# Recognize our internal host
md_syslog('info', Internal Host $hostip HELO $helo);
# Don't look at it further
return('CONTINUE', 'ok');
}
else
{
# Foreign host
md_syslog('info', Foreign Host $hostip HELO $helo);
}

# Check if the HELO is an IP address
if ($helo =~ /^(\[?)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\]?)$/ )
{
# HELO looks like an IP - the comparison will split the string
#   into 3 variables; $1 will have [ or be undefined, $2 
will
#   have the IP address without any brackets, $3 will have
#   ] or be undefined ($1 and $3 are undefined if HELO 
lacked
#   square brackets)
md_syslog('info', IP HELO $helo);

# Check #0
# The IP address portion should *not* be identical to the
#   original HELO string - if it is, the original HELO 
lacked
#   brackets and therefore is invalid (this is safer than
#   trying to evaluate $1 and $3 directly, as they may be
#   undefined, or have garbage from a 

Re: [Mimedefang] sendmail and filter_helo interaction

2006-11-09 Thread Richard Laager
On Thu, 2006-11-09 at 23:06 -0500, Dirk the Daring wrote:
   # Check #3
   # HELO should not contain localhost

How effective is this for you? Do you run into false positives?

   # Check #4
   # If the HELO is an FQDN, the index and rindex of . will not 
 be the same
   # This catches the spammer using domain.tld (which will slip
   #   by Check #2)

I check that the HELO must have a ., but I haven't gone any further
than that. Does this work well for you? Any false positives?

Richard



signature.asc
Description: This is a digitally signed message part
___
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


Re: [Mimedefang] sendmail and filter_helo interaction

2006-11-09 Thread John Rudd

Dirk the Daring wrote:



# Check #4
# If the HELO is an FQDN, the index and rindex of . will not 
be the same

# This catches the spammer using domain.tld (which will slip
#   by Check #2)
if ( index($helo, .) == rindex($helo, .) )
{
# Reject connection - invalid HELO
md_syslog('alert', Non-FQDN HELO $helo by Host $hostip);
return('REJECT', INVALID HELO/EHLO: $helo is 
not FQDN);

}





   As I wrote previously, my entire filter is heavily logged. My 
analysis of those logs indicates that only about 50% of foreign 
mailhosts connecting to my network get past HELO. Based on the 
I-think-reasonable assumption that no legitimate mail server would be 
tripped up by GREETPAUSE, RATECONTROL, CONNCONTROL or the tests I have 
in filter_helo, my conclusion is that those 50% are spammers, and I'm 
effectively stopping them by the end of HELO.





Given that I don't think check #4 is valid, I'm not sure I believe your 
claim.  For one, depending on the configuration I'm using, you might end 
up rejecting my email, because my mail server's hostname is the 
registered domain name (rudd.cc) ... and I'm not a spammer.


(I don't recall any prohibition on a host's name being just its 
registered domain, domain.tld)


I'm also curious why you're using a lot of index/rindex calls instead of 
regular expressions (I'm not enough of an expert to know if one is 
honestly faster than the other).  For the above one, why not:


$helo =~ /^[^\.]+\.[^\.]+$/

(from the start of the string, one or more non-dots, followed by 1 dot, 
followed by one or more non-dots, and then the end of the string; you 
can only match this expression if you have exactly 1 dot in the strong)


Or,

(($helo =~ /\./)  ($helo !~ /\..+\./)

(contains at least one dot, AND does not contain: a dot, at least any 
one other character, and then another dot, anywhere in the string; 
again, you can only match these two expressions if you have exactly one 
dot in the string)



$helo =~ /\./

also works for your index of . isn't -1 check.

___
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