[exim] Ratelimiting, a fix and a patch

Top Page
Delete this message
Reply to this message
Author: Dean Brooks
Date:  
To: exim-users
Subject: [exim] Ratelimiting, a fix and a patch
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@???