Diário de infra: domando gateways antispam, falhas de SPF e filtros em Bash#
Quem trabalha com infraestrutura de larga escala sabe que o fluxo de e-mails é uma das engrenagens mais sensíveis e frustrantes de se manter rodando em estado de arte. Há dias em que você precisa atuar em múltiplas camadas do modelo OSI: desde lidar com um servidor legado que não suporta um simples rsync de contas (onde a única saída é caçar e matar os PIDs na unha para não travar o I/O do disco), até debugar lógicas complexas de roteamento e scripts shell que pregam peças no momento da auditoria.
Recentemente, enfrentei um incidente crítico de entrega envolvendo gateways externos e resolvi documentar aqui o rastro técnico (packet pathing), a diferenciação forense entre políticas de SPF e a evolução de uma ferramenta de automação em Bash para auditoria de zonas DNS.
O diagnóstico inicial e dicas multi-painel#
Antes de mergulhar na regra de SPF, é vital garantir que a infraestrutura local está saudável. Se você estiver lidando com um ambiente cPanel, a primeira ação para isolar problemas de permissão (UID/GID) em caixas de e-mail é rodar o script nativo:
# Corrigindo permissões de mail em nível de root no cPanel
/scripts/mailperm --verbose
Nota: Esse comando varre o servidor corrigindo ownership e permissões de pastas críticas como mail/ e etc/. Se fosse para um usuário específico, eu usaria --login=nome_do_usuario.
No cenário que resolvi hoje, em um ambiente DirectAdmin, o problema era uma rejeição na borda (edge rejection). Criei uma conta de teste ([email protected]) e monitorei os logs em tempo real para captar o erro exato:
O fluxo observado foi: o SpamExperts entregava a mensagem no nosso servidor de destino (identificado internamente como DEST-10, IP 192.168.x.x), onde a conexão era sumariamente dropada com o erro:
rejected RCPT <[email protected]>: SPF: [IP_DO_GATEWAY] is not allowed to send mail from domain.com
O antispam como o "falso negativo"#
O comportamento era inconsistente: mensagens vindas de endereços @domain.com através de um gateway do SpamExperts eram sumariamente rejeitadas por falha de SPF, enquanto as do @domain.com, passando pelo exato mesmo fluxo, eram entregues.
Análise forense: por que o Gmail passava e o hotmail não?#
A resposta reside na diferenciação técnica entre as terminações de registro TXT de SPF (RFC 7208):
- O Hotmail utiliza Hard Fail (
-all): A política deles instrui o receptor: "Se o IP de conexão não estiver nesta whitelist explícita, rejeite a conexão imediatamente". Como o SpamExperts servia de ponte, o IP de conexão visto pelo meu servidor era o do gateway, não do IP de origem do Hotmail. O Exim obedeceu ao RFC e dropou o pacote. - O Gmail utiliza Soft Fail (
~all): A diretiva diz: "Se o IP não estiver na lista, a mensagem é suspeita, mas aceite-a para análise posterior". Meu servidor aceitou a conexão e, como a mensagem continha uma assinatura DKIM válida (d=domain.com) e o filtro era um roteador confiável, o sistema de reputação permitiu a entrega.
A solução definiva: whitelist de IPs confiáveis (trusted SMTP IPs)#
O objetivo não é relaxar o SPF (o que abriria brecha para spoofing), mas sim informar ao MTA (Exim) que o SpamExperts é uma ponte de confiança. O fluxo Remetente -> Filtro -> Destino precisa ser validado internamente.
No ecossistema do DirectAdmin, o arquivo responsável por adicionar blocos de IPs e informar ao servidor que aqueles remetentes são confiáveis é o:
/etc/virtual/whitelist_hosts_ip
Neste arquivo, já rastreamos cerca de 73 entradas de blocos e IPs avulsos, mas o provedor do filtro (N-able/SpamExperts) havia atualizado sua infraestrutura global, tornando nossa lista local obsoleta para os novos clusters de entrega.
Fui até a documentação oficial da N-able para buscar a lista pública de IPs de entrega atualizada deles (ex: X.X.X.0/24) e os adicionei ao arquivo de exceções. Após salvar, reiniciei o Exim:
systemctl restart exim
# Ou service exim restart
A batalha do Bash: auditando registros MX em massa#
Durante este incidente, surgiu a necessidade de auditar centenas de domínios em um arquivo zonas.txt para identificar quais ainda utilizavam MX locais ou externos que não apontavam para o SpamExperts.
Aqui, o script passou por uma evolução técnica necessária para evitar falsos positivos "fantasmas":
Iteração 1: O erro de expansão#
Comecei com um one-liner simples: for i in 'cat zonas.txt'; do echo 'consultando $i' && grep MX /var/named/$i.db | head -1; done. Falha: O uso de aspas simples impediu a expansão da variável $i. O shell tentou ler o arquivo literalmente como $i.db.
Iteração 2: Alinhamento e variáveis vazias#
Tentei usar printf para gerar um relatório em colunas, mas quando um domínio possuía o registro filtrado pelo grep -v, o script gerava linhas quebradas. Precisei adicionar um gatekeeper: if [ -n "$mx" ].
Iteração 3: O falso positivo do DKIM#
O script subitamente retornou chaves públicas de registros TXT dentro da consulta de MX. Exemplo: p=MIIBIjAN.... Causa: A string base64 da chave DKIM continha a sequência "MX" colada em outros caracteres. Como usei um grep genérico, ele capturou a linha TXT acidentalmente.
O script final "blindado"#
Usei o parâmetro -w para buscar a palavra exata (word-regexp) e o awk para extrair apenas a última coluna (o hostname do MX):
#!/bin/bash
# Auditoria Forense de Registros MX
for i in $(cat zonas.txt); do
# Filtra SpamExperts e MX padrão local, pegando apenas o endpoint final
mx=$(grep -w "MX" /var/named/$i.db | egrep -v "spamexperts.com|mail.|$i" | head -1 | awk '{print $NF}')
if [ -n "$mx" ]; then
# Formatação em colunas para relatório limpo e alinhado
printf "%-35s | %s\n" "$i" "$mx"
fi
done
Considerações práticas#
Gerenciar infraestrutura é uma tarefa de vigilância constante entre o macro (DNS/SPF global) e o micro (bash scripts e regex). A lição fundamental é que o SPF Hard Fail (-all) exige um mapeamento cirúrgico de todos os nós de relay. Mantenha suas listas de whitelist atualizadas e suas ferramentas de auditoria blindadas contra ruídos estatísticos em chaves criptográficas.
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários