OK, I found a major flaw in my previous teergrubing setup... The new
"delay" modifier takes effect as soon as it is processed, not after the
remaining conditions in the ACL entry are processed. For some reason I
thought it was handled like message/log_message and got done after the
whole ACL entry was completed... oh well, misread of the documentation
on my part.
So, here is what I am now using (with gratuitous line wraps added by
Mozilla at no extra charge):
acl_check_connect:
accept hosts = 127.0.0.1 : +website_mail_hosts :
+skip_rbl_hosts : +local_hosts :
accept log_message = Teergrube: Blacklisted CONNECT
dnslists = BLACKLISTS
delay = 30s
accept
acl_check_mail:
accept hosts = 127.0.0.1 : +website_mail_hosts :
+skip_rbl_hosts : +local_hosts :
accept log_message = Teergrube: Blacklisted MAIL FROM:
dnslists = BLACKLISTS
delay = 30s
accept
These two insert some artificial delays very early in the SMTP
connection for blacklisted hosts.
acl_check_rcpt:
deny log_message = Teergrube: Multiple unknown users
($rcpt_fail_count)
message = unknown user
domains = +local_domains
condition = ${if >{$rcpt_fail_count}{0} {1}{0}}
! verify = recipient
delay = ${eval:30*$rcpt_fail_count}s
deny message = unknown user
domains = +local_domains
! verify = recipient
Add ever-increasing delays for hosts trying dictionary attacks against a
local domain.
acl_check_rcpt: (continued)
deny log_message = Teergrube: Blacklisted RCPT TO:
message = RBL: $sender_host_address,
$dnslist_domain, $dnslist_value, $dnslist_text
! hosts = 127.0.0.1 : +website_mail_hosts :
+skip_rbl_hosts : +local_hosts :
dnslists = BLACKLISTS
delay = ${eval:30*$rcpt_count}s
deny log_message = Teergrube: Sender verification failure
message = invalid sender
! hosts = 127.0.0.1 : +website_mail_hosts :
! sender_domains = +callout_no_cache_domains :
+no_callout_domains
! verify = sender/callout=60s
delay = 30s
deny log_message = Teergrube: Invalid null sender usage
message = invalid use of null sender
senders = :
condition = ${if >{$rcpt_count}{1} {1}{0}}
delay = 30s
Add delays for various other stuff (sender verification failures,
multiple recipient null-sender usage, blacklisted hosts).
acl_check_data:
deny log_message = Teergrube: Hotmail forgery
message = X-Forgery: NOT HOTMAIL SERVER
sender_domains = hotmail.com
condition = ${if def:header_X-Originating-IP: {0}{1}}
delay = 30s
deny log_message = Teergrube: AOL forgery
message = X-Forgery: NOT AOL ADDRESS
senders = \N^\d.*@aol\.com$\N
delay = 30s
deny log_message = Teergrube: AOL forgery
message = X-Forgery: NOT AOL MAILER
sender_domains = aol.com
condition = ${if match {${lc:$h_X-Mailer:}} {(a(?:ol|tlas))}
{0}{1}}
delay = 30s
deny log_message = Teergrube: AOL forgery
message = X-Forgery: NOT AOL SERVER
sender_domains = aol.com
condition = ${if match {${lc:$h_Received:}} {by.*aol\.com}
{0}{1}}
delay = 30s
deny log_message = Teergrube: Yahoo forgery
message = X-Forgery: NOT YAHOO SERVER
sender_domains = yahoo.com
condition = ${if match {$h_Received:}
{(yahoo.com.via.(?:HTTP|NNFMP))} {0}{1}}
delay = 30s
Delays for the infamous Hotmail/AOL/Yahoo forgers...
The only problem I've found so far is that in acl_smtp_connect and
acl_smtp_mail I'm adding delays without denying the connection. Because
there is no denial, log_message never takes effect. I think it might be
good if log_message sent the configured message to the log on _either_ a
denial or a forced delay, but of course only send it one time if a
particular ACL entry causes both a delay and a denial.