Hi,
We've been using Exim's new ratelimiting ACL commands over the past
several months (since the 4.60 release) and have found them to be
extremely powerful. Once you get your head around the leaky versus
strict concept, it all falls into place.
So powerful in fact that we have been able to eliminate the need for
setting recipients_max on a per message basis (for local users) since
rate limiting will eventually limit them.
Now, the problem, and a proposed fix w/ patch.
Local submissions (acl_not_smtp) don't properly record per-recipient
(per_rcpt) checks properly into the ratelimit counters. No matter how
many recipients are injected in a locally submitted message, the
ratelimiters only record a single recipient.
True, you can limit the number of messages (per_mail), but someone
could send 200 recipients per message from a CGI script which could
easily account for thousands of recipients very quickly.
This simple patch against acl.c seems to fix the problem by recording
the true number of recipients for local submissions into the ratelimiter
counters:
*** ./acl.c.orig Thu May 11 10:58:12 2006
--- ./acl.c Thu May 11 10:28:26 2006
***************
*** 2036,2042 ****
Arguments:
arg the option string for ratelimit=
log_msgptr for error messages
!
Returns: OK - Sender's rate is above limit
FAIL - Sender's rate is below limit
DEFER - Problem opening ratelimit database
--- 2036,2043 ----
Arguments:
arg the option string for ratelimit=
log_msgptr for error messages
! where ACL_WHERE_xxxx indicating which ACL this is
!
Returns: OK - Sender's rate is above limit
FAIL - Sender's rate is below limit
DEFER - Problem opening ratelimit database
***************
*** 2044,2050 ****
*/
static int
! acl_ratelimit(uschar *arg, uschar **log_msgptr)
{
double limit, period;
uschar *ss, *key;
--- 2045,2051 ----
*/
static int
! acl_ratelimit(uschar *arg, uschar **log_msgptr, int where)
{
double limit, period;
uschar *ss, *key;
***************
*** 2263,2268 ****
--- 2264,2272 ----
if (per_byte)
dbd->rate = (message_size < 0 ? 0.0 : (double)message_size)
* (1 - a) / i_over_p + a * dbd->rate;
+ else if (per_cmd && where == ACL_WHERE_NOTSMTP)
+ dbd->rate = ((double)recipients_count)
+ * (1 - a) / i_over_p + a * dbd->rate;
else
dbd->rate = (1 - a) / i_over_p + a * dbd->rate;
}
***************
*** 2873,2879 ****
#endif
case ACLC_RATELIMIT:
! rc = acl_ratelimit(arg, log_msgptr);
break;
case ACLC_RECIPIENTS:
--- 2877,2883 ----
#endif
case ACLC_RATELIMIT:
! rc = acl_ratelimit(arg, log_msgptr, where);
break;
case ACLC_RECIPIENTS:
--
Dean Brooks
dean@???