em Sem categoria

GrayList no servdir de emails (EXIM/MYSQL) – Mini tutorial

Este artigo foi tirado do site Dicas-L da Unicamp.

Colabora??o: Silmar A. Marca

Graylist ? uma lista “cinza”, onde o servidor rejeita a
mensagem por um determinado tempo. Tal atitude forca a
mensagem a ser re-enviada, o que geralmente n?o acontece
caso a mesma seja enviada por um servidor de SPAM ou por
in?meros tipos de VIRUS. Uma vez a mensagem conseguir ser
enviada, o servidor que a enviou poder? postar sucessivas
mensagens sem atraso.

Funciona bem na vers?o 4.50 ou superior do EXIM. ?
pr?-requisito compilar o exim com suporte a mysql.

Vale a pena ressaltar que o GrayList apresentado ?
modificado do padr?o original. O mesmo valida apenas o
dominio de quem envia e a rede do mesmo. Valida tamb?m
mensagens de erro (Bounce). Tal modifica??o tem apresentado
os efeitos positivos de diminuir atrasos na entrega da
mensagem em caso de round-robing nos ips de entrega,
isto sem causar impacto na eficiencia da ferramenta.

Observa se que ? importante adicionar o graylist no final
das clausulas rcpt e data e n?o no inicio! Adicionar
antes do aceite final para qualquer hosts! A mesma n?o
impede usuarios autenticados, relay Hosts e SPF validados
(caso habilitado).

Partes do c?digo foram baseados em diversos tutorias na internet.

– Site do EXIM (http://www.exim.org/)
– MYSQL (http://www.mysql.org/)
– SPF (http://www.libspf2.org/)

Criar tabela no mysql:
======================

#
# Estrutura da tabela `greylist`
#

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 ‘;

# ——————————————————–

#
# Estrutura da tabela `greylist_log`
#

CREATE TABLE `greylist_log` (
`id` bigint(20) NOT NULL auto_increment,
`listid` bigint(20) NOT NULL default ‘0’,
`timestamp` datetime NOT NULL default ‘0000-00-00 00:00:00’,
`kind` enum(‘deferred’,’accepted’) NOT NULL default ‘deferred’,
PRIMARY KEY (`id`)
) TYPE=MyISAM COMMENT=’GrayList Log’;

Arquivo exim.conf:
==================

< ..Outras configuracoes iniciais...>

#Comentar caso nao haja base Mysql
MYSQL_SERVER = “localhost/baseexim/usuarioeximbd/senhaeximbd”

#-DEF: Lista GreyList (Defer Temporario)
.ifdef MYSQL_SERVER
GREYLIST_ENABLED_GREY = yes
# GREYLIST_ENABLED_LOG = 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
GREYLIST_LOG_TABLE = greylist_log
# GREYLIST_SKPSPF = yes
.endif

< ..Outras configuracoes iniciais...>

.ifdef MYSQL_SERVER
.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’)

GREYLIST_LOG = INSERT INTO GREYLIST_LOG_TABLE \
(listid, timestamp, kind) \
VALUES ($acl_m9, now(), ‘$acl_m8’)
.endif
.endif

< ..Outras configuracoes iniciais...>

#-Definicao da ACL. Clausula GreyList (ocorre antes do rcpt e do data):
.ifdef GREYLIST_ENABLED_GREY
greylist_acl:

# Limpar tabela automaticamente 09:3xBRST 10:3xBRDT (horario normal)
warn condition = ${if eq {${substr{9}{3}{$tod_zulu}}} {123}{yes}{no}}
set acl_m4 = ${lookup mysql{GREYLIST_CLEAN}}

warn set acl_m8 = ${lookup mysql{GREYLIST_TEST}{$value}{result=unknown}}
set acl_m9 = ${extract{id}{$acl_m8}{$value}{-1}}
set acl_m8 = ${extract{result}{$acl_m8}{$value}{unknown}}

accept
condition = ${if eq {$acl_m8} {unknown} {yes}}
condition = ${lookup mysql{GREYLIST_ADD}{yes}{no}}

.ifdef GREYLIST_ENABLED_LOG
warn condition = ${lookup mysql{GREYLIST_LOG}}
.endif

accept
condition = ${if eq{$acl_m8} {deferred} {yes}}
condition = ${lookup mysql{GREYLIST_DEFER_HIT}{yes}{yes}}

warn condition = ${lookup mysql{GREYLIST_OK_COUNT}}

warn !senders = : [email protected]* : [email protected]*
condition = ${lookup mysql{GREYLIST_OK_NEWTIME}}
warn senders = : [email protected]* : [email protected]*
condition = ${lookup mysql{GREYLIST_OK_BOUNCE}}
deny
.endif

< ..Outras configuracoes de ACL...>

acl_check_rcpt:
< ... Outras configuracoes deste rcpt. Como verifica??es de sender, aceitar relay_hosts e autenticados...>
< ... Geralmente coloca se esta clausula antes do accept final para quem n?o ? ralay_host e autenticado...>
.ifdef GREYLIST_ENABLED_GREY
defer hosts = !+relay_from_hosts
!authenticated = *
.ifdef GREYLIST_SKPSPF
!spf = pass
.endif
acl = greylist_acl
message = GreyListed: please try again later
delay = 15s
.endif
.endif

< ..Outras configuracoes. Outros ACLs...>

acl_check_data:
< ... Outras configuracoes deste rcpt. Como verifica??es de sender, aceitar relay_hosts e autenticados...>
< ... Geralmente coloca se esta clausula antes do accept final para quem n?o ? ralay_host e autenticado...>
.ifdef GREYLIST_ENABLED_GREY
defer
.ifdef GREYLIST_SKPSPF
!spf = pass
.endif
acl = greylist_acl
message = GreyListed: please try again later
delay = 15s
.endif