| schlittermann |
Looking for the “old” version (based on files in some directory structure)? I moved it to grey-sh.
There are a lot greylist implementations around (e.g. a greylist daemon: greylistd).
I just needed a really simple one. And a “one size fits all” implementation.
My first attempt was a solution based on files in the local file system (see grey-sh). After it ate all inodes of my secondary MX (having a 2GB filesystem only) I started playing with Exim’s ability to incorporate Perl functions. I know that there’s
I’m quite sure that the current (Perl based) solution is almost as simple as the older one, though it’s slower (see Performance).
And yes, I thought about SQL based versions too. MySQL seemed to be too much effort to setup (because it should be really simple) and SQLite is not shipped as part of the Exim packages compiled for Debian GNU/Linux currently. And, another point, the configuration wouldn’t read as clean as it is now.
I implemented a small Perl function which stores its data in a DBM file. Each greylisted item (key) gets two associated timestamps (values). One timestamp for the time the item was inserted and the other for the time the item was used the last time. This latter timestamp is for cleaning purpose only.
The unseen function returns “yes” if the item is seen
the first time or if there didn’t pass enough time since it was seen the
first time. In all other cases it returns “no”.
This greylist works on whatever items you want, preferrably on sender
ip address (in $sender_host_address) or sender address (in
$sender_address) or on some tuples (sender address +
recipient address).
If you expect to get mails from hosts with changing IP this greylist may not be for you. But you may consider using the senders (mail) address.
If you expect to get mails from providers with a large amount of outgoing mail servers it may take a while until your greylist learned about all of them.
If you’re hosting several domains you should expect a lower
efficency, because it can happen that the sending address will contact
you again, not as part of retrying but just for some other domain. To
avoid this you may use a tuple ($sender_host_address plus
$domain for greylisting). But I do not know if all MTA can
handle temporary errors on just some recipient addresses.
Update (6 Feb 07): I’ve dropped IP based greylisting, since
I saw in real live that e.g. web.de uses different outgoing
servers each time for attempts sending the same message.
Here some live statistic for a combined (sender address, recipient address) based greylist (updated once per hour):
(Live statistics were previously fetched dynamically — removed in static build.)
It’s up to you where your greylist rule gets applied. The HELO test may be a good choice. But if you’ve trusted hosts (authenticated), then you might give them a chance to authenticate first. For this reason I use this rule in the MAIL test:
acl_check_rcpt:
accept authenticated = *
defer condition = ${perl{unseen}{<$sender_address>:<$local_part@$domain>}}
log_message = greylisted ($sender_host_address)
...
For passing more parameters (grey time, DBM-File) please read the comments in the script.
It’s quite simple, straight forward and hopefully without any considerable bugs. You’ll find it here: https://git.schlittermann.de/IUS/libexim-grey-perl
You have to load the script into your Exim. Check if your Exim is
built with Perl support (exim -v -bV should show you “Perl”
among some other features).
For further information follow the linked docs: https://git.schlittermann.de/IUS/libexim-grey-perl#documentation
Sure, there is a performance hit, because as soon as Exim starts
evaluating the ${perl{...}} statement, it has to load/link
the Perl libraries. On my system I got about 30ms for loading plain Exim
and about 130ms for loading Exim plus the Perl library. (See exim-lookup-benchmark.txt for some
more comparisons.)
But if you see that you have to scan about 80% less messages for containing spam or viruses, you will survive with these 100ms :) I think there is some space for optimization, but this is left as an exercise to the reader.
In the repository you’ll find an exigrey script, it can
be used for listing your items, creating some statistics and for
cleaning up. (Try --help.)
# exigrey --list
66.135.209.199 : 1167598436 1167600030 (1594s 2006-12-31 21:53:56 2006-12-31 22:20:30)
85.221.200.142 : 1167598622 1167598622 ( 0s 2006-12-31 21:57:02 2006-12-31 21:57:02)
62.57.33.50 : 1167598674 1167598674 ( 0s 2006-12-31 21:57:54 2006-12-31 21:57:54)
...
# exigrey --stats
...
# exigrey --cleanup 7
....
The script and the exigrey maintenance utility are
available from the git repository: https://git.schlittermann.de/IUS/libexim-grey-perl.
Some issue, not specifically to this approach, not even to greylisting, but to returning temporary errors: some Exchange 2003 seem to have problems with 4xx responses. (I do not want to discuss here, if Exchange is a useful MTA platform, if it gets confused by 4xx responses. More I’d like to “kill” these Exchange admins, when they try to explain why greylisting is a bad thing. They do not understand, that temporary errors can happen at *any* time, not just generated by greylisting.)