Quem gerencia servidores de e-mail com cPanel e Exim já deve ter presenciado um acúmulo repentino na fila com centenas ou milhares de mensagens com status frozen (congeladas). Quando isso acontece, o disco começa a sofrer com excesso de operações de leitura e escrita (I/O wait), e os e-mails legítimos acabam demorando muito mais para serem despachados.
O estado congelado não é uma pane no software: ele funciona como um disjuntor de segurança do próprio Exim para evitar que o servidor desperdice processador e rede tentando entregar repetidamente mensagens que violaram regras rígidas ou sofreram erros irrecuperáveis.
Neste artigo, vamos entender como o Exim estrutura os arquivos no diretório de spool, o que significa um bloqueio por frozen by ACL, por que anexos grandes causam falhas silenciosas e como diagnosticar e limpar o ambiente com comandos rápidos no terminal.
1. A Estrutura Física do Spool do Exim e Interações com o Kernel#
Para entender por que as mensagens congelam, vale a pena olhar como o Exim grava dados em /var/spool/exim/input/.
Como o Exim divide uma mensagem no disco#
Cada mensagem que entra na fila é separada em pelo menos dois arquivos distintos:
- Arquivo de cabeçalho (
-H): guarda os metadados do envelope (remetente real, destinatários, carimbos de tempo, cifras TLS e identificador de status). É aqui que fica gravada a flag lógica de congelamento. - Arquivo de dados (
-D): contém o corpo do e-mail e os anexos codificados (normalmente em Base64).
Essa separação permite que o Exim leia apenas os arquivos -H durante a inspeção de fila (exim -bp), economizando memória e evitando ler corpos pesados de e-mails desnecessariamente.
O mecanismo de travas e a flag frozen#
Quando o serviço inicia uma tentativa de entrega:
- O Exim abre o arquivo com
openat()e tenta aplicar uma trava exclusiva comflock(fd, LOCK_EX | LOCK_NB). Se outro processo filho já estiver cuidando daquela mensagem, a chamada retornaEWOULDBLOCKe o Exim passa para o próximo item, evitando entregas duplicadas. - Quando uma regra de segurança é violada ou o destino recusa a mensagem de forma definitiva, o Exim grava a marcação
-frozendiretamente no arquivo de cabeçalho (-H). A partir desse instante, as varreduras normais de fila passam a ignorar esse e-mail.
O ciclo de vida e impacto de uma mensagem congelada#
Uma mensagem entra em estado congelado (frozen) quando o servidor não consegue entregar a mensagem original e também falha ao tentar notificar o remetente:
- Tentativa inicial e falha: o Exim tenta entregar um e-mail (por exemplo, um relatório de cron disparado por
rootpara um endereço externo). O servidor de destino rejeita a entrega com um erro permanente (código 5xx) ou atinge o limite de tentativas temporárias (código 4xx). - Geração da mensagem de retorno (bounce): conforme o padrão SMTP, o servidor cria uma notificação de falha. Para evitar loops infinitos de notificações entre servidores, o remetente desse aviso é gravado como nulo:
<>. - Falha na entrega do bounce: o Exim tenta devolver a notificação para quem gerou o e-mail (
[email protected]). Se o alias em/etc/aliasesnão existir, a caixa postal local estiver lotada ou o domínio não resolver internamente, o aviso também não pode ser entregue. - Congelamento: como a mensagem original não pôde ser entregue e o aviso de erro também falhou, o Exim ativa a função interna
deliver_freeze(). O arquivo de cabeçalho da mensagem no disco ganha a marca de congelado, e o daemon para de tentar enviá-la nas varreduras normais de fila (exim -q).
Quando milhares de mensagens congeladas se acumulam por semanas, o diretório /var/spool/exim/input/ fica sobrecarregado. O número de inodes diminui e comandos comuns de checagem começam a demorar segundos ou minutos, elevando o uso de CPU em modo de espera de disco (I/O wait).
2. Rastreamento e Análise Forense da Fila pelo Terminal#
Identificando domínios com maior retenção#
Para ter um resumo estatístico rápido de quais destinos estão acumulando volume:
exim -bp | exiqsumm | sort -n | tail -n 20
O comando exim -bp lista o estado atual de todas as mensagens no spool, o exiqsumm agrupa os totais por domínio e o tail destaca os 20 maiores acumuladores.
Isolando identificadores de mensagens#
Quando você identifica um domínio suspeito (domain.com), use o exiqgrep para listar apenas os IDs das mensagens retidas:
exiqgrep -r "@domain\.com$" -i
A flag -i emite apenas o identificador da mensagem (por exemplo, 1wF7Aa-00000009iej-1s3H), facilitando o envio para outros comandos via pipe ou xargs.
Lendo metadados e histórico completo#
Com o ID em mãos, consulte o histórico de eventos e os cabeçalhos salvos no spool:
# Ver a linha do tempo completa da mensagem
exim -Mvl 1wF7Aa-00000009iej-1s3H
# Inspecionar os cabeçalhos brutos salvos no arquivo -H
exim -Mvh 1wF7Aa-00000009iej-1s3H
Estudo de caso 1: falhas de autenticação e ataques de dicionário: ataques de backscatter e a flag frozen by ACL#
Um dos logs mais comuns em servidores com mensagens congeladas é este:
2026-04-21 06:13:30 Received from [email protected] H=(noreply.spamdome.com) [34.82.177.3] P=esmtps X=TLS1.3:TLS_AES_256_GCM_SHA384:256 S=3207 [email protected] T="\351\205\215\351\200\201\347\212\266\346\263\201\343\201\256\343\201\224\346\241\210\345\206\205"
2026-04-21 06:13:30 frozen by ACL
O que está acontecendo aqui#
- Remetente forjado: o remetente utiliza uma estrutura que simula retorno de erro para tentar forçar o seu servidor a enviar um aviso de falha (bounce) para uma vítima externa.
- Assunto codificado: a sequência de escape octal
\351\205\215...no campoT=representa caracteres orientais (neste exemplo, uma notificação falsa de entrega de mercadoria em japonês). - Decisão da ACL: a mensagem passou pela checagem de conexão inicial, mas atingiu a pontuação máxima nas regras de antispam durante a fase de dados (
acl_smtp_data). Quando a diretiva no Exim está configurada para congelar em vez de rejeitar imediatamente (deny), o arquivo é retido no spool para conferência manual.
Dica operacional: se o seu servidor recebe muito spam com essa característica, vale a pena alterar a política das ACLs de antispam no cPanel de Freeze para Deny (550), evitando que lixo eletrônico consuma inodes em disco.
Estudo de caso 2: mensagens volumosas e esgotamento de storage: mensagens volumosas e esgotamento de storage#
Quando uma única mensagem aparece retendo 15 MB ou mais no spool e permanece presa por horas, dois fatores costumam estar em jogo:
Limites de tamanho no destino (message_size_limit)#
No /etc/exim.conf, existe a diretiva message_size_limit. Se o seu servidor permite envios de até 50 MB, mas o servidor do destinatário aceita no máximo 10 MB, o diálogo SMTP falha:
- O destino anuncia no banner
250-SIZE 10485760. - Se o Exim tentar empurrar o payload maior, o servidor remoto rejeita com
552 Message size exceeds fixed maximum message size. Dependendo do código retornado e de falhas secundárias na notificação de erro, a mensagem pode acabar congelada.
A expansão do base64 e cotas locais#
Arquivos anexados a e-mails precisam ser codificados em texto ASCII de 7 bits via Base64. Essa conversão adiciona um acréscimo fixo de aproximadamente 33% ao tamanho original:
- Um anexo de 16 MB se transforma em mais de 21 MB em disco e em trânsito.
- Se a entrega for local e a caixa postal do destinatário estiver próxima do limite de cota, o agente de entrega local (
dovecot_lda) falha ao gravar a mensagem com erroEDQUOT(Quota exceeded). O Exim então congela o item para não perder o e-mail do cliente.
Inspecionando o conteúdo antes de purgar#
Antes de deletar itens da fila, inspecione algumas mensagens para identificar se o disparo veio de scripts legítimos ou de invasões em sites hospedados:
# Ver os cabecalhos completos da mensagem
exim -Mvh 1wG0DU-00000004C5t-42tQ
# Ver o corpo do e-mail
exim -Mvb 1wG0DU-00000004C5t-42tQ
# Ver o log individual de tentativas dessa mensagem
exim -Mvl 1wG0DU-00000004C5t-42tQ
Nos cabeçalhos (exim -Mvh), procure pela linha injetada pelo PHP:
X-PHP-Originating-Script: 1001:envio.php
O número antes dos dois pontos é o UID do usuário no Linux. Com esse identificador, você descobre em qual pasta /home/usuario/public_html o script disparador reside.
3. Depuração de Baixo Nível com strace e Gargalos de I/O#
Se o log do Exim não deixar claro por que uma mensagem não avança, você pode acompanhar as chamadas de sistema forçando a entrega monitorada:
strace -f -s 256 -e trace=network,openat,write,flock exim -M 1wF7Aa-00000009iej-1s3H
-f: essencial para acompanhar os processos filhos que realizam a conexão SMTP remota.-s 256: exibe o texto dos comandos SMTP nas chamadas de rede.-e trace=network,openat,write,flock: isola as operações de rede, travas e escrita em disco.
Dois gargalos comuns revelados pelo strace#
- Black hole de MTU (Path MTU Discovery): se o Exim conclui o handshake TCP, envia o comando
DATA, mas congela indefinidamente em chamadaswrite()com blocos grandes de Base64 sem nunca receber retorno emread(), algum roteador no caminho está descartando pacotes grandes com o bit Don't Fragment (DF) ativo. - Esgotamento de inodes no disco: se o comando
df -hmostra espaço livre, mas odf -iacusa 100% de uso de inodes na partição/var, chamadasopenat()para criar novos cabeçalhos falham comENOSPC. O Exim entra em colapso e congela mensagens em cascata.
Rastreando falhas de entrega de mensagem específica com strace#
Se uma mensagem específica insiste em travar e você precisa ver onde a conexão morre (seja em consulta DNS ou falha de socket):
strace -f -tt -s 512 -e trace=openat,write,connect,unlink exim -M 1wG0DU-00000004C5t-42tQ
A flag -f acompanha processos filhos e -e trace=connect mostra o IP e a porta de rede exatos onde o Exim tentou se conectar antes de falhar.
4. Procedimentos Cirúrgicos: Descongelamento, Retentativas e Purga em Massa#
Purgando mensagens congeladas de um domínio específico (SPAM)#
Para remover do spool todas as mensagens congeladas associadas a um domínio fraudulento:
exiqgrep -r "@domain\.com$" -i | xargs -I {} exim -Mrm {}
O comando exim -Mrm remove fisicamente os arquivos -H e -D do disco e limpa os registros correspondentes no banco de retentativas (retry.db).
Descongelando e forçando entrega de e-mails legítimos#
Se a causa da retenção (como uma falha de DNS externa) foi resolvida e as mensagens legítimas precisam ser entregues:
# 1. Descongelar as mensagens (Thaw)
exiqgrep -r "@domain\.com$" -i | xargs -I {} exim -Mt {}
# 2. Forçar a tentativa imediata de entrega
exiqgrep -r "@domain\.com$" -i | xargs -I {} exim -M {}
Purgando mensagens congeladas em massa#
Se você já conferiu a fila e precisa remover todas as mensagens congeladas de uma só vez sem derrubar o serviço do Exim:
exiqgrep -z -i | xargs exim -Mrm
Entendendo a cadeia de comandos:
exiqgrep -z -i: localiza apenas as mensagens congeladas (-z) e imprime estritamente os identificadores (Message-IDs,-i), um por linha.| xargs: repassa os identificadores em lotes eficientes para o comando seguinte, aproveitando a memória em vez de criar um novo processo para cada mensagem.exim -Mrm: remove os arquivos-He-Dcorrespondentes do spool do disco.
5. Conectividade remota do MySQL sob CloudLinux e CageFS#
Liberar o MySQL para conexões externas em servidores cPanel com CloudLinux exige ajustes tanto na escuta de rede quanto na camada de isolamento do CageFS.
1. Liberando a escuta do MySQL na rede#
Por padrão, o MySQL atende apenas em 127.0.0.1. Para permitir conexões vindas da rede externa, edite o /etc/my.cnf:
[mysqld]
bind-address = 0.0.0.0
skip-name-resolve = 1
bind-address = 0.0.0.0: faz o MySQL escutar em todas as interfaces de rede ativas.skip-name-resolve = 1: essencial para desempenho. Impede que o MySQL tente fazer resolução reversa de DNS para cada IP que conecta. Sem essa diretiva, qualquer lentidão no DNS externo trava a criação de threads e lota o limite de conexões (max_connections).
Reinicie o banco de dados e confirme a porta aberta:
/scripts/restartsrv_mysql
ss -tulpn | grep 3306
2. Mapeamento de sockets e esqueleto no CageFS#
O CloudLinux isola cada usuário cPanel dentro de um ambiente virtualizado (o CageFS). Quando usuários locais rodam scripts no terminal ou em cron jobs que conversam com o MySQL, eles precisam acessar o socket do banco dentro de suas jaulas.
Verifique se o socket do MySQL está listado nos pontos de montagem do CageFS em /etc/cagefs/cagefs.mp:
/var/lib/mysql/mysql.sock
/var/run/mysqld/mysqld.sock
Se bibliotecas de cliente ou binários do banco tiverem sido atualizados recentemente no sistema principal, force a sincronização das jaulas dos usuários:
cagefsctl --addrpm MariaDB-client
cagefsctl --force-update
A flag --force-update remonta o esqueleto do CageFS em /usr/share/cagefs-skeleton/, garantindo que todas as contas tenham acesso às bibliotecas compartilhadas corretas.
3. Monitoramento de limites com o MySQL governor#
O CloudLinux possui um módulo chamado MySQL Governor que monitora o consumo de CPU e I/O de disco de cada conta em tempo real.
Se uma aplicação externa começar a rodar consultas lentas sem índices, o MySQL Governor reduz a prioridade do usuário para evitar que ele derrube o servidor.
Para checar se um usuário está sofrendo restrições:
dbctl list | grep usuario
Se o usuário estiver marcado como throttled, suas consultas remotas vão demorar para responder, dando a impressão de falha de conexão.
6. Problemas comuns e armadilhas de rede (CSF/LFD)#
Bloqueio por excesso de conexões no CSF (PORTFLOOD)#
Se a porta 3306 estiver liberada no firewall, mas o cliente externo relatar quedas constantes, verifique a diretiva PORTFLOOD no /etc/csf/csf.conf:
PORTFLOOD = "3306;tcp;5;10"
Se essa regra estiver ativa, qualquer aplicativo que abrir mais de 5 conexões em 10 segundos terá o IP bloqueado temporariamente.
Para evitar isso em integrações legítimas, adicione o IP do cliente diretamente na lista de permissões permanentes:
csf -a IP_DO_CLIENTE "Acesso remoto ao banco"
csf -r
Erro de plugin de autenticação (caching_sha2_password)#
Se clientes antigos ou bibliotecas legadas de PHP tentarem conectar no MySQL 8 e devolverem o erro Authentication plugin 'caching_sha2_password' cannot be loaded, ajuste o método de autenticação do usuário para o padrão anterior:
ALTER USER 'usuario'@'IP_DO_CLIENTE' IDENTIFIED WITH mysql_native_password BY 'SuaSenhaForte';
FLUSH PRIVILEGES;
Limite de descritores de arquivo no kernel (limitnofile)#
Quando muitas conexões remotas simultâneas são abertas, o MySQL pode acusar erro de Too many open files ou Can't create a new thread.
Confira o limite atual do processo:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files"
Se o limite for baixo, aumente nas configurações do systemd criando /etc/systemd/system/mysqld.service.d/override.conf:
[Service]
LimitNOFILE=65535
Depois aplique e reinicie:
systemctl daemon-reload
/scripts/restartsrv_mysql
7. Checklist de Validação e Matriz Operacional#
Matriz rápida de diagnóstico para problemas de spool#
| Sintoma | Causa mais provável | Verificação rápida | Resolução | |
Para ter certeza de que ambos os serviços estão operando em harmonia:
- Fila do Exim limpa: rode
exim -bpce confirme que a contagem total de mensagens caiu para níveis saudáveis (geralmente abaixo de algumas dezenas). - Porta 3306 acessível externamente: teste a partir de uma máquina remota usando
nc -zv IP_DO_SERVIDOR 3306. - CageFS atualizado: rode
cagefsctl --validatepara certificar que nenhum ponto de montagem do MySQL ficou quebrado. - Logs limpos: monitore
/var/log/exim_mainloge/var/log/messagespor alguns minutos para garantir que nenhuma mensagem volte a congelar sem motivo.
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