Notícias de Tenologia

Visitantes Online

Nós temos 1 visitante online
Auditoria no Plesk PDF Imprimir E-mail
Escrito por Daniel Maglione   
Sáb, 16 de Agosto de 2008 15:42

Plesk + qmail queue_extra Howto

Introdução

O Plesk (http://www.plesk.com.br/) é um painel de controle para hosting bem fácil de usar, traduzido para o Português, e que tem uma ampla base de conhecimento.

Este documento foi criado devido a necessidade de se criar a solução para a requisição de um de nossos clientes que tem uma necessidade especial: Auditar todas as mensagens enviadas e recebidas pelos seus funcionários.

Como em todo painel de controle, o preço da facilidade são algumas limitações. No caso do Plesk, existe apenas opção de cópia de mensagens recebidas utilizando aliases, porém essa configuração além de difícil (precisa ser habilitada individualmente para cada caixa) ainda não resolve totalmente o problema pois não contempla as mensagens enviadas.

Seria necessário fazer alguma configuração manual no servidor. Em um servidor baseado em Postfix, é algo bastante simples, basta utilizar a opção sender_bcc_maps e pronto, mas o Plesk utiliza qmail. Trocar para o Postfix estava fora de cogitação, pois estragaria as funcionalidades de correio do Plesk, praticamente inutilizando o Painel.

Para resolver este desafio precisamos habilitar a fila extra do qmail (QUEUE_EXTRA) pois só assim podemos ter um ponto central por onde passam todas as mensagens, além disso será necessário criar um mecanismo onde seja possível configurar individualmente o domínio que necessita da funcionalidade, e tudo isso sem estragar as funcionalidades do painel.

Como fazer isso? Isso é o que pretendo explicar neste howto.

Pré-requisitos

O conteúdo deste artigo também pode ser aplicado em um servidor qmail sem o Plesk, bastando algumas pequenas alterações, principalmente na parte dos patches de compilação.

Recompilar o qmail, habilitando QUEUE_EXTRA

Baixe o qmail e descompacte em /usr/src, faça o mesmo com os patches do Plesk:

 cd /usr/src
 wget http://cr.yp.to/software/qmail-1.03.tar.gz
 tar xzvf qmail-1.03.tar.gz

Se for Plesk 8.0.X

 wget http://kb.swsoft.com/attachments/1161/qmail_patches.tar.gz 
 tar xzvf qmail_patches.tar.gz

Se for Plesk 7.5.4

 wget http://kb.swsoft.com/attachments/1088/qmail_patches.tgz
 tar xzvf qmail_patches.tar.gz

Aplique os patches na árvore do qmail:

 cd /usr/src/qmail-1.03
 for PATCH in `ls -1 /usr/src/qmail_patches/*`; do patch -p0 < $PATCH; done

Nesse momento você tem a árvore do qmail com os patches do Plesk, para habilitar o QUEUE_EXTRA edite o arquivo extra.h e defina QUEUE_EXTRA como "Tlog\0" e QUEUE_EXTRALEN como 5, conforme as linhas abaixo:

 #ifndef EXTRA_H
 #define EXTRA_H
 
 #define QUEUE_EXTRA "Tlog\0"
 #define QUEUE_EXTRALEN 5
 
 #endif

Isso fará com que o qmail crie um fila extra que duplicará todas as mensagens da fila original e as entregará conforme regras definidas em /var/qmail/alias/.qmail-log. As regras deste arquivo seguem o mesmo padrão dos outros "dot-qmail".

Correções necessárias ANTES da compilação
  • Edite o arquivo conf-spawn e coloque o número 500 na primeira linha. Isso limitará a concorrencia de entregas em 500, não prejudicando o limite de 1024 descritores padrão do Debian. É possível mudar isso, mas não é o foco deste documento.
  • Um patch (patch-pe) causará um erro no Makefile (será que o patch fornecido pela SWSoft não está completo?), pois agora o comando auto-uid exige nome, valor e uid como parâmetros e não mais apenas nome e valor. Para corrigir aplique o patch abaixo:
 --- qmail-1.03.orig/Makefile   2007-02-13 17:13:56.000000000 -0200
 +++ qmail-1.03/Makefile        2007-02-14 11:19:49.344861888 -0200
 @@ -112,16 +112,16 @@
 
  auto_uids.c: \
  auto-uid auto-gid conf-users conf-groups
 -      ( ./auto-uid auto_uida `head -1 conf-users` \
 -      &&./auto-uid auto_uidd `head -2 conf-users | tail -1` \
 -      &&./auto-uid auto_uidl `head -3 conf-users | tail -1` \
 -      &&./auto-uid auto_uido `head -4 conf-users | tail -1` \
 -      &&./auto-uid auto_uidp `head -5 conf-users | tail -1` \
 -      &&./auto-uid auto_uidq `head -6 conf-users | tail -1` \
 -      &&./auto-uid auto_uidr `head -7 conf-users | tail -1` \
 -      &&./auto-uid auto_uids `head -8 conf-users | tail -1` \
 -      &&./auto-gid auto_gidq `head -1 conf-groups` \
 -      &&./auto-gid auto_gidn `head -2 conf-groups | tail -1` \
 +      ( ./auto-uid auto_uida `head -1 conf-users` `head -1 conf-users \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-uid auto_uidd `head -2 conf-users | tail -1` `head -2 conf-users | tail -1 \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-uid auto_uidl `head -3 conf-users | tail -1` `head -3 conf-users | tail -1 \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-uid auto_uido `head -4 conf-users | tail -1` `head -4 conf-users | tail -1 \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-uid auto_uidp `head -5 conf-users | tail -1` `head -5 conf-users | tail -1 \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-uid auto_uidq `head -6 conf-users | tail -1` `head -6 conf-users | tail -1 \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-uid auto_uidr `head -7 conf-users | tail -1` `head -7 conf-users | tail -1 \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-uid auto_uids `head -8 conf-users | tail -1` `head -8 conf-users | tail -1 \
        | xargs --replace grep {} /etc/passwd | cut -d ":" -f 3` \
 +      && ./auto-gid auto_gidq `head -1 conf-groups` `head -1 conf-groups \
        | xargs --replace grep {} /etc/group | cut -d ":" -f 3`\
 +      && ./auto-gid auto_gidn `head -2 conf-groups | tail -1` `head -2 conf-groups \
        | tail -1 | xargs --replace grep {} /etc/group | cut -d ":" -f 3` \
        ) > auto_uids.c.tmp && mv auto_uids.c.tmp auto_uids.c
 
  auto_uids.o: \

Para aplicar o patch, salve as linhas acima no arquivo /tmp/plesk_autouid.patch e execute os seguintes comandos:

 patch -p1 < /tmp/plesk_autouid.patch

Antes da compilação, haverá mais um bug relacionado ao suporte SSL, para resolver, execute o comando abaixo:

 echo "-lssl" > ssl.lib

Para compilar:

 apt-get install build-essential libssl-dev libssl0.9.7
 make
Habilitando QUEUE_EXTRA no plesk

Após compilar o qmail, copie o arquivo qmail-queue para o diretório /var/qmail/bin nomeando como qmail-queue.qextra

 cp qmail-queue /var/qmail/bin/qmail-queue.qextra

No plesk o qmail-queue é acionado pelo Dr. Web Anti-Virus. Para habilitar o novo qmail-queue edite o arquivo /etc/drweb/drweb_qmail.conf e substitua a linha:

 QmailQueue = /var/qmail/bin/qmail-queue.origin

Por:

 QmailQueue = /var/qmail/bin/qmail-queue.qextra

Dessa forma a fila extra já está habilitada, e passará a obedecer as regras do arquivo /var/qmail/alias/.qmail-log.

Resumo

Até aqui, apenas habilitamos o suporte a fila extra (QUEUE EXTRA) do qmail, o que faz com que qualquer mensagem enviada ou recebida pelo sistema seja "duplicada" e processada de acordo com as regras do arquivo /var/qmail/alias/.qmail-log. Este arquivo segue as regras dos arquivos "dot-qmail", portanto poderíamos por exemplo encaminhar todas as mensagens para uma única conta, criando o arquivo /var/qmail/alias/.qmail-log com a linha abaixo:

 &email@dominio.com

Mas nossa intenção não é apenas gerar uma cópia das mensagens de qualquer maneira, queremos classificar e verificar quais domínios necessitam de tal "feature" e qual conta receberá o e-mail. Para fazer isso, utilizaremos o operador | (pipe) para enviar as mensagens para um programa de classificação. Como não encontrei nenhum programa de classificação que fizesse o que precisava, resolvi criar um.

O programa de classificação de mensagens

Durante a análise, concluí que as seguintes funcionalidades seriam necessárias ao programa:

  • Uma maneira simples de atualizar a lista de domínios e contas;
  • Lista de domínios que desejam receber cópia dos e-mails enviados e o diretório (maildir) para a entrega destas mensagens;
  • Já que a queue_extra permite, criar uma lista de domínios que desejam receber cópia dos e-mails recebidos e e o diretório (maildir) para a entrega destas mensagens;
  • Seja simples de fazer e dar manutenção, pois o prazo para a construção da funcionalidade era curto.
Arquitetura escolhida

No Debian

Perl

 apt-get install perl perl-base perl-suid

Email::Filter: Não existe pacote para a versão Sarge do Debian, você pode instalar através do CPAN perl -MCPAN -e'install Email::Filter' ou utilizar o pacote que backportei do Etch. Para utilizar, inclua as seguintes linhas no arquivo /etc/apt/sources.list

 #EMail::Filter
 deb http://debian.maglione.com.br/maglione/dists/sarge/main/pool/l libemail-filter-perl/

Aí fica fácil:

 apt-get install libemail-filter-perl
Data::Dumper já faz parte do pacote perl-base
Código fonte do programa
 #!/usr/bin/perl -U

 =head1 NAME

 qmail-MailAudit - qmail queue extra messages classification script

 =head1 SYNOPSIS

 After enable QUEUE_EXTRA features in qmail, use qmail-mailaudit.pl script to send a copy of
 any message sent or received by any domain to a specified account.

 To enable qmail-mailaudit.pl, add the following line in /var/qmail/alias/.qmail-log file:

     |/usr/sbin/qmail-mailaudit.pl

 To map domains and accounts, edit files /var/qmail/control/mailaudit-sent to sent mails and
 /var/qmail/control/mailaudit-recv to received mails. Bellow an example of two files:

 /var/qmail/control/mailaudit-sent
     #Domain;Maildir
     domain.com.br;/var/qmail/mailnames/domain.com.br/recebidos/Maildir/

 /var/qmail/control/mailaudit-recv
     #Domain;Maildir
     domain.com.br;/var/qmail/mailnames/domain.com.br/enviados/Maildir/

 =head1 COPYRIGHT AND LICENSE

 Copyright 2007 by Daniel Maglione <daniel@maglione.com.br>

 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself.

 =cut

 use strict;

 my $debug = undef; # undef = normal mode, 
             defined (any value) = debug mode (don't use under qmail!)
 my $localdelivery_user = 'popuser';

 use Email::Filter;
 if ($debug)
 {
   use Data::Dumper
 }

 sub load_hash
 {
   # load_hash - Reads configurations from file and loads in hash variables
   # Usage: %hash = load_hash('path_to_config_file');
   # Returns: empty if file don't exists or don't have any records
   #          hash of domain->maildir if configuration file is ok

   my $path = shift;

   my $handle;
   my $record;
   my %result_hash = ();
   open ($handle, "<$path") or return(%result_hash);
   foreach $record (<$handle>)
   {
     if (not $record =~ /^\s*#/) # Strips comments (lines begining with #)
     {
       my @tmp_array;
       chomp($record);
       @tmp_array = split(/;/, $record);
       $result_hash{$tmp_array[0]} = $tmp_array[1];
       undef @tmp_array;
     }
   }
   return(%result_hash);
 }

 # Lines below are to change the qmail-queue user to localdelivery_user
 my ($login, $pass, $uid, $gid) = getpwnam($localdelivery_user);
 $( = $gid;
 $) = $gid;
 $< = $uid;
 $> = $uid;
 if ($debug)
 {
   print ("Debug: Changing to user $login, UID = $uid, GID = $gid\n");
 }
 if (  ((split(/ /,$)))[0] ne $gid) || ((split(/ /,$())[0] ne $gid)  )
 {
   print ("Couldn't Change Group ID!");
 }

 if (  ($> ne $uid) || ($< ne $uid)  )
 {
   print ("Couldn't Change User ID!");
 }
 # We don't need these anymore...
 undef($login);
 undef($pass);
 undef($uid);
 undef($gid);

 my %sent_array = load_hash('/var/qmail/control/mailaudit-sent');
 # Hash of domains that we need to audit sent mails (Domain->Maildir)

 my %recv_array = load_hash('/var/qmail/control/mailaudit-recv');
 # Hash of domains that we need to audit sent received mails 
 # (Domain->Maildir)

 my $email = Email::Filter->new();
 $email->exit(0);
 if($debug)
 {
   print (Dumper($email));
 }
 # This loop looks the From header. If From domain is found on sent_array, then
 # we need to deliver message on  maildir specified in the config 
 # (sent mail audit).
 my $from;
 foreach $from (keys (%sent_array))
 {
   if ($email->from =~ /^.*\@$from>?$/)
   {
     if ($debug)
     {
       print "Debug: Delivering message from '" . $email->from . 
             "' because domain $from is in config file (sent audit)\n";
     }
     $email->accept($sent_array{$from});
   }
 }

 # This loop looks the To header. If To domain is found on recv_array, then
 # we need to deliver message on  maildir specified in the config 
 #(received mail audit).
 my $to;
 foreach $to (keys (%recv_array))
 {
   if ($email->to =~ /^.*\@$to>?$/)
   {
     if ($debug)
     {
       print "Debug: Delivering message to '" . $email->to . 
             "' because domain $to is in config file (received audit)\n";
     }
     $email->accept($recv_array{$to});
   }
 }

 exit(0);
 # Returns succeful state to qmail-queue
Configurando o programa
  • O programa deve ser salvo no diretório /usr/sbin com o nome de qmail-mailaudit.pl
  • Para o programa poder efetuar a troca de usuário, o setuid-bit deve estar ligado, e o programa deve ter acesso de execução para os usuários qmailq e popuser, para isso pode-se setar as permissões da seguinte forma:
 chmod 4755 /usr/sbin/qmail-mailaudit.pl

Para evitar loop de mensagens, o programa entrega as mensagens diretamente no Maildir do usuário (ao invés de utilizar novamente o qmail), para isso o programa precisa saber qual usuário deve entregar as mensagens no maildir. Normalmente no Plesk o usuário é o popuser, caso não seja em seu caso, altere a linha abaixo no programa:

 my $localdelivery_user = 'popuser';
  • Crie as listas de mapeamento domínio vs maildir, incluindo todos os domínios que receberão cópias das mensagens:
  • E-Mails enviados, arquivo /var/qmail/control/mailaudit-sent
 #Domain;Maildir
 domain.com.br;/var/qmail/mailnames/domain.com.br/recebidos/Maildir/
  • E-Mails recebidos, arquivo /var/qmail/control/mailaudit-recv
 #Domain;Maildir
 domain.com.br;/var/qmail/mailnames/domain.com.br/recebidos/Maildir/
  • Crie o arquivo /var/qmail/alias/.qmail-log com a linha abaixo:
 |/usr/sbin/qmail-mailaudit.pl
  • Reinicie o qmail com o comando:
 invoke-rc.d qmail restart
Pacote qmail-mailaudit

Se você estiver utilizando Debian Sarge, pode fazer uso do pacote qmail-mailaudit que criei, acrescentando as linhas abaixo no seu arquivo /etc/apt/sources.list:

 #qmail-mailaudit
 deb http://debian.maglione.com.br/maglione/dists/sarge/main/pool/q qmail-mailaudit/
 deb http://debian.maglione.com.br/maglione/dists/sarge/main/pool/l libemail-filter-perl/

Aí basta executar o comando:

 apt-get install qmail-mailaudit
Testando

Se tudo funcionou, o log do qmail deve exibir mensagens como abaixo:

 Feb 14 17:05:52 mail qmail: 1171479952.922001 starting delivery 8035: msg 1107836 to local 
  Este endereço de e-mail está protegido contra spambots. Você deve habilitar o JavaScript para visualizá-lo.
 
 Feb 14 17:05:52 mail qmail: 1171479952.922038 status: local 1/10 remote 0/20
 Feb 14 17:05:52 mail qmail: 1171479952.922064 starting delivery 8036: msg 1107836 to local 
  Este endereço de e-mail está protegido contra spambots. Você deve habilitar o JavaScript para visualizá-lo.
 
 Feb 14 17:05:52 mail qmail: 1171479952.922085 status: local 2/10 remote 0/20

A cada mensagem enviada ou recebida o qmail deve enviar uma mensagem igual para o alias log, essa mensagem deve ser filtrada pelo qmail-mailaudit.pl e entregue diretamente na caixa do usuário especificado nos arquivos de configuração.

Em caso de problemas
  • Certifique-se do funcionamento da QUEUE_EXTRA;
  • Verifique se o usuário da variavel $localdelivery_user possui permissões para entregar mensagens nos maildirs;
  • Verifique se o arquivo qmail-mailaudit.pl tem permissão de execução e setuid (chmod 4755 /usr/sbin/mailaudit.pl) e seu seu owner e group são root;
  • Habilite o modo Debug e consulte os logs para identificar a causa da falha.

TODO

Traduzir o howto para inglês e submetê-lo ao site da SWSoft

LAST_UPDATED2