E aí? Recebendo muitos emails no seu novo servidor? Tá feliz?

Chegamos no final dessa série gigante. Com o nosso servidor em produção, não há muito mais o que fazer a não ser assisti-lo funcionar. As exceções vão para as as tarefas administrativas que cuidarão da saúde do nosso intrépido servidor de email e agendas. Essas tarefas são simples, porém devem ser feitas em períodos regulares que eu vou deixar por sua conta definir de quanto em quanto tempo elas serão executadas. O uso do servidor vai determinar naturalmente essa necessidade.

Então, vejamos quais tarefas são essas.

Basicão

As tarefas mais básicas são relativas ao estado geral de operação do servidor. Verificar o espaço em disco, os processos em execução, carga de processamento, essas coisas.

Existem milhares de ferramentas para fazer isso, seja manualmente, seja de moto automatizado através de uma monitoração.

Manualmente, as coisas se resolvem do modo mais simples possível. Os comandos mais usados serão os que já existem no sistema, tipo ssh, df, top, iotop, netstat, ss, tail etc.

Há outras ferramentas bastantes úteis mas que não vêm instaladas com o sistema. Isso pode ser facilmente resolvido com um sbopkg -i <ferramenta>. As que mais uso são htop, nmon, multitail. Esses dias chegou ao meu conhecimento através de uma dica do Elcio uma outra ferramentinha que parece muito legal para ver a saúde geral do servidor: o glances. Ainda não instalei para usar regularmente, mas em breve o farei.

Para a monitoração remota, eu costumo separar em duas classes: em tempo real ou histórica.

Para a monitoração de logs em tempo real, eu passei a usar não tem muito tempo um aplicativo em node.js que evita que você tenha que abrir uma seção SSH só para olhar logs. Essa ferramenta é o log.io. Ele não te dá acesso aos logs históricos, mas você conseguirá ver e pesquisar em todos os logs que quiser em tempo real a partir do momento que conectar na funcional interface web do log.io. Super mão na roda para administração cotidiana.

Para a monitoração de carga em tempo real, costumo usar uma solução ridiculamente simples e funcional que faz parte do KDE, o KSysGuard. Para o administrador desatento, ele monitora apenas o uso de recursos em tempo real da sua máquina local. Mas não se engane! Ele pode fazer isso em máquinas remotas também, e faz isso muito bem.

Para usar o KSysGuard para monitorar um servidor remoto você precisa instalar o utilitário ksysguardd nos servidores monitorados. Esse utilitário não possui um pacote separado no Slackware, mas você pode extraí-lo do pacote kde-workspace e colocá-lo em /usr/bin/ksysguard. A única biblioteca da qual ele necessita é a libc, que já vem em qualquer Linux, e você não precisa instalar mais nada do KDE. É só instalar o executável do ksysguardd no servidor, abrir o KSysGuard local, conectar ao servidor e configurar os sensores que você quer monitorar.

Já para fazer uma monitoração histórica dos principais recursos do seu servidor, como uso da CPU, memória, espaço em disco e swap, você pode usar o CloudWatch do próprio AWS. Você terá que instalar e configurar o CloudWatch Monitoring Scripts for Linux. Uma vez instalado e configurado, você pode implementar a monitoração no cron deste modo:

#
# AWS CloudWatch resource monitoring
*/5 * * * * /opt/aws-scripts-mon/mon-put-instance-data.pl --aws-credential-file=/root/.awscreds --mem-util --mem-used --mem-avail --swap-util --swap-used --disk-path=/ --disk-path=/var/spool/mail/vmail --disk-space-util --disk-space-used --disk-space-avail --from-cron

Esse comando vai rodar o script de monitoração a cada cinco minutos para obter os dados monitorados e enviar para o CloudWatch. No console do CloudWatch você poderá ver os dados históricos do jeito que quiser.

O mais interessante dessa abordagem é que você pode configurar o CloudWatch para enviar alarmes em determinadas ocasiões, tipo um processamento alto por um determinado período de tempo, pouca memória disponível ou um disco quase cheio.

Fique a vontade para usar o seu próprio arsenal para administração e monitoração, só não deixe de fazê-los. Tudo o que falei acima são apenas sugestões baseadas em minhas próprias necessidades. Dificilmente elas serão próximas das suas.

Ensinando o SpamAssassim

Como já vimos anteriormente, o SpamAssassin é inteligente. Ele tem a real capacidade de aprender a identificar o que é ou não spam com mais precisão se for devidamente treinado para isso.

Antes de continuar, recomendo muito que você leia o manual do sa-learn (ou man sa-learn), especificamente as seções 'GETTING STARTED' e 'EFFECTIVE TRAINING', e o FAQ do Bayes . Há um outro artigo do SpamAssassin específico sobre como melhorar a precisão das análises feitas por ele, o que também é uma boa leitura

O aprendizado do SpamAsssasin é constante. Para treiná-lo de modo efetivo precisamos fazer umas coisinhas. A primeira delas é separar o joio do trigo. Usando o seu cliente de email, separe as mensagens que chegarem desta forma:

  • Pasta do Professor: crie uma pasta chamada Professor e dentro dela crie duas pastas, Boas e Ruins.
  • Mensagens que SÃO spam: mova (não copie) para a pasta Professor/Ruins todas as mensagens que você recebe e sabe que são spam mas que o SpamAssassin não reconheceu como tal, e por isso foram parar na sua caixa de entrada (INBOX).
  • Mensagens que NÃO SÃO spam: copie (não mova) as mensagens recebidas que você sabe que não são spam para a pasta Professor/Boas.
  • Amostras equivalentes: colete o mesmo número de mensagens que são e não são spam antes de executar o treinamento. Se é para haver alguma diferença, o número de não spam deve superar o de spam, e não o contrário.
  • Colete, depois treine: comece o treinamento quando houverem pelo menos 1.0000 mensagens de cada tipo. Quando mais, melhor, mas há um limite: entre 1.000 e 5.000 mensagens é mais efetivo, acima de 5.000 mensagens não há qualquer benefício adicional ao treinamento.
  • Datas equivalentes: não misture mensagens de spam antigas com mensagens não spam novas, ou vice-versa. Mantenha o mesmo período de amostragem para ambas as pilhas de mensagens.
  • Renove: de tempos em tempos apague as mensagens antigas em cada pasta para que a inteligência do SpamAssassin evolua.
  • Não recicle: não use as mensagens na pasta Spam para ensinar o SA. Essas ele já sabe que são spam e por isso estão nessa pasta.

Depois de separadas as mensagens e conectado via SSH ao servidor, rode o 'professor' do SpamAssassin deste modo.

  1. Para as mensagens que SÃO spam (Professor/Ruins):
# sa-learn --progress --spam /var/mail/vmail/exemplo.com.br/eumesmo/Professor/Ruins/{cur,new}
  1. Para as mensagens que NÃO SÃO spam (Professor/Boas):
# sa-learn --progress --ham /var/mail/vmail/exemplo.com.br/eumesmo/Professor/Boas/{cur,new}
  1. Sincronize o banco de dados do SpamAssassin
# sa-learn --sync

Esse processo vai ensinar ao SpamAssassin o que ele deve acolher e o que ele deve assassinar. Faça isso com regularidade, pois o aprendizado passa por um processo natural de expiração para que o banco de dados não consuma todo o seu disco. Dica: crie uns aliases para rodar esse comandos mais facilmente.

Note que você só está usando os emails que você recebe para ensiná-lo. Você pode fazer isso com as mensagens de outros usuários apenas trocando os caminhos. Mas como eles não saberão (ou não vão querer) separar as mensagens com o esmero necessário, você corre o risco de ensinar errado o SpamAssassin. Lembre-se que na configuração que fizemos para o SpamAssassin dissemos que a base da inteligência dele é global. Logo, o que você ensinar com as suas mensagens valerá para todos os usuários. Melhor confiar só em você para isso, né?

Depois que você estiver habituado com o processo de treinamento do SpamAssassin, talvez queira automatizar esse processo. Para isso, crie o arquivo /etc/cron.daily/sa-learn com o conteúdo abaixo.

#!/bin/sh

# Teach SA what is ham
sa-learn --ham /var/mail/vmail/exemplo.com.br/eumesmo/Professor/Boas/{cur,new} > /dev/null 2>&1

# Teach SA what is spam
sa-learn --spam /var/mail/vmail/exemplo.com.br/eumesmo/Professor/Ruins/{cur,new} > /dev/null 2>&1

# Sync SA database
sa-learn --sync > /dev/null 2>&1

Torne-o executável com:

# chmod 755 /etc/cron.daily/sa-learn

Ao fazer isso, o treinamento ocorrerá todos os dias automaticamente. Só não coloque mensagens erradas nas pastas do treinamento, senão você vai ensinar errado o SpamAssassin. Se isso acontecer, você pode começar tudo do zero com apenas um comando:

# rm -rf /var/lib/spamassassin/.spamassassin/bayes_*

Um outro detalhe sobre a inteligência do SA: ela é capaz de aprender sozinha. Isso é útil, mas você não deve confiar só nesse aspecto autodidata. Continue ensinado-a.

Você pode conferir quando o SA aprendeu ou não sozinho com uma mensagem olhando o cabeçalho X-Spam-Status dos seus emails. Esse cabeçalho se parece com isso:

X-Spam-Status: No, score=0.8 required=3.0 tests=BAYES_05,
  FILL_THIS_FORM_FRAUD_PHISH,RDNS_DYNAMIC,SPF_HELO_PASS,T_FILL_THIS_FORM_SHORT
  shortcircuit=no autolearn=no autolearn_force=no version=3.4.0

Veja o valor da propriedade autolearn. Se for no como no exemplo acima, o SA não usou a mensagem para aprender nada. Se for spam ele aprendeu que a mensagem é spam. Por fim, ham indica que a mensagem foi aprendida como não spam.

Para ver a quantas anda a inteligência do seu SpamAssassin, use o comandinho abaixo. Na saída dele, nspam é a quantidade de mensagens identificadas como spam, nham as mensagens que não são spam e ntokens é a quantidade de tokens aprendidos pela análise das mensagens. Esses valores incluem o que foi ensinado e o que foi aprendido sozinho.

# sa-learn --dump magic
...
0.000          0       2062          0  non-token data: nspam
0.000          0       2062          0  non-token data: nham
0.000          0      25871          0  non-token data: ntokens
...

Só isso! 'Mas e o backup?', você pergunta. E fico feliz que você tenha perguntado. Eu não consigo imaginar um servidor de email sem backup! Aliás, eu não consigo imaginar nem o meu telefone sem backup, imagina um servidor, seja lá o que ele faz!

Fico tão feliz com a sua preocupação que vou te ensinar um método jóia e baratinho de fazer backup.

Backup

Usamos o AWS. Storage é barato lá. No S3 então, ridiculamente barato. Por que não usá-lo para nossos backups?

Para usar o AWS S3 como o destino de backups dos seus servidores, você vai precisar do S3cmd, um aplicativozinho CLI que faz o trâmite de transferências de arquivos de e para o S3. Ele é simplezinho e bastante funcional, tem tudo que precisamos para fazer nossos backups.

Instalá-lo requer apenas um sbopkg -i s3cmd. Configurá-lo é um pouquinho mais complicado, mas a documentação dele vai te ajudar.

Com o S3cmd instalado e configurado e um bucket no S3 para os seus backups, crie o arquivo /usr/local/bin/s3bkp com o conteúdo abaixo. Assim como o outro script, esse também está no gist, junto com o arquivo de configuração.

#!/bin/sh
#title           :s3bkp
#description     :Backup selected databases and files to Amazon S3.
#author          :Deny Dias (deny [at] macpress [dot] com [dot] br)
#date            :2015.03.09
#version         :0.2
#usage           :Put this script in /usr/local/bin, chmod +x, run in cron.
#                 It requires s3cmd, an account with key and policies set and
#                 a S3 bucket in place.
#license         :CC0
#==============================================================================

set -e

# Set runtime paths
RUNPATH=$( dirname "$0" )
RUNPATH=$( cd "$RUNPATH" && pwd )

# Execution time accounting
# Start timestamp
res1=$(date +%s)
# End timestamp and print total execution time
endexec () {
  res2=$(date +%s)
  dt=$(echo "$res2 - $res1" | bc)
  dd=$(echo "$dt/86400" | bc)
  dt2=$(echo "$dt-86400*$dd" | bc)
  dh=$(echo "$dt2/3600" | bc)
  dt3=$(echo "$dt2-3600*$dh" | bc)
  dm=$(echo "$dt3/60" | bc)
  ds=$(echo "$dt3-60*$dm" | bc)
  printf "[`date -Iseconds`] Total runtime: %d:%02d:%02d:%02d\n" $dd $dh $dm $ds
}

# Check for root
isroot () {
  if [ $EUID -ne 0 ]; then
    echo "[`date -Iseconds`] This script must run as root."
    exit 1
  fi
}

# Import defaults
loaddefaults () {
  RCFILE="${HOME}/.aws/s3bkprc"
  if [ -f "$RCFILE" ]; then
    echo "[`date -Iseconds`] Importing defaults from $RCFILE..."
    . $RCFILE
  else
    echo "[`date -Iseconds`] Configuration file not found. Create it at $RCFILE."
    exit 2
  fi
}

# Check dependencies
dependencies () {
  #if [ ! -x "$DBDUMP" ]; then
  #  echo "[`date -Iseconds`] Database dump utility $DBDUMP not found. Please install it."
  #  exit 3
  #fi
  if [ ! -x "$ARCH" ]; then
    echo "[`date -Iseconds`] Archive utility $ARCH not found. Please install it."
    exit 4
  fi
  if [ ! -x "$S3CMD" ]; then
    echo "[`date -Iseconds`] Amazon S3 utility $S3CMD not found. Please install it."
    exit 5
  fi
}

# Create temporary directory
mktmp () {
  if [ ! -d "$DUMPTMP" ]; then
    echo "[`date -Iseconds`] Creating temporary directory $DUMPTMP..."
    mkdir -p $DUMPTMP
  fi
}

# List foreign packages
lspkg () {
  echo "[`date -Iseconds`] Listing 3rd party packages..."
  stat -c "%y %n" $LSPKG | sort > $DUMPTMP/3rdpkglist.txt
}

# Dump databases
dumpdb () {
  for i in "${DBBKP[@]}"; do
    echo "[`date -Iseconds`] Dumping $i database..."
    mysqldump --user=$DBUSER --pass=$DBPASS --opt $i > $DUMPTMP/dbdump_$i.sql
    echo "[`date -Iseconds`] $i database dump done."
  done
}

# Create archive
archive () {
  archdate=$(date "+%Y-%m-%d")
  archhost=$(cat "/etc/HOSTNAME")
  archive="$DUMPTMP/../"$archdate"_backup_$archhost.tar.gz"
  echo "[`date -Iseconds`] Archiving files..."
  GZIP=-6 $ARCH pczf $archive $FSBKP > /dev/null 2>&1
  echo "[`date -Iseconds`] File archiving done."
}

# Create archive checsum
checksum () {
  echo "[`date -Iseconds`] Creating archive checksum..."
  md5sum $archive > $archive.sum
  echo "[`date -Iseconds`] Archive checksum done."
}

# Send archive file to Amazon S3
sendtos3 () {
  echo "[`date -Iseconds`] Putting archive to Amazon S3..."
  echo "[`date -Iseconds`] Destination: $S3PATH"
  $S3CMD -f -q put $archive $archive.sum $S3PATH
  echo "[`date -Iseconds`] Archive sent to Amazon S3."

}

# Cleanup
cleanup () {
  echo "[`date -Iseconds`] Cleaning up..."
  rm -rf $archive $archive.sum $DUMPTMP
  echo "[`date -Iseconds`] Clean up done."
}

# The main script
echo "[`date -Iseconds`] Backing up instance to Amazon S3..."
isroot
loaddefaults
dependencies
mktmp
lspkg
dumpdb
archive
checksum
sendtos3
endexec
cleanup
echo "[`date -Iseconds`] Instance back up to Amazon S3 done."

Agora crie o arquivo de configuração em /root/.aws/s3bkprc com o conteúdo abaixo. Não esqueça de editar os parâmetros conforme as suas necessidades.

DBDUMP="/usr/bin/mysqldump"
ARCH="/usr/bin/tar"
S3CMD="/usr/bin/s3cmd"
DUMPTMP="/var/spool/mail/vmail/tmp/bkpdump"
DBUSER="root"
DBPASS="<senha fodona do MariaDB>"
DBBKP=( "horde" "mysql" "vimbadmin" )
LSPKG="/var/log/packages/*SBo /var/log/packages/*deny"
FSBKP="/etc /home /usr/local/bin /root /var/lib/sbopkg/queues"
FSBKP+=" /var/lib/spamassassin /var/lib/tor/hidden_service"
FSBKP+=" /var/spool/mail/vmail/exemplo.com /var/spool/mail/vmail/sieve*"
S3PATH="s3://exemplo.s3.adm/backups/mail/"

Agora crie os diretórios, ajuste algumas permissões e execute o script pela primeira vez.

# mkdir -p /var/spool/mail/vmail/tmp
# chmod 755 /usr/local/bin/s3bkp
# chmod 400 /root/.aws/s3bkprc
# s3bkp

Vai demorar um pouco até o backup ser concluído. É bom ficar claro que esse tempo vai aumentar conforme as caixas de mensagens forem crescendo. Mas isso não é problema, uma vez que o processo é automatizado.

Agora vamos colocar o backup para rodar todos os dias. Crie o arquivo /etc/cron.daily/s3bkp com o conteúdo abaixo.

#!/bin/sh
# Backup instance
/usr/local/bin/s3bkp >> /var/log/s3bkp 2>&1

Ajuste a permissão com:

# chmod 755 /etc/cron.daily/s3bkp

A execução diária vai gerar um novo arquivo de log, /var/log/s3bkp. Esse novo arquivo também deve ser rotacionado. Mas você já sabe como fazer isso, então deixo por sua conta essa mudança.

E pronto! Todos os dias as 4:40h o seu backup será feito. Esse horário é definido pelo crontab do root, na opção diária do run-parts. Se você quiser que a execução do backup ocorra em um horário diferente, então crie uma entrada no cron para o s3bkp para o horário desejado.

Sieve

Olha ele aí de novo! Só que agora em um contexto diferente.

Lá atrás vimos como ele funciona no contexto do Dovecot e do SpamAssassin. Mas o Sieve também pode nos ajudar a classificar nossos emails que são de boa gente.

Vou deixar um exemplo de um script Sieve genérico com várias regrinhas úteis. Use o seu cliente de email para editar e enviar esse script para o servidor. Uma vez que ele esteja lá, todos os clientes de email (celular, computadores, sistemas) que você conectar a sua conta se beneficiarão dos filtros automaticamente, mesmo que o cliente em questão não faça nem idéia do que é Sieve. Como vimos, esses scripts rodam apenas no servidor e você só precisa de um cliente para alterá-los.

Ai vai! Faça bom uso.

################################################################################
# Meus filtros Sieve
#
# Mensagens detectadas como spam são tratadas por um filtro global do servidor
# em /var/mail/vmail/sieve-before/globalspam.sieve do seguinte modo:
# - X-Spam-Level >= 3: move para a pasta Spam e marca como lido
# - X-Spam-Level >= 10: descartadas sumariamente
#
# Os demais filtros são configurados aqui.
################################################################################

# Carrega extensões do Sieve
require [ "envelope", "fileinto", "imap4flags", "regex" ];

# Move mensagens dos amigos para a pasta Migos.
if address :is "from" [
  "amigo1@xiboquinha.com", "amigo2@furufunfun.br", "amigo3@casadamaejoana.com"
]
{
  fileinto "Migos";
}

# Move mensagens administrativas para a pasta SysAdmin/Systems.
if anyof (
  address :is "from" [
    "aws@amazon.com", "nic@registro.br"
  ],
  address :is "to" [
    "abuse@exemplo.com", "noc@exemplo.com.br", "postmaster@exemplo.com",
    "security@exemplo.com"
  ],
  header :contains "from" "github"
)
{
  fileinto "SysAdmin/Systems";
}

# Move mensagens relativas a serviços assinados por mim para a pasta
# Assinaturas.
if address :is :domain "from" [
  "turmadamonica.com.br", "defloration.com","blackblock.com.br"
]
{
  fileinto "Assinaturas";
}

# Move mensagens de serviços financeiros para a pasta Famirri.
if address :is :domain "from" [ "bancocuzao.com.br" ]
{
  fileinto "Famirri";
}

# Move mensagens de listas de discussão.
#   Lista: HordeAnnounce
if anyof (
  address :is "from" [ "mailman-owner@lists.horde.org" ],
  address :all :contains ["to", "cc", "bcc"] "announce@lists.horde.org"
)
{
  fileinto "Listas/HordeAnnounce";
}
#   Lista: SlackDocs
if address :all :contains ["to", "cc", "bcc"] "slackdocs@alienbase.nl"
{
  fileinto "Listas/SlackDocs";
}

# Descarta mensagens de endereços que não quero receber do catch-all.
if address :all :contains ["to", "cc", "bcc"] [
  "mariazinha@exemplo.com", "zezao@exemplo.com",
]
{
  discard;
}

# Spammers, morram!
if anyof (
  address :is :domain "from" [
    "dominio1.com.br", "dominio2.com", "dominio3.net"
  ],
  address :is "from" [
    "animal@spammer1.com.br", "puto@spammer2.com", "corno@spammer3.net"
  ]
)
{
  discard;
}

# Fim dos filtros.

Adapte os filtros acima conforme a sua necessidade e seja feliz.

Tem mais?

Credo, ou! Cansa não? Você leu 16 artigos gigantescos com um monte de coisa chata e ainda quer mais? Doente!

Tem, tem muito mais!

Você pode ver formas de proteger melhor o seu servidor de emails. Aconselho o uso de uma combinação de ferramentas como Fail2ban, chrootkit, AIDE, RKHunter e Lynis. Elas darão uma ótima plataforma de detecção de intrusão ao seu servidor.

Você também pode querer obter estatísticas sobre como os seus usuários estão utilizando o servidor. Isso pode ser feito com o bom e velho AWStats.

Talvez você não se sinta seguro com apenas um servidor de email atendendo o seu domínio. Acho justa sua preocupação. Para resolvê-la você vai precisar de um ou mais backup MX.

As nuvens são o limite para você. Faça bom uso do seu servidor e não faça spam.

Aqui cabô!