Ban ips on bad mailfrom offenses as well as bad rcpts.

This commit is contained in:
Stuart Gathman
2007-07-02 03:06:10 +00:00
parent 46545cab94
commit cdfeb2d792
+24 -12
View File
@@ -1,6 +1,10 @@
#!/usr/bin/env python
# A simple milter that has grown quite a bit.
# $Log$
# Revision 1.109 2007/06/23 20:53:05 customdesigned
# Ban IPs based on too many invalid recipients in a connection. Requires
# configuring check_user. Tighten HELO best_guess policy.
#
# Revision 1.108 2007/04/19 16:02:43 customdesigned
# Do not process valid SRS recipients as delayed_failure.
#
@@ -594,7 +598,6 @@ class bmsMilter(Milter.Milter):
self.log("REJECT: BANNED IP")
self.setreply('550','5.7.1', 'Banned for dictionary attacks')
return Milter.REJECT
self.bad_rcpts = 0
self.hello_name = None
self.connecthost = hostname
if hostname == 'localhost' and not ipaddr.startswith('127.') \
@@ -602,6 +605,7 @@ class bmsMilter(Milter.Milter):
self.log("REJECT: PTR is",hostname)
self.setreply('550','5.7.1', '"%s" is not a reasonable PTR name'%hostname)
return Milter.REJECT
self.offenses = 0
return Milter.CONTINUE
def hello(self,hostname):
@@ -650,6 +654,17 @@ class bmsMilter(Milter.Milter):
for t in smart_alias[key]:
self.add_recipient('<%s>'%t)
def offense(self,inc=1):
self.offenses += inc
if self.offenses > 3:
try:
ip = addr2bin(self.connectip)
if ip not in banned_ips:
banned_ips.add(ip)
print >>open('banned_ips','a'),self.connectip
except: pass
return Milter.REJECT
# multiple messages can be received on a single connection
# envfrom (MAIL FROM in the SMTP protocol) seems to mark the start
# of each message.
@@ -769,7 +784,9 @@ class bmsMilter(Milter.Milter):
if not (self.internal_connection or self.trusted_relay) \
and self.connectip and spf:
rc = self.check_spf()
if rc != Milter.CONTINUE: return rc
if rc != Milter.CONTINUE:
if rc != Milter.TEMPFAIL: self.offense()
return rc
else:
rc = Milter.CONTINUE
# FIXME: parse Received-SPF from trusted_relay for SPF result
@@ -786,6 +803,7 @@ class bmsMilter(Milter.Milter):
elif cbv_cache.has_key(self.canon_from) and cbv_cache[self.canon_from] \
or domain in blacklist:
if not self.internal_connection:
self.offense()
if not dspam_userdir:
if domain in blacklist:
self.log('REJECT: BLACKLIST',self.canon_from)
@@ -866,6 +884,8 @@ class bmsMilter(Milter.Milter):
# check hello name via spf unless spf pass
h = spf.query(self.connectip,'',self.hello_name,receiver=receiver)
hres,hcode,htxt = h.check()
# FIXME: in a few cases, rejecting on HELO neutral causes problems
# for senders forced to use their braindead ISPs email service.
if hres in ('deny','fail','neutral','softfail'):
self.log('REJECT: hello SPF: %s 550 %s' % (hres,htxt))
self.setreply('550','5.7.1',htxt,
@@ -907,7 +927,7 @@ class bmsMilter(Milter.Milter):
if policy == 'CBV':
if self.mailfrom != '<>':
self.cbv_needed = (q,ores) # accept, but inform sender via DSN
self.bad_rcpts = 3 # ban ip if any bad recipient
self.offenses = 3 # ban ip if any bad recipient
elif policy != 'OK':
self.log('REJECT: no PTR, HELO or SPF')
self.setreply('550','5.7.1',
@@ -1059,15 +1079,7 @@ class bmsMilter(Milter.Milter):
if gossip and self.umis:
gossip_node.feedback(self.umis,1)
self.umis = None
self.bad_rcpts += 1
if self.bad_rcpts > 3:
try:
ip = addr2bin(self.connectip)
if ip not in banned_ips:
banned_ips.add(ip)
print >>open('banned_ips','a'),self.connectip
except: pass
return Milter.REJECT
return self.offense()
# FIXME: should dspam_exempt be case insensitive?
if user in block_forward.get(domain,()):
self.forward = False