A little trick and gotcha with Exim ratelimits

September 6, 2012

In light of recent events, I've been exploring Exim's features for ratelimiting incoming email. In the process I have found something that I feel like documenting. Suppose you're trying to establish what ratelimit settings you actually want (ones that won't cut off your users). The simple way to do this is to create a do-nothing ratelimit ACL stanza that exists just to log the actual rate volumes, something like:

  ratelimit = 10 / 10m / per_rcpt / $sender_address
  log_message = SENDER RATE: $sender_rate

This looks like just what you want, except there's a gotcha; this is not actually measuring what you think it is and what you want. The default Exim behavior of ratelimits is that they are 'leaky'. In Exim terminology, this means that if an actual rate exceeds the limit, it doesn't update the rate counters; in effect, the rate counters stick at the point where they started to go over the limit. This behavior is generally what you want for rates that are actually enforced, but it's definitely not what you want if you're only using ratelimits to explore the actual real rates. In this situation what you'd see is a reported 'sender rate' that was almost always only slightly over 10, regardless of what the real sending rate was.

What you want in this situation is for the ratelimit to be 'strict', where it's updated for every action (whether or not the action pushes the rate over the limit). Then it actually tracks the real sending rate. So you actually want the ACL stanza:

  ratelimit = 10 / 10m / per_rcpt / strict / $sender_address
  log_message = SENDER RATE: $sender_rate

(If you're doing ratelimiting, you may or may not want to exclude email to internal addresses. Locally we're going to exclude them, because we mostly care about a compromised user here being exploited to spam outside sites and poison our sender reputation. Spamming our own users is annoying but we can deal with it.)

Written on 06 September 2012.
« Some thoughts on logging failed login attempts (for existing users)
What the standard(s) say about the order of readdir()'s results »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Sep 6 01:27:34 2012
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.