milter-greylist (mail rate limiting) limits everything on instead of just one user


Recently I enabled the mail rate limiting feature to test it and I found some issue. The setup is default installaiton of CentOS 6.5 + Virtualmin. CentOS is running Postfix as default MTA.

Here is what happens: I install the mail rate limiting using the option in Virtualmin (which installs the package from the Virtualmin repo), then enable the mail rate limiting and put a low general limit of 60 messages per hour. What is expected is that the milter will greylist any user sending more than 60 messages per hour even for the local users sending mail via PHP or sendmail.

What happens is that if a local user reaches the limit, then nobody can send email from anymore (local users sending via sendmail or PHP). Here are the logs:

This is what I get when I try to send a lot of emails via PHP:

Apr 8 04:40:32 s3 postfix/pickup[12585]: 342B0802AA2: uid=508 from= Apr 8 04:40:32 s3 milter-greylist: smfi_getsymval failed for {if_addr} Apr 8 04:40:32 s3 postfix/cleanup[26517]: 342B0802AA2: message-id= Apr 8 04:40:32 s3 milter-greylist: ratelimit overflow for class virtualmin_limit: 6219, limit is 60 recipients / 3600 sec, key = "" Apr 8 04:40:32 s3 milter-greylist: 342B0802AA2: addr localhost[] from to blacklisted (ACL 65) Apr 8 04:40:32 s3 postfix/cleanup[26517]: 342B0802AA2: milter-reject: RCPT from localhost[]: 5.7.1 Message quota exceeded; from= to= Apr 8 04:40:32 s3 postfix/cleanup[26517]: warning: 342B0802AA2: milter configuration error: can't reject recipient in non-smtpd(8) submission Apr 8 04:40:32 s3 postfix/cleanup[26517]: warning: 342B0802AA2: deferring delivery of this message

It is what we expect, the milter kicks in and defers the delivery of the messages.

Now I try to send an email from another local user:

Apr 8 04:43:20 s3 postfix/pickup[12585]: D6EAB802A7B: uid=0 from= Apr 8 04:43:20 s3 milter-greylist: D6EAB802A7B: addr localhost[] from to blacklisted (ACL 65) Apr 8 04:43:20 s3 postfix/cleanup[22329]: D6EAB802A7B: milter-reject: RCPT from localhost[]: 5.7.1 Message quota exceeded; from= to=

It is something that we do not expect. This user didn’t sent too much emails and his’ emails should not be blacklisted.

It looks like when a local user gets blacklisted, the whole localhost is actually blacklisted (which means that nobody can send emails anymore).

Something interesting is the line milter-greylist: smfi_getsymval failed for {if_addr}. I have read in a previous post ( Locutus saying it is not a real problem. But I see here: this thing is probably used to identify local mail and there is a workaround for Postfix. Also in the building instructions of milter-greylist is pointed that if you are building for Postfix you should use --enable-postfix key. And if you check the code of the milter-greylist you’ll see that enabling postfix exchanges {if_addr} with {client_addr}.

So it looks whoever built the CentOS package in the Virtualmin repo didn’t used the --enable-postfix key and more likely the failing {if_addr} is not quite harmless as it probably prevent the milter from detecting if the mail is local and then blacklist the user and not the IP.

Can you please rebuild the package with --enable-postfix, that will at least get rid of the error message if not fixing the whole problem. Do you thing something else can cause blacklisting of the whole localhost?

Thanks for your time!


OK. So the {if_addr} is not really the problem. The ratelimit keyword have option key, which by default is “%i” that is the IP address. So we need to switch fo “%f” for the “from” value. Then we should greylist not blacklist otherwise the IP/user will be blocked forever. Then we should turn off the autowhite otherwise the message will be resent immediately. So at the end the rule is like that:

ratelimit "virtualmin_limit" rcpt 30 / 30m key "%f" racl greylist from /.*/ ratelimit "virtualmin_limit" delay 31m autowhite 0m msg "Message quota exceeded" racl whitelist default

The only drawback is that it does not make difference between mails sent from localhost, mails sent via SMTP from another host (using mail client) and mail from other servers for local users.

If we can split these queues we can achieve:

  • mail sent from localhost (via PHP or sendmail) should be limited using the “from” field (it is safe, it is always the linux user). We should block the user not the IP.
  • mails sent via email clients (Thunderbird etc.) should be scanned and limited by the IP or the user used for authentication. Better IP it is easier.
  • mail coming from other mail servers for local users should be scanned and limited by the IP. (this is good security measure as it will prevent DoS attacks nicely)

What are your thoughts?

We have encountered the same problem. I’ll try the above suggestion and see how it goes.

any idea how to fix that? It spams the log file, so i might not see the more relevant parts of it ;-(

This still needs to be addressed. I just put my newest server together, set it up for 500 per hour and promptly locked every address on the machine out. greylist sees every single message as if it comes from localhost, so it happily blocks localhost after 500 messages of any kind, and better, never releases them. I am experimenting with the settings above, hopefully then will work for me too, but the Virtualmin defaults do need attention.


We should probably talk about this in a ticket in the tracker. I’ve created that here: