Exim Fast Gray List Mini Tutorial

Fast Gray List Mini Tutorial

  1. Fast Gray List Mini Tutorial
    1. Introduction
    2. SQL Table Definition
    3. Exim Config File Definitions
    4. Greylist ACL
    5. Check RCPT ACL
    6. Check DATA ACL

 

Taken from exim-users EximMailingLists posting by Silmar A. Marca in [WWW] http://www.exim.org/mail-archives/exim-users/Week-of-Mon-20050131/msg00147.html

Introduction

This is based (but modified) on the tutorial written by Tor Slettnes, which essentially incorporates the stuff from [WWW] http://johannes.sipsolutions.net/Projects/exim-greylist.

I have a tested implementation of modify graylist simplest: this gray list compare only domain of sender and a mask/24 of sender to domain of rcpt. Have a auto clean of gray list old recordes...

It is a fast gray list and work!!!

SQL Table Definition

#Create Sql bd
CREATE TABLE `greylist` (
`id` bigint(20) NOT NULL auto_increment,
`relay_ip` varchar(20) default NULL,
`sender_type` enum('NORMAL','BOUNCE') NOT NULL default 'NORMAL',
`sender` varchar(150) default NULL,
`recipient` varchar(150) default NULL,
`block_expires` datetime NOT NULL default '0000-00-00 00:00:00',
`record_expires` datetime NOT NULL default '9999-12-31 23:59:59',
`create_time` datetime NOT NULL default '0000-00-00 00:00:00',
`TYPE` enum('AUTO','MANUAL') NOT NULL default 'MANUAL',
`passcount` bigint(20) NOT NULL default '0',
`last_pass` datetime NOT NULL default '0000-00-00 00:00:00',
`blockcount` bigint(20) NOT NULL default '0',
`last_block` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `relay_ip` (`relay_ip`,`sender`,`recipient`,`sender_type`)
) TYPE=MyISAM COMMENT='GrayList ' AUTO_INCREMENT=199 ;

Exim Config File Definitions

First section of the config file.

#Exim.conf file
GREYLIST_ENABLED_GREY = yes
GREYLIST_INITIAL_DELAY = 12 MINUTE
GREYLIST_INITIAL_LIFETIME = 4 HOUR
GREYLIST_WHITE_LIFETIME = 36 DAY
GREYLIST_BOUNCE_LIFETIME = 7 DAY
GREYLIST_RECORD_LIFETIME = 90 DAY
GREYLIST_TABLE = greylist
#....

.ifdef GREYLIST_ENABLED_GREY
GREYLIST_TEST = SELECT CASE \
WHEN now() > block_expires THEN "accepted" \
ELSE "deferred" \
END AS result, id \
FROM GREYLIST_TABLE \
WHERE (now() < record_expires) \
AND (sender_type = ${if def:sender_address_domain{'NORMAL'}{'BOUNCE'} }) \
AND (sender = '${quote_mysql:${if
def:sender_address_domain{$sender_address_domain}{${domain:$h_from:}} }}') \
AND (recipient = '${quote_mysql:${if
def:domain{$domain}{${domain:$h_to:}} }}') \
AND (relay_ip = '${quote_mysql:${mask:$sender_host_address/24}}') \
ORDER BY result DESC LIMIT 1

GREYLIST_ADD = REPLACE INTO GREYLIST_TABLE \
(relay_ip, sender_type, sender, recipient, block_expires, \
record_expires, create_time, type) \
VALUES ( '${quote_mysql:${mask:$sender_host_address/24}}', \
${if def:sender_address_domain{'NORMAL'}{'BOUNCE'}}, \
'${quote_mysql:${if
def:sender_address_domain{$sender_address_domain}{${domain:$h_from:}} }}', \
'${quote_mysql:${if def:domain{$domain}{${domain:$h_to:}} }}', \
DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_DELAY), \
DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_LIFETIME), \
now(), \
'AUTO' \
)

GREYLIST_DEFER_HIT = UPDATE GREYLIST_TABLE \
SET blockcount=blockcount+1, last_block=now() \
WHERE id = $acl_m9

GREYLIST_OK_COUNT = UPDATE GREYLIST_TABLE \
SET passcount=passcount+1, last_pass=now() \
WHERE id = $acl_m9

GREYLIST_OK_NEWTIME = UPDATE GREYLIST_TABLE \
SET record_expires = DATE_ADD(now(), INTERVAL
GREYLIST_WHITE_LIFETIME) \
WHERE id = $acl_m9 AND type='AUTO'

GREYLIST_OK_BOUNCE = UPDATE GREYLIST_TABLE \
SET record_expires = DATE_ADD(now(), INTERVAL
GREYLIST_BOUNCE_LIFETIME) \
WHERE id = $acl_m9 AND type='AUTO'

GREYLIST_CLEAN = DELETE FROM GREYLIST_TABLE \
WHERE (record_expires > DATE_ADD(now(), INTERVAL
GREYLIST_RECORD_LIFETIME)) AND (type='AUTO')
.endif
#...

Greylist ACL

#-GreyList (before rcpt and data):
.ifdef GREYLIST_ENABLED_GREY
greylist_acl:
# clean greylist records as 09:3xBRST 10:3xBRDT (horario normal)
warn condition = ${if eq {${substr{8}{3}{$tod_zulu} }} {123}{yes}{no}}
set acl_m4 = ${lookup mysql{GREYLIST_CLEAN}}

# For regular deliveries, check greylist.

# check greylist tuple, returning "accepted", "deferred" or "unknown"
# in acl_m8, and the record id in acl_m9

warn set acl_m8 = ${lookup mysql{GREYLIST_TEST}{$value}{result=unknown}}
# here acl_m8 = "result=x id=y"

set acl_m9 = ${extract{id}{$acl_m8}{$value}{-1}}
# now acl_m9 contains the record id (or -1)

set acl_m8 = ${extract{result}{$acl_m8}{$value}{unknown}}
# now acl_m8 contains unknown/deferred/accepted

# check if we know a certain triple, add and defer message if not
accept
# if above check returned unknown (no record yet)
condition = ${if eq {$acl_m8} {unknown} {1}}
# then also add a record
condition = ${lookup mysql{GREYLIST_ADD}{yes}{no}}

# check if the triple is still blocked
accept
# if above check returned deferred then defer
condition = ${if eq{$acl_m8} {deferred} {1}}
# and note it down
condition = ${lookup mysql{GREYLIST_DEFER_HIT}{yes}{yes}}

# use a warn verb to count records that were hit
warn condition = ${lookup mysql{GREYLIST_OK_COUNT}}

# use a warn verb to set a new expire time on automatic records,
# but only if the mail was not a bounce, otherwise set to now().
warn !senders = : postmaster@* : Mailer-Daemon@*
condition = ${lookup mysql{GREYLIST_OK_NEWTIME}}
warn senders = : postmaster@* : Mailer-Daemon@*
condition = ${lookup mysql{GREYLIST_OK_BOUNCE}}
deny
.endif
#....

Check RCPT ACL

acl_check_rcpt:
#....<put is in end of rcpt acl, before accept clause>
.ifdef GREYLIST_ENABLED_GREY
defer hosts = !+relay_from_hosts
!authenticated = *
!senders = : postmaster@* : Mailer-Daemon@*
acl = greylist_acl
message = GreyListed: please try again later
.endif
<the end clause accept is here>

#....

Check DATA ACL

acl_check_data:
#....<put is in end of data acl, before accept clause>
.ifdef GREYLIST_ENABLED_GREY
defer hosts = !+relay_from_hosts
senders = : postmaster@* : Mailer-Daemon@*
acl = greylist_acl
message = GreyListed: please try again later
.endif
<the end clause accept is here>


,,Although rare, some "legitimate" bulk mail senders, such as groups.yahoo.com, will not retry temporarily failed deliveries. Evan Harris has compiled a list of such senders, suitable for whitelisting purposes

The list is avaliable here [WWW] http://cvs.puremagic.com/viewcvs/greylisting/schema/whitelist_ip.txt?view=markup

Comment: You might want to use an unsigned integer for ip storage, which is more effective especially when you are creating an index over the ip column, which i would recommend as it makes the hole thing faster (note that comparing integer values is faster than comparing string values). PostgreSQL also offers a special data type for ip Adress storage. In MySQL, you can convert an ip adress to an integer using the INET_ATON() function. This doesn't support subnet masks, but I don't see a real point in graylisting a whole /24 network which may also consist of some spambots.

If you having multiple MX Servers, please note that these servers should exchange the graylist information so that delivery does not get deferred on every Server. This can for example be done using the MySQL NDBCluster Engine.

CategoryHowTo

 

http://www.exim.org/eximwiki/FastGrayListMiniTutorial?highlight=%28CategoryHowTo%29

 

In attach - my work exim config