você está aqui: Home  → Arquivo de Mensagens

GrayList no servdir de emails (EXIM, MYSQL) - Mini tutorial

Colaboração: Silmar A. Marca

Data de Publicação: 30 de Maio de 2005

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.

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         = : postmaster@* : Mailer-Daemon@*
        condition        = ${lookup mysql{GREYLIST_OK_NEWTIME}}
   warn senders          = : postmaster@* : Mailer-Daemon@*
        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
  

Silmar A. Marca, GrupoGSN - Desenvolvimento, Implantação e Verificação de Servidores Profissionais baseados em Linux/Novell



 

 

Veja a relação completa dos artigos de Silmar A. Marca

Opinião dos Leitores

Seja o primeiro a comentar este artigo
*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script