Postfix: Contornando comandos incorretos de conexões SMTP

Olá !

Anteriormente, eu publiquei um artigo (https://respirandolinux.wordpress.com/2013/09/20/postfix-contornando-501-syntax-helo-hostname/) sobre como contornar o erro de sintaxe quando clientes remotos enviam o comando HELO/EHLO de forma incorreta, principalmente sem inserir o hostname após o comando. Utilizando o procedimento do meu artigo anterior, não será mais possível aplicar restrições na etapa HELO/EHLO, uma vez que independentemente da entrada, o resultado sempre será “OK”.

É muito comum quando temos um servidor SMTP que será utilizado por aplicações, muitos comandos serem enviados com a sintaxe incorreta ou até mesmo estas aplicações enviarem comandos inválidos. Para contornar este problema, podemos utilizar o parâmetro “smtpd_command_filter” no Postfix.

A diretiva “smtpd_command_filter” (disponível a partir da versão 2.7) é descrita na documentação do Postfix como um último recurso para contornar clientes que enviam comandos incorretos ou inválidos de fato. Apesar das modificações que serão aplicadas, é possível aplicar restrições HELO após utilizar esse parâmetro.

Vejamos um exemplo que pode ser utilizado para contornar clientes que enviam o HELO/EHLO sem estar seguido do FQDN:

smtpd_command_filter = pcre:/etc/postfic/command_filters

Conteúdo do arquivo:

/^HELO\s*$/ HELO nome.desejado
/^EHLO\s*$/ EHLO nome.desejado

Desta forma, quando um cliente remoto enviar o HELO/EHLO sem estar seguindo do hostname, este comando será substituído por “HELO/EHLO nome.desejado”.

No log será exibida uma entrada conforme abaixo sempre que um comando por modificado pelo Postfix.:

replacing client command “HELO” with “HELO domain.invalid”

Zimbra: Aumentando as entregas simultâneas de mensagens

No Zimbra as mensagens são entregues nas caixas postais dos usuários do sistema através do protocolo LMTP, esta operação é bastante dispendiosa e caso não haja conexões LMTP disponíveis no momento da entrega a mensagem será enfileirada. É preciso se atentar que aumentar este parâmetro irá aumentar a utilização de recursos do seu servidor, portanto deve ser feito somente se estiverem ocorrendo enfileiramentos para entregas locais. É possível identificar se o protocolo LMTP está com gargalo procurando pela seguinte mensagem nos logs:

Zimbra LMTP server closing connection; service busy

Para aumentar o número de processos simultâneos do LMTP, que por padrão vem setado para 20, execute o comando abaixo:

zmprov ms nome.do.servidor zimbraLmtpNumThreads NOVO_VALOR

É preciso também modificar a configuração do Postfix, que é o  MTA do Zimbra para igualar a quantidade de entregas simultâneas com a disponibilidade do LMTP:

zmlocalconfig -e postfix_lmtp_destination_concurrency=NOVO_VALOR

Este valor também vem com padrão setado para 20 e deve sempre ser ajustado de acordo com o número de processos do LMTP.

Configurando o Amavis em um servidor dedicado

Olá ! Neste artigo apresento as configurações para separar o Amavis em um servidor dedicado. Em alguns ambientes isso pode ser necessário devido ao trafego de mensagens, onde o MTA (neste exemplo o Postfix)e Amavis precisam ser separados em servidores dedicados.

Neste exemplo o servidor Postfix é o host mail.matriz.com.br (192.168.200.116) e o servidor dedicado para o Amavis é o host amavis.matriz.com.br (192.168.200.115)

Primeiramente, no servidor Postfix edite o main.cf adicionando a seguinte linha:

content_filter = smtp-amavis:amavis.matriz.com.br:10024

Ainda no servidor Postfix, edite o arquivo master.cf adicionando o seguinte serviço:

0.0.0.0:10025 inet n – y – – smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o mynetworks=127.0.0.0/8,192.168.200.115/32
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
-o recipient_bcc_maps=
-o sender_bcc_maps=

Deve-se prestar atenção no parâmetro mynetworks do serviço, onde deve ser incluído o IP do servidor do Amavis para entrega das mensagens. Feito isso, após reiniciar o serviço, o Postfix já irá entregar as mensagens com as configurações feitas.

No servidor Amavis, precisamos colocar o serviço para escutar na porta 10024 e aceitar conexões do nosso MTA. No Debian e derivados o arquivo 20-debian_defaults pode ser editado para incluir as configurações ou o 50-user, que vem limpo justamente para as configurações adicionais. Para distribuições baseadas em Red Hat, o Amavis utiliza um único arquivo de configuração.

@inet_acl = qw(127.0.0.1 192.168.200.115 192.168.200.116 [::1]); # Controle acesso – Informar os IPs dos MTAs e do servidor amavis
$inet_socket_bind = ‘0.0.0.0’; # Onde escutar – Colocar as interfaces onde o Amavis deve aceitar conexões
$inet_socket_port = 10024; # Porta
### Encaminhando para o Postfix ###
$notify_method = ‘smtp:[mail.matriz.com.br]:10025’;
$forward_method = ‘smtp:[mail.matriz.com.br]:10025’;
###

Efetuada as configurações, reinicie o serviço do Amavis e tente enviar uma mensagem, nos logs do Amavis deve aparecer a conexão do MTA:

Feb  4 13:30:27 amavis amavis[3052]: (03052-01) Passed CLEAN {RelayedInternal}, MYNETS LOCAL [192.168.200.116]:51347 [192.168.200.116] <joao@matriz.com.br> -> <joao@matriz.com.br>, Message-ID: <67917efa9170c57c59fd791eb0e83c47@matriz.com.br>, mail_id: zQYc-U7HehsQ, Hits: -1.326, size: 596, queued_as: 46FAC5A6DC, dkim_new=default:matriz.com.br, 2981 ms

Postfix: Criando regras condicionais

É muito comum termos que criar regras condicionais em nosso MTA, que serão aplicadas a remetentes, destinatários ou domínios específicos. No Postfix isso pode ser feito através da diretiva smtpd_restriction_classes (http://www.postfix.org/RESTRICTION_CLASS_README.html).

Vamos imaginar o seguinte cenário, uma organização possui dois domínios (vamos assumir que sejam matriz.com.br e filial.com.br) e precisa criar regras para que determinados usuários enviem e-mail somente para os domínio internos ou até mesmo um único domínio interno. Iniciamos a configuração criando essas classes no main.cf:

smtpd_restriction_classes = somente_matriz, somente_filial, somente_interno

somente_matriz = check_recipient_access hash:/etc/postfix/condicionais/somente_matriz, reject

somente_filial = check_recipient_access hash:/etc/postfix/condicionais/somente_filial, reject

somente_interno = check_recipient_access hash:/etc/postfix/condicionais/somente_interno, reject

Portanto, com a diretiva smtpd_restriction_classes criamos as três classes e logo abaixo especificamos cada uma delas, sendo que após a verificação do arquivo, há a rejeição explícita.

Para definir a quem se aplica a regra, precisamos criar um arquivo para efetuar essa consulta, e como estamos criando um controle de destinatário, colocar a consulta em smtpd_recipient_restrictions:

check_sender_access hash:/etc/postfix/condicionais/regras_condicionais

Lembrando que esta regra deve vir em primeiro lugar, pois mesmo se o remetente estiver conectando de um host confiável ou autenticado, o bloqueio deve ser aplicado, por exemplo:

smtpd_recipient_restrictions = check_sender_access hash:/etc/postfix/condicionais/regras_condicionais,
permit_mynetworks,
reject_sender_login_mismatch,
permit_sasl_authenticated,
reject_unauth_destination,
reject_unlisted_recipient,
reject_unverified_recipient,
reject

O arquivo regras_condicionais é escrito da desta forma:

fulano@matriz.com.br                  somente_matriz

beltrano@filial.com.br                  somente_filial

sicrano@matriz.com.br               somente_interno

Neste exemplo, temos três usuários onde estamos aplicando classes diferentes, e outros usuários não estarão em nenhuma.

O arquivo somente_matriz fica da seguinte forma:

matriz.com.br OK

O arquivo somente_filial fica da seguinte forma:

filial.com.br OK

O arquivo somente_interno fica da seguinte forma:

matriz.com.br OK

filial.com.br OK

Portanto, para cada classe definimos o domínio de destino seguindo da diretiva OK, informando ao Postfix que deve ser permitido, e como após a consulta do arquivo definimos um reject o envio para domínios fora da regra será negado.

 

Utilizando o amavis para inserir Disclaimer

Olá ! Nos artigos anteriores eu expliquei sobre a inserção de Disclaimer utilizando um filtro externo escrito somente para essa funcionalidade:

https://respirandolinux.wordpress.com/2013/01/10/postfix-adicionando-disclaimer-excecoes-de-remetentes-e-arquivos-diferentes-por-dominio/

https://respirandolinux.wordpress.com/2013/01/05/postfix-adicionando-disclaimer-excecoes-de-remetentes/

https://respirandolinux.wordpress.com/2012/12/18/postfix-adicionando-disclaimer-todas-as-mensagens-enviadas/

Porém, se o Amavis já estiver implementado é possível utilizar o mesmo para inserir as mensagens automáticas, portanto veremos essa implementação neste artigo.

Primeiramente, é necessário instalar o altermime, que continua sendo o programa utilizado para modificar a mensagem,

Após instalar o altermime, vamos iniciar a configuração do Disclaimer, podendo ser feita no arquivo 50-user.conf do Amavis:

### HABILITA INSERÇÃO DISCLAIMER
$defang_maps_by_ccat{+CC_CATCHALL} = [ 'disclaimer' ];

# Programa utilizado para modificar a mensagem
$altermime = '/usr/bin/altermime';

$policy_bank{'MYNETS'} = { # Modificar somente as mensagens geradas internamente
originating => 1,
allow_disclaimers => 1,
};

# Arquivo com o Disclaimer
@altermime_args_disclaimer = qw(--disclaimer=/etc/postfix/disclaimer/_OPTION_.txt);

@disclaimer_options_bysender_maps = ({
#Permite incluir disclaimer baseado no dominio ou usuário

#Os domínios matriz e filial terão disclaimers diferentes
'matriz.com.br' => 'matriz.com.br',
'filial.com.br' => 'filial.com.br',

#O usuario fabio terá um disclaimer pessoal
fabio@matriz.com.br' => 'fabio.matriz.com.br',

#O usuario fulano não terá um disclaimer

fulano@matriz.com.br' => 'empty',

# Disclaimer para ser inserido caso não se encaixe nos critérios acima
'.' => 'default',
},);

Feito isso, basta reiniciar o serviço do Amavis que as mensagens automáticas já serão inseridas, sendo preciso criar os arquivos no diretório apontado em altermime_args_disclaimer.

Postfix: contornando 501 Syntax: HELO hostname

Antes de aplicar essa orientação, leia: https://respirandolinux.wordpress.com/2014/08/25/postfix-contornando-comandos-incorretos-de-conexoes-smtp/

Olá ! Compartilho com vocês como configurar o Postfix para não recusar o HELO  e EHLO com a sintaxe incorreta. As RFCs 821 e 2821 especificam claramente que o HELO e EHLO deve ser seguidos do hostname ou domínio que deseja ser informado. porém é muito comum implementar o SMTP para que diversas aplicações enviem e-mails, e certamente muitas destas não seguirão os padrões.

Em uma dessas implementações, foi observado que diversas aplicações estavam enviando o HELO ou EHLO sem nenhum parâmetro, sendo rejeitado pelo servidor:

220 SMTP
HELO
501 Syntax: HELO hostname

220 SMTP
EHLO
501 Syntax: EHLO hostname

O Postfix já estava configurado para não exigir o HELO/EHLO (smtpd_helo_required = no) e as restrições da etapa HELO (smtpd_helo_restrictions) estavam liberando as aplicações, porém a sintaxe continuava sendo testada e como o HELO/EHLO estava sendo enviado sem nenhum parâmetro, o servidor rejeitava.

Para contornar essa configuração, podemos usar o parâmetro smtpd_noop_commands que permite informar ao Postfix quais comandos passarão a ser aceitos com o código 250 – OK, sobrescrevendo qualquer outra implementação.

Edite o main.cf incluindo a seguinte linha:

smtpd_noop_commands = HELO EHLO

Feito isso, efetue um reload no serviço  do Postfix e os comandos HELO/EHLO sem parâmetro serão aceitos:

220 SMTP
HELO
250 2.0.0 Ok

220 SMTP
EHLO
250 2.0.0 Ok

Roundcube + Spamassassin: Treinando automaticamente o anti spam

Seguindo a série de artigos sobre o Spamassassin e Amavis, apresento agora um complemento (plugin) para o Roundcube que permitirá que o spamassassin “treine”  automaticamente as mensagens após os usuários marcarem como “Spam” ou “Não Spam”.

Eu havia publicado uma configuração para o Dovecot mover as mensagens marcadas como SPAM automaticamente para a pasta desejada : https://respirandolinux.wordpress.com/2013/08/21/dovecot-mover-spam-automaticamente-para-a-pasta-desejada , porém caso ocorra uma falso positivo o usuário não terá como “treinar” o anti-spam para não considerar mais essa mensagem. Como também pode ocorrer de um SPAM não ser identificado e estar chegando na caixa postal do usuário.

Utilizando o Roundcube, é possível utilizar o complemento MARKASJUNK2 para treinar automaticamente o spamassassin, primeiramente efetue o Download no mesmo neste link:

http://www.tehinterweb.co.uk/roundcube/#pimarkasjunk2

Após efetuar o Download, descompacte o mesmo dentro do diretório plugins da sua instalação do Roundcube e edite as seguintes linhas do arquivo config.inc.php:

#Estamos informando para o plugin utilizar comandos como mecanismo para treinar o anti-spam

$rcmail_config[‘markasjunk2_learning_driver’] = ‘cmd_learn’;

#Qual comando deve ser utilizado para identificar a mensagem como spam

$rcmail_config[‘markasjunk2_spam_cmd’] = ‘sa-learn –no-sync –spam –username=amavis %f’;

#Qual comando deve ser utilizado para identificar a mensagem como não-spam (HAM)

$rcmail_config[‘markasjunk2_ham_cmd’] = ‘sa-learn –no-sync –ham –username=amavis %f’

Feito isso, adicione o markasjunk2 aos plugins que serão carregados no Roundcube, no arquivo main.inc.php:

$rcmail_config[‘plugins’] = array(“managesieve”, “markasjunk2”);

Ao carregar o Webmail, serão apresentados os botões SPAM para marcar qualquer mensagem SPAM e o botão NÃO SPAM para marcar mensagens dentro da pasta SPAM do usuário como falso positivo, quando o usuário clicar em uma destas opções o spamassassin será treinado automaticamente.

Abaixo estão as capturas de tela demonstrando a funcionalidade no Roundcube:

Marcar como Não Spam:

Captura de tela de 2013-09-10 15:39:44

Marcar como SPAM:

Captura de tela de 2013-09-10 15:40:04

Dovecot: Mover SPAM automaticamente para a pasta desejada

Quem implementa uma solução anti-spam em seu ambiente, certamente pode desejar mover automaticamente as mensagens marcadas como SPAM  para uma pasta específica do usuário, muitas vezes isto é feito através do Procmail, porém é possível efetuar essa configuração diretamente no Dovecot (Se o estiver utilizando para armazenamento das caixas postais, obviamente), não sendo necessário incluir mais um componente no ambiente.

No Dovecot essa configuração é possível utilizando o serviço SIEVE ( para mais informações: http://wiki.dovecot.org/LDA/Sieve), assumindo que você já o tenha configurado no seu Dovecot, basta modificar a diretiva plugin incluindo a linha abaixo:

plugin {

sieve_global_path = /var/lib/dovecot/default.sieve

}

O script que irá mover as mensagens marcadas como SPAM automaticamente é este, portanto você deve alterar o arquivo configurado no sieve_global_path da seguinte forma:

require [“fileinto”];

# rule:[Move Spam to Junk Folder]
if header :is “X-Spam-Flag” “YES”
{
fileinto “Spam”;
stop;
}

Caso deseje mover para uma outra pasta, como Junk que é muito utilizada, basta substituir o nome da pasta após o fileinto.

Postfix: Copiar mensagens de remetentes ou destinatários específicos

Olá ! Quem trabalha com qualquer MTA conhece o recurso de copiar as mensagens que passam pelo servidor para um destinatário específico. No Postfix isso é feito com o parâmetro always_bcc, porém as vezes precisamos auditar somente o que alguns usuários  enviam ou recebem. Para isso, temos os parâmetros recipient_bcc_maps e sender_bcc_maps, onde podemos especificar usuários que terão suas mensagens recebidas ou enviadas, respectivamente, copiadas.

Vejamos um exemplo desta implementação:

Edite o arquivo main.cf da seguinte forma:

recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
sender_bcc_maps = hash:/etc/postfix/sender_bcc

No arquivo recipient_bcc nós colocamos os usuários que queremos que suas mensagens recebidas serão copiadas, e no arquivo sender_bcc, a mesma lógica para as mensagens enviadas. Vamos supor que queiramos copiar todas as mensagens enviadas por fabio@teste.com.br e todas as mensagens recebidas pelo usuario@teste.com.br para o auditor@teste.com.br:

/etc/postfix/recipient_bcc:

usuario@teste.com.br              auditor@teste.com.br

/etc/postfix/sender_bcc

fabio@teste.com.br                 auditor@teste.com.br

 

Após efetuar a configuração no main.cf e criar os arquivos, basta executar o postmap nos mesmos e efetuar o reload no serviço do Postfix.

Spamassassin e PostgreSQL: sintaxe de entrada é inválida para tipo bytea

Continuando com a série de artigos sobre Amavis e Spamassassin, segue uma dica para quem está integrando o Spamassassin ao PostgreSQL. Após efetuar as configurações observei que não estava sendo possível gravas as mensagens como Spam ou Ham na tabela bayes do Spamassassin, no PostgreSQL era apresentado o seguinte erro:

sintaxe de entrada é inválida para tipo bytea

Isso se devia por estar utilizando a função genérica SQL para o plugin BayesStore:

Mail::SpamAssassin::BayesStore::SQL

Para corrigir, basta alterar a função para a própria do Postgres:

Mail::SpamAssassin::BayesStore::PgSQL