Feliz com o seu servidor de emails funcionando? Ainda que ele não esteja em produção e não seja capaz receber emails vindos da internet afora, ele está pronto para assumir a função. E justamente por isso, pronto para ser perigoso.

Por isso é importante entender tudo o que foi feito no artigo anterior antes de expormos nosso bonitinho na internet, esse lugar ameaçador. Esse artigo também é longo... e chato pácaraleo.

Vamos seguir na mesma ordem que instalamos e configuramos, sendo que aqui vamos falar só do Postfix. Ele é complexo o suficiente e falar de todos os demais serviços agora iria tornar este artigo um livro.

master.cf: o mestre

O coração do Postfix é o arquivo master.cf. Ele define os serviços que estarão disponíveis e como eles se falam.

SMTP: boca e ouvidos

Logo no comecinho tem isso, e vem no começo não à toa:

# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       1       postscreen
tlsproxy  unix  -       -       n       -       0       tlsproxy
dnsblog   unix  -       -       n       -       0       dnsblog
smtpd     pass  -       -       n       -       -       smtpd
  -o content_filter=spamd

Esse trecho é a definição do serviço SMTP que roda na porta 25, o que é dito pelo parâmetro inet. É através dele que os servidores de email em toda a internet se falam e trocam mensagens entre si. Todos os bilhões de emails que vão e vêm na internet todos os dias passam por aqui.

Ele roda como um serviço público, ou seja, que está disponível para fora do servidor (primeiro n); sem privilégios (primeiro -); com a raiz real do filesystem (segundo n); sempre alerta (segundo -); e com no máximo um processo em execução (1). O último item é o comando a ser executado pelo serviço.

Sugiro que você leia o manual do master.cf para entender melhor esses campos. Não vou falar mais deles aqui, exceto se for necessário para a explicação.

Na nossa configuração, o serviço SMTP é executado pelo comando postscreen. O Postscreen está para o SMTP assim como o leão de chácara está para a boate dos playba: ele barra os de estética duvidosa e os bagunceiros que estão na lista negra.

A lista negra do Postscreen é governada por esses parâmetros do main.cf:

# Postsreen spam prevention
postscreen_greet_action = enforce
postscreen_dnsbl_action = enforce
postscreen_access_list = permit_mynetworks
postscreen_dnsbl_sites =
  zen.spamhaus.org,
  b.barracudacentral.org,
  bl.spamcop.net

Isso diz o seguinte, nessa ordem:

  1. Seja educado e me cumprimente, porque senão tu toma tôco. (postscreen_greet_action = enforce)
  2. Tôco pra quem tá em lista negra. (postscreen_dnsbl_action = enforce)
  3. Os meus parça podem entrar na boa. (postscreen_access_list = permit_mynetworks)
  4. Essas são as listas que eu olho. Se seu nome ou CPF estiver nelas, veja o 3. (postscreen_dnsbl_sites = ...)

Só nessa aí o tráfego de spam para o seu domínio já cai vertiginosamente. Convenhamos, spammer é burro e preguiçoso. Eles não sabem configurar servidor direito.

Há mais proteções, mas as do Postscreen que habilitamos são essas.

Depois que o porteiro liberou a entrada, tem o nosso amigo tlsproxy. Ele habilita o tráfego criptografado entre os servidores de email.

Quando um servidor conecta ao seu para entregar uma mensagem, ele não fez uma conexão segura. Mas o seu servidor diz a ele que um negócio chamado STARTTLS é bem vindo. STARTTLS é justamente o comando que transforma uma conexão insegura em uma segura. Veja como é isso:

$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.exemplo.com ESMTP
ehlo mail.exemplo.com
250-mail.exemplo.com
250-PIPELINING
250-SIZE 40000000
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
Connection closed by foreign host.

No exemplo acima conectamos ao nosso servidor via telnet, um protocolo que nem sonha o que é criptografia. Depois cumprimentamos o robô com ehlo mail.exemplo.com, que responde dizendo que, dentre outras coisas, ele suporta STARTTLS. Podemos usar isso para criptografar a conexão.

No /var/log/maillog esse diálogo é assim:

May 18 18:15:19 mail postfix/postscreen[27398]: CONNECT from [127.0.0.1]:40064 to [127.0.0.1]:25
May 18 18:15:19 mail postfix/postscreen[27398]: WHITELISTED [127.0.0.1]:40064
May 18 18:15:19 mail postfix/smtpd[27399]: connect from localhost[127.0.0.1]
May 18 18:15:41 mail postfix/smtpd[27399]: disconnect from localhost[127.0.0.1]

Agora vamos usar o STARTTLS para promover uma conexão segura:

$ openssl s_client -starttls smtp -connect localhost:25 -quiet
depth=3 C = SE, O = Root CA, OU = http://www.cacert.org, CN = CA Cert Signing Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
250 DSN
ehlo mail.exemplo.com
250-mail.exemplo.com
250-PIPELINING
250-SIZE 40000000
250-ETRN
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye

Notou a diferença na resposta? Agora temos um certificado e anúncio de capacidades diferentes. Há até a possibilidade de fazer login (250-AUTH PLAIN LOGIN), o que você só desejaria fazer em uma conexão criptografada, certo? De qualquer modo, não vamos fazer isso aqui. Esse serviço é só para tráfego de mensagens entre servidores.

O errinho depois do certificado você pode ignorar, já que ele diz o óbvio: ao menos um certificado na cadeia de certificados é auto assinado. Claro, espertão! Ao menos um, o raiz, tem que ser.

E o log disso?

May 18 18:21:13 mail postfix/postscreen[27519]: CONNECT from [127.0.0.1]:40066 to [127.0.0.1]:25
May 18 18:21:13 mail postfix/postscreen[27519]: WHITELISTED [127.0.0.1]:40066
May 18 18:21:13 mail postfix/smtpd[27520]: connect from localhost[127.0.0.1]
May 18 18:21:13 mail postfix/smtpd[27520]: Anonymous TLS connection established from localhost[127.0.0.1]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
May 18 18:21:24 mail postfix/smtpd[27520]: disconnect from localhost[127.0.0.1]

Opa! Ó lá, ó lá! Anonymous TLS connection na veia!

Os servidores na internet podem entregar mensagens para o seu usando os dois métodos: seguro e não seguro. Um servidor bem configurado e que suporta STARTTLS promove uma conexão para segura primeiro e entrega a mensagem depois. Um servidor mal configurado ou que não suporta STARTTLS (de novo, mal configurado) vai falar em texto puro, não seguro. Mas seu servidor é benevolente e aceita os dois.

Continuando, depois de termos uma conexão segura, entra o dnsblog. Esse é o serviço que consulta as listas negras e registra os resultados em log para o Postscreen. A documentação do Postscreen fala mais sobre o dnsblog.

Se você prestou atenção no master.cf original, antes de substituí-lo com a versão que proponho, deve ter notado que existia um bloco que definia o serviço SMTPS e que estava comentado. Ativar esse bloco habilitaria o mesmo serviço que temos com o SMTP com STARTTLS, mas na porta 465. Acontece que esse serviço não faz parte do RFC 5321, o padrão que define tudo o que estamos fazendo aqui. Por esta razão, cagamos para este serviço e simplesmente desaparecemos com ele.

smtpd: idioma

Depois de passar pelos três serviços (postscreen, tlsproxy e dnsproxy), a conexão e a mensagem chegam 'NO CARA': smtpd! Ele é o daemon fodão, o servidor de email propriamente dito. O smtpd é tão fodão que o comando dele é ele mesmo e é muito complexo pra eu explicar aqui. É muito mais produtivo você ler a documentação do smtpd e o RFC mencionado acima, inteiros.

Para o contexto desta explicação, basta eu dizer uma coisa sobre o smtpd: todas as mensagens recebidas de fora pelo serviço SMTP são encaminhadas por ele para o SpamAssassin analisar e determinar se é ou não spam. Uma vez concluída a ánalise, a mensagem volta para o smtpd para por fim ser entregue, também por ele, ao Dovecot. Só então ela é guardada na sua caixa de correio, onde ficará te esperando. Mais sobre isso logo mais.

Eu expliquei tão detalhadamente esse primeiro bloco do main.cf porque ele é o mais básico dos serviços prestados pelo Postfix e também o mais complexo. Incrível o que cinco linhas podem fazer, não?

Agora que você já entende melhor como os serviços se relacionam no main.cf, os demais blocos vou explicar en passant.

submission: porta de saída

Logo depois do serviço SMTP temos isso:

submission  inet  n     -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_etrn_restrictions=reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o content_filter=dksign:[127.0.0.1]:10027
  -o receive_override_options=no_address_mappings
  -o milter_macro_daemon_name=ORIGINATING

Esse é o bloco que estabelece o serviço oficial de envio para os clientes de email. Ele roda na porta 587, chama-se submission e é por ele que todos os emails que você enviar vão passar antes de sair do servidor para o destino.

Assim como no SMTP, esse serviço suporta STARTTLS, só que aqui dissemos que a conexão segura é obrigatória com a opção smtpd_tls_security_level=encrypt. Se o cliente de email não suportar STARTTLS não tem conexão. Isso é bom porque protege o usuário e a senha necessários para fazer o login antes de poder enviar emails (smtpd_sasl_auth_enable=yes).

Como o nosso servidor estará conectado a internet o tempo todo, ele não precisa do comando ETRN, que é desabilitado com smtpd_etrn_restrictions=reject.

Outras restrições de uso para envio de emails são controladas pela opção smtpd_recipient_restrictions=.... Ela diz que só quem faz parte da mesma rede que o servidor ou usuários autenticados podem utilizar o serviço. O resto cai fora.

Depois vem as opções do filtro que submete as mensagens enviadas ao serviço que assina mensagens, o DKIM. Falaremos um pouco dele a seguir.

E isso fecha os dois serviços mais essenciais do Postfix: o SMTP para o tráfego entre servidores e o submission para que você e os demais usuários possam enviar emails para outras pessoas.

O bloco seguinte define um montão de serviços internos do Postfix. Não mexa neles. Se quiser saber mais sobre esses serviços, RTFM do master.cf.

Na luta contra spam

Em seguida vem esse bloco:

spamd     unix  -       n       n       -       -       pipe
  user=spamd argv=/usr/bin/spamc

Esse é o assassino de spam que o SMTP usa como filtro. Toda mensagem que chega passa por aí. Veremos como é isso com mais detalhes em outro artigo.

Por últimos, temos esses dois blocos:

dksign    unix  -       -       n       -       4       smtp
  -o smtp_send_xforward_command=yes
  -o smtp_discard_ehlo_keywords=8bitmime,starttls
127.0.0.1:10028 inet  n  -      n       -       10      smtpd
  -o content_filter=DNS e cron
  -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
  -o smtpd_helo_restrictions=
  -o smtpd_client_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks=127.0.0.0/8
  -o smtpd_authorized_xforward_hosts=127.0.0.0/8

Isso tudo é uma coisa só: a integração com o serviço que executa o DKIM. Ele é responsável por assinar todas as mensagens que são enviadas do seu cliente para o serviço submission. Vamos entender o que é isso e como é feito também em outro artigo.

O importante agora é você saber que o DKIM é uma medida que evita que você seja tratado como spammer por outros servidores. Eu disse evita porque se você fizer spam, mesmo com DKIM e tudo o mais que ainda vamos ver, você será tratado como spammer e eu acho é pouco. O que garante que você não é spammer é o seu comportamento, tipo quando você diz não ser mala mas as pessoas te acham um M-A-L-A.

Isso encerra o master.cf. no nosso contexto específico de uso.

main.cf: as regras do jogo

Agora que conhecemos bem os serviços expostos pelo Postfix, podemos partir pra outro arquivo essencial na configuração do Postfix: main.cf. Há um universo incrível de configurações possíveis nesse arquivo, mas vamos focar apenas nos mais essenciais, começando pelo pedaço mais cabuloso: os parâmetros de TLS.

Seguro

Ah, uma coisa que ainda não disse: O TLS é a evolução do SSL e ambos são implementados pelo OpenSSL, aquele mesmo do Heartbleed. O que me leva a te dizer que o aviso do documento sobre TLS no Postfix deve ser levado a sério:

By turning on TLS support in Postfix, you not only get the ability to encrypt mail and to authenticate remote SMTP clients or servers. You also turn on thousands and thousands of lines of OpenSSL library code. Assuming that OpenSSL is written as carefully as Wietse's own code, every 1000 lines introduce one additional bug into Postfix

Certo? Ok, vamos as configurações.

# TLS settings
tls_random_source = dev:/dev/urandom

# Custom smtp TLS settings
smtp_tls_loglevel = 1
smtp_tls_note_starttls_offer = yes
smtp_tls_security_level = may
smtp_tls_protocols = !SSLv2
smtp_tls_cert_file = /etc/ssl/private/certificate.crt
smtp_tls_key_file = /etc/ssl/private/certificate.key
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

# Custom smtpd TLS settings
smtpd_tls_loglevel = 1
smtpd_tls_auth_only = yes
smtpd_tls_ciphers = high
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2
smtpd_tls_received_header = yes
smtpd_tls_cert_file = /etc/ssl/private/certificate.crt
smtpd_tls_key_file = /etc/ssl/private/certificate.key
smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtpd_tls_dh1024_param_file = /etc/ssl/private/dhparam.pem
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

A separação é bem evidente, né? Primeiro o parâmetro que se aplica ao TLS no Postfix como um todo, depois os que se aplicam ao serviço SMTP (smtp_tls_*) e depois ao smtpd (smtpd_tls_*). Essa separação é importante pois apesar de tudo ser o Postfix, os diferentes serviços que ele governa podem e devem operar com configurações distintas.

Primeiramente definimos a fonte dos números randômicos para o TLS. Neste caso, usamos o /dev/urandom, que é o gerador de números pseudo-randômicos do Linux. Como não dispomos de um medidor de radiação cósmica de fundo ou de fenômenos quânticos conectado ao nosso servidorzinho para termos números randômicos reais, os pseudo terão que ser suficientes.

Para ambos os serviços, habilitamos o registro das conexões seguras no log do Postfix com as opções *_tls_loglevel. Isso nos ajudará a identificar quando uma conexão foi feita de modo seguro ou não.

No SMTP, definimos também que a possibilidade de conectar de modo seguro com o STARTTLS em um servidor qualquer seja registrada no log com a opção smtp_tls_note_starttls_offer = yes. Essa opção é importante porque se existir a possibilidade de uma conexão segura e uma mensagem for entregue de modo não seguro, há um problema com o nosso servidor.

Depois definimos que o nosso servidor pode usar a conexão segura se ela existir, smtp_tls_security_level = may. Isso habilita a segurança oportunística: se houver usa, se não houve não usa. Se você quiser que o seu servidor só fale com outros servidores que ofereçam conexões seguras, então esse parâmetro deve ser alterado para smtp_tls_security_level = encrypt, mas isso diminuirá bastante a sua capacidade de entregar mensagens aos seus destinatários, uma vez que a muitos servidores na internet não suportam segurança para tráfego de emails.

E aqui é o lugar ideal para um aviso importantíssimo!
A segurança de uma conexão entre servidores de email pode ser facilmente quebrada por um ataque do tipo homem-no-meio (MitM). Para mais informações sobre isso, leia este artigo. Se você quiser torná-lo invulnerável a este tipo de ataque, terá que usar DNSSEC. Mas isso é tema pra outro artigo. De qualquer modo, o Route53 (o DNS do AWS) não suporta DNSSEC. Como estamos utilizando-o para nossos exemplos, não faz sentido abordar isso aqui.

Continuando, em seguida desabilitamos o protocolo SSLv2 com a opção smtp_tls_protocols = !SSLv2. Esse idioma do SSL é reconhecidamente fraco e não deve mais ser utilizado para nada.

Por fim, há as opções que apontam o certificado do servidor, a chave privada do certificado e o arquivo que contém todos os certificados raiz aceitos pelo nosso servidor. Note que o certificado usado pelo Postfix é o mesmo usado pelo nginx. Isso facilita muito a administração de certificados.

No smtpd definimos praticamente as mesmas coisas que o SMTP, mas há algumas adições importantes.

Lembra que no teste dos serviços que fizemos na parte anterior desta série nós vimos que o smtpd oferece a opção de login somente depois de um STARTTLS? Pois então, isso é configurado aqui coma opção smtpd_tls_auth_only = yes.

Seguindo, temos o conjunto de cifradores criptográficos permitidos em nosso servidor, smtpd_tls_ciphers = high. Habilitamos somente os cifradores fortes e desativamos os médios e os fracos. Isso trará alguns problemas de compatibilidade com outros servidores pobremente configurados. Como não queremos falar com gente porca mesmo, então tá beleza.

A opção smtpd_tls_received_header = yes faz com que no cabeçalho de cada mensagem conste a informação que ela foi recebida usando métodos seguros. É bom poder saber isso de um modo fácil.

Finalmente definimos dois arquivos necessários ao smtpd. Primeiro o arquivo de chaves requerido pelo recurso PFS, o mesmo usado no nginx. Depois o arquivo que guarda as informações sobre sessões seguras.

Restrições

Agora que entendemos melhor os parâmetros do TLS essenciais para o tráfego de mensagens criptografadas entre servidores e clientes de email, vamos ver outro bloco importante do main.cf, o que trata das restrições que nosso servidor aplicará a outros servidores e clientes de email. O bloco é esse:

# SMTPD restritcions settings
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtpd_helo_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  check_helo_access hash:/etc/postfix/helo_access
  # Due to crap DNS/RDNS configuration made by morons at some ISP services
  #   it's not possible to enable reject_invalid_helo_hostname,
  #   reject_non_fqdn_helo_hostname and reject_unknown_helo_hostname here, as
  #   the required name resolution will fail, leading to 550 errors when
  #   sending mail from MUAs under these dumb networks.
  #   This is particularly true for the NET Virtua.
  permit
smtpd_sender_restrictions =
  permit_mynetworks,
  reject_non_fqdn_sender,
  reject_unknown_sender_domain,
  permit
smtpd_recipient_restrictions =
  reject_unknown_client_hostname,
  reject_unknown_sender_domain,
  reject_unknown_recipient_domain,
  reject_unauth_pipelining,
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_unauth_destination,
  reject_invalid_hostname,
  reject_non_fqdn_sender,
  permit

# Dealing with rejection: use permanent 550 errors to stop retries
unknown_address_reject_code = 550
unknown_hostname_reject_code = 550
unknown_client_reject_code = 550

Primeiro somos maus. Vamos deixar o puto do spammer fazer tudo que tem que fazer uma vez conectado em nosso servidor e só depois mandá-lo a merda. Isso é feito com a opção smtpd_delay_reject = yes.

Depois exigimos que os outros cumprimentem o nosso servidor com a opção smtpd_helo_required = yes.

Em seguida vem as restrições aplicadas aos comandos HELO e EHLO do smtpd. Esses comandos são como os servidores e clientes de email se apresentam ao nosso servidor.

Com base nessa identificação permitimos as máquinas que fazem parte da nossa rede (permit_mynetworks) e os clientes de emails devidamente autenticados (permit_sasl_authenticated).

Depois temos uma restrição controlada pelo arquivo /etc/postfix/helo_access. Ela barra o roubo de identidade. Suponha que um spammer filho duma puta conecta ao seu servidor e tenta enviar um email em nome do seu domínio, o que o smtpd permite fazer. Por causa dessa restrição, o spammer filho da puta é rejeitado porque somente o seu servidor pode enviar emails em nome do seu domínio. Mais ninguém de fora poderá fazer isso sem estar autenticado, pelo menos não através desse servidor.

Existem outras restrições que seriam úteis aqui, mas infelizmente no Brasil temos um bando de administradores de rede preguiçosos que trabalham para ISPs sem vergonhas tipo o Vírtua da Net, onde nem um DNS funciona direito. Ativar essas restrições adicionais vai impedir que você e seus usuários enviem emails a partir de clientes de email. Você pode testar se essas configurações adicionais não restringem isso. Se funcionar para você, use-as.

Depois temos as restrições que se aplicam ao comando MAIL FROM do SMTP (smtpd_sender_restrictions) e as que se aplicam ao comando RCPT TO (smtpd_recipient_restrictions). Consulte a documentação do main.cf para mais informações sobre essas restrições. O README sobre controle de acesso do Postfix também vale a pena ser lido.

Uma coisa que também pode ajudar a entender onde cada bloco de restrições se aplica é isso:

Conversa do SMTP                     # Restrição no main.cf
--------------------------------------------------------------------
220 mail.exemplo.com ESMTP           # <-smtp_client_restrictions
HELO mail.exemplo.com                # <-smtp_helo_restrictions
250 mail.exemplo.com
MAIL FROM:<eumesmo@exemplo.com>      # <-smtp_sender_restrictions
250 2.1.0 Ok
RCPT TO:<eumesmo@exemplo.com>        # <-smtp_recipient_restrictions
250 2.1.5 Ok
DATA                                 # <-smtp_data_restrictions
354 End data with <CR><LF>.<CR><LF>
To:<eumesmo@exemplo.com>             # <-header_checks
From:<eumesmo@exemplo.com>
Subject:SMTP Test
This is a test message               # <-body_checks
.
250 2.0.0 Ok: queued as 301AE20034
QUIT
221 2.0.0 Bye

Facinho, né?

Algumas das restrições que impomos geram respostas aos servidores. O bloco de restrições define que essas respostas são todas um erro 550 mailbox not found, que é um erro permanente e que faz com que um spammer filho da puta não volte a tentar conectar para entregar lixo.

Identidade

Outro bloco de configuração que vale a pena ser mencionado é esse:

# Server identity settings
myhostname = mail.exemplo.com
myorigin = $mydomain
mydestination = localhost, localhost.$mydomain
mynetworks = 127.0.0.0/8 172.16.1.0/24
smtpd_banner = $myhostname ESMTP

Esse bloco é a carteira de identidade do seu servidor. Especificamos um nome (myhostname) que tem que ser igual ao que você usou no DNS. O nome também qualifica o domínio, a parte depois do primeiro ponto e que no nosso caso é exemplo.com.

A configuração myorigin especifica qual o domínio que será completado para um email de uma conta local do sistema. Por exemplo: root vira root@exemplo.com.

mydestination especifica a lista de servidores e domínios pelos quais o nosso servidor vai responder. Aqui precisamos definir apenas o localhost com e sem FQDN, pois o nosso domínio exemplo.com é um domínio virtual fornecido pelo ViMbAdmin. Domínios virtuais não devem aparecer nesta configuração.

As redes que podem usar o nosso servidor para enviar emails são especificadas em mynetworks. Coloque nessa configuração todas as redes internas privadas que você vai usar para enviar email sem necessitar de autenticação. Clientes de email não contam porque eles fazem autenticação. É essa configuração que é levada em conta por todos os permit_mynetworks que você ver no Postfix.

Se você está no AWS, esses endereços são os de subredes de VPCs e os diversos VPCs devem ser conectados um ao outro para que as instâncias em um VPC possam ter acesso às instâncias em outro VPC via rede interna privada. Esses endereços devem ser no formato CIDR e a rede do loopback (127.0.0.1/8) deve sempre ser informada, senão o nosso servidor não consegue enviar os emails a partir dele mesmo.

Fechando o bloco de identidade temos a configuração smtpd_banner = $myhostname ESMTP. Por padrão a mensagem inicial de conexão, aquela que vemos quando conectamos via telnet na porta 25, informa qual é o software que implementa o smtpd. Ninguém precisa saber isso, então alteramos essa mensagem para mostrar somente o que interessa.

Local e SASL

Agora vamos falar de como o Postfix interage com o Dovecot para tratar as mensagens destinadas a usuários locais, aqueles que existem de fato no servidor.

mailbox_command =
  /usr/libexec/dovecot/deliver -c
  /etc/dovecot/conf.d/01-mail-stack-delivery.conf -m "${EXTENSION}"

Esse bloco aí faz isso. Ele usa o comando deliver do Dovecot para distribuir as mensagens recebidas pelo servidor nas devidas caixas de correio dos usuários locais. Simples assim. Os usuários dos domínios virtuais, aqueles que não existem no servidor, são tratados de outro modo. Veremos como logo mais.

A outra ponta da integração do Postfix com o Dovecot é a autenticação dos clientes de email para que o Postfix decida quem pode usar nosso servidor para enviar mensagens para outros servidores na internet via smtpd. Isso é feito por um treco chamado SASL (Simple Authentication and Security Layer) e é governado pelo bloco abaixo.

# SASL settings
smtpd_sasl_auth_enable = yes
smtpd_sasl_authenticated_header = yes
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
smtpd_sasl_type = dovecot

Primeiro é dito que queremos usar o SASL (smtpd_sasl_auth_enable = yes). Por padrão o Postfix não faz qualquer autenticação para usar o smtpd. Conectou, pode usar. Não, né?

Depois informamos que queremos que o usuário autenticado apareça no cabeçalho da mensagem com a opção smtpd_sasl_authenticated_header = yes. Outra coisa que é bom termos como saber.

A opção smtpd_sasl_path = private/auth informa onde está o socket de autenticação criado pelo Dovecot para que o Postfix possa utilizar. Esse caminho é relativo ao chroot do Postfix, que é por padrão /var/spool/postfix.

Em seguida dizemos com a opção smtpd_sasl_security_options = noanonymous que a autenticação SASL só pode aceitar métodos que não possibilitem usuários anônimos.

Depois, a opção smtpd_sasl_local_domain fornece um nome para o local de autenticação a ser apresentado aos clientes de email.

E por fim, é dito que a implementação de SASL que vamos usar é a do Dovecot com a opção smtpd_sasl_type = dovecot.

Backend e domínios hospedados

Deixei o mais complicado para o final, só pra sacanear sua cabeça cansada de tanto lenga-lenga.

Para encerrar o entendimento dos parâmetros mais importantes do Postfix, vamos falar das configurações que fazem-no integrar ao ViMbAdmin para reconhecer os domínios, usuários e apelidos virtuais.

Esse bloco tem importância crucial para que o nosso Postfix funcione com o esquema de domínios, usuários e caixas de correio virtuais. O método apresentado aqui é baseado na documentação original do Postfix que trata de domínios virtuais. No nosso caso, estamos implementando especificamente o exemplo onde o Postfix é usado com mailbox virtual, domínios separados e sem contas Unix daquele documento.

Isso traz a necessidade de entender ao menos por cima um conceito importante do Postfix: as classes de endereçamento. Precisamos entender especificamente isso:

  1. Nome canônico: quando o Postfix é o destino final de mensagens enviadas para as classes de endereçamento local. Elas são formadas pelos nomes do nosso servidor (e seus IPs) conforme configurados pela opção mydestination do main.cf.
  2. Domínios hospedados: quando o Postfix é o destino final de mensagens enviadas para quaisquer outros domínios das classes de endereçamento de domínios e mailboxes virtuais. Essas classes são informadas pelas opções virtual_mailbox_domains e virtual_mailbox_maps.

Os nomes canônicos foram definidos um pouco mais acima, quando configuramos a identidade do nosso servidor. Agora vamos ao bloco que define quais são nossos domínios hospedados, aqueles que são fornecidos pelo ViMbAdmin através do MariaDB.

# ViMbAdmin related settings
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_mailbox_base = /var/mail/vmail
virtual_mailbox_domains = mysql:/etc/postfix/mysql/virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql/virtual_alias_maps.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp

A opção virtual_minimum_uid é um mecanismo de segurança para o Postfix garantir que nenhuma mensagem será escrita em arquivos sensíveis do sistema cujos proprietários sejam mais privilegiados. Esse parâmetro impede que qualquer mensagem tratada pelo Postfix seja escrita com o uid=0, o do root, ou qualquer outro uid menor que 5000.

Em seguida definimos de modo estático qual usuário e grupo do sistema possui a propriedade das caixas de mensagens virtuais com as opções virtual_uid_maps e virtual_gid_maps. Elas correspondem ao usuário e grupo vmail que criamos lá atrás na instalação, e não por acaso o uid desse usuário é 5000.

Então definimos outra coisa importante: qual é o caminho no filesystem que armazenará os diretórios dos domínios e mailboxes (usuários) virtuais. Isso é feito com a configuração virtual_mailbox_base = /var/mail/vmail. No filesystem, /var/mail é um link simbólico para /var/spool/mail. Se você olhar o conteúdo desse diretório, verá que ele contém os arquivos de mailbox dos usuários locais do sistema e o ponto de montagem do filesystem que criamos lá atrás para guardar os maildir dos usuários virtuais. Esse último é o lugar que armazena os domínios virtuais e diretórios com as caixas de correio de cada usuário, em cada domínio.

Aliás, aqui é o lugar ideal para explicar que mailbox guarda todas as mensagens de um usuário em um só arquivo e maildir guarda uma mensagem por arquivo dentro de um diretório. No nosso contexto de operação, usuários Unix possuem mailboxes, usuários virtuais possuem maildir.

Em seguida é dito como o Postfix deve conversar com o MariaDB para obter os dados do backend do ViMbAdmin. Essas três configurações (virtual_mailbox_domains, virtual_mailbox_maps e virtual_alias_maps) apontam para os arquivos que criamos na etapa anterior e que contém o usuário, a senha e as declarações SQL necessárias para essa função. Toda vez que um email chega da internet para ser entregue a um usuário virtual, são esses arquivos que mostram ao Postfix o que ele deve fazer.

Notou que o Postfix nem sabe o que é ViMbAdmin? Pois então, ele só sabe como obter os dados do banco criado pelo ViMbAdmin. Por isso o MariaDB é o backend propriamente dito.

E por último dizemos ao Postfix como ele deve falar com o MDA. Para isso ele usa o socket LMTP disponibilizado pelo Dovecot e definido aqui em virtual_transport. O protocolo LMTP é a evolução dos métodos de entrega de mensagem locais (ou LDA). A diferença de um para o outro é que o LDA roda como um comando de vida curta executado cada vez que uma mensagem deve ser entregue a um usuário, enquanto o LMTP é um processo de longo prazo, executado apenas uma vez como um daemon e que dá conta da entregas de todas as mensagens. Isso torna as coisas mais eficientes e menos custosas.

E pra encerrar essa porra toda, precisamos obedecer três regrinhas no main.cf e no ViMbAdmin para que nossos domínios hospedados funcionem a contento:

  1. NUNCA inserir o nome do domínio hospedado como um dos nomes canônicos na opção mydestination do main.cf. No nosso caso definimos como nomes canônicos apenas o localhost, com e sem FQDN. O domínio exemplo.com não está listado pois ele existe apenas como domínio hospedado. Para quebrar essa regra precisamos mexer no main.cf, o que é relativamente difícil.
  2. NUNCA inserir o nome do domínio hospedado como um apelido de domínio virtual. Isso é feito com a opção virtual_alias_domains do main.cf. Como não usamos essa opção em nossas configurações, será difícil que esta regra seja quebrada.
  3. NUNCA configurar mailbox virtuais coringas como apelidos. Por exemplo, isso não pode nunca como apelido: @exemplo.com @exemplo.com.br. Esse apelido redireciona tudo do domínio exemplo.com para o domínio exemplo.com.br, sendo que a parte do usuário é apenas copiada. Mas isso pode: @exemplo.com eumesmo@exemplo.com. Esse é um 'pega tudo' (catch-all) que aceita todos os emails, mesmo de usuários que não existem, e os encaminha para uma conta específica. Essa regra pode ser quebrada facilmente com uma configuração errada no ViMbAdmin, então tome cuidado pra não fazer besteira lá.

Ufa! Essa parte foi mais longa e chata do que eu imaginei que seria. Pelo menos consegui falar tudo que era importante sobre o Postfix. Há configurações que eu não mencionei, mas você pode ler a documentação do main.cf pra tirar suas dúvidas adicionais.