Doze construções

Um servidor de e-mail auto-hospedado que realmente chega à caixa de entrada

Postfix, Dovecot e rspamd em uma única instância, com SPF, DKIM e DMARC configurados corretamente e uma etapa de verificação que lê os próprios cabeçalhos do lado receptor.

O que isto constrói

Um servidor de e-mail completo de domínio único: Postfix para transporte, Dovecot para IMAP e entrega local, rspamd para filtragem e assinatura DKIM, e os três registros DNS que decidem se grandes receptores colocam seu e-mail na caixa de entrada ou em uma pasta que ninguém abre. Ele envia, recebe, autentica e não é um relay aberto.

Administrar seu próprio e-mail é um conselho fora de moda e, em sua maioria, por um bom motivo. A entregabilidade é a parte difícil, não o software. Se o DNS estiver errado, o Postfix mais cuidadosamente configurado do mundo entrega mensagens direto no vazio.

Antes de começar

  • Um R-8 ou maior. A filtragem exige CPU e o rspamd usará alegremente cada núcleo que você der durante uma onda de spam.
  • Um domínio cujo DNS você controla, e paciência para a propagação.
  • DNS reverso configurado no endereço da instância para o hostname do seu e-mail. É editável no painel e é obrigatório: receptores rejeitam remetentes irresolvíveis.
  • Um ticket para o suporte perguntando se a porta 25 de saída está aberta na sua instância. Pergunte antes de construir, não depois.
  • mail.example.com em todo lugar. Substitua pelos seus.

1. Hostname e DNS

hostnamectl set-hostname mail.example.com
apt update && apt full-upgrade -y

Publique estes registros agora, porque a etapa do certificado precisa do registro A e a etapa de assinatura precisa de um lugar para colocar uma chave. Os valores na tabela são o que cada registro faz, não o que colar.

RegistroNomeConteúdo
A / AAAAmailOs endereços da instância no painel
MX@10 mail.example.com.
TXT@v=spf1 mx -all
TXT_dmarcv=DMARC1; p=none; rua=mailto:[email protected]; adkim=s; aspf=s
PTRendereço da instânciamail.example.com — definido no painel

O registro SPF diz: meus hosts MX enviam meu e-mail, todo o resto é forjado. Falha dura em vez de falha suave, porque ~all convida os receptores a tomar sua própria decisão e a decisão deles não será a generosa. DMARC começa em p=none para que você colete relatórios por uma semana antes que algo seja rejeitado em seu nome.

2. Certificados

apt install -y certbot
certbot certonly --standalone -d mail.example.com

Nada está ouvindo na porta 80 ainda, então o modo standalone é o caminho mais simples. Os hooks de renovação vêm no final, quando os daemons existirem para recarregar.

3. Postfix

DEBIAN_FRONTEND=noninteractive apt install -y postfix postfix-pcre dovecot-imapd dovecot-lmtpd rspamd redis-server

Agora defina a configuração de transporte. Cada linha abaixo é deliberada; postconf as escreve no lugar para que não haja editor para errar:

postconf -e "myhostname = mail.example.com"
postconf -e "mydestination = localhost"
postconf -e "smtpd_banner = \$myhostname ESMTP"
postconf -e "inet_interfaces = all"
postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtp_tls_security_level = dane"
postconf -e "smtpd_tls_mandatory_protocols = >=TLSv1.2"
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination"
postconf -e "smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unknown_recipient_domain reject_unauth_destination"
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "virtual_mailbox_domains = example.com"
postconf -e "smtpd_milters = inet:127.0.0.1:11332"
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
postconf -e "milter_default_action = accept"

A linha mais importante é smtpd_relay_restrictions. Ela termina com reject_unauth_destination, que é o que impede a internet inteira de usar sua máquina para enviar e-mail. Um relay aberto faz você ser listado em blocklists em horas e, além disso, viola os termos de uso.

Habilite a porta de submissão para que seus próprios clientes possam enviar, com autenticação exigida e sem acesso anônimo:

postconf -M submission/inet="submission inet n - y - - smtpd"
postconf -P "submission/inet/syslog_name=postfix/submission"
postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
postconf -P "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"

4. Dovecot

Caixas de correio em Maildir sob um único usuário do sistema mantém esta construção pequena. Crie o usuário e o armazenamento:

groupadd -g 5000 vmail
useradd -g vmail -u 5000 -d /var/vmail -m vmail
install -d -o vmail -g vmail -m 700 /var/vmail/example.com

Escreva /etc/dovecot/conf.d/99-local.conf:

mail_location = maildir:/var/vmail/%d/%n
mail_uid = vmail
mail_gid = vmail
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
ssl_min_protocol = TLSv1.2
auth_mechanisms = plain login
disable_plaintext_auth = yes

passdb {
  driver = passwd-file
  args = scheme=ARGON2ID username_format=%u /etc/dovecot/users
}
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

Crie uma caixa de correio. O comando solicita duas vezes e grava um hash, nunca a senha em si:

echo -n "[email protected]:" >> /etc/dovecot/users
doveadm pw -s ARGON2ID >> /etc/dovecot/users
chmod 640 /etc/dovecot/users
chgrp dovecot /etc/dovecot/users

5. rspamd e DKIM

Gere a chave de assinatura e publique a parte pública:

install -d -o _rspamd -g _rspamd -m 750 /var/lib/rspamd/dkim
rspamadm dkim_keygen -s mail -b 2048 -d example.com -k /var/lib/rspamd/dkim/example.com.mail.key
chown _rspamd:_rspamd /var/lib/rspamd/dkim/example.com.mail.key
chmod 400 /var/lib/rspamd/dkim/example.com.mail.key

Esse comando imprime um registro DNS na saída padrão. Publique-o como um registro TXT em mail._domainkey.example.com, exatamente como impresso, com os segmentos entre aspas unidos da forma que seu provedor de DNS espera. Depois diga ao rspamd onde a chave está, em /etc/rspamd/local.d/dkim_signing.conf:

path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector = "mail";
allow_username_mismatch = true;
use_domain = "header";
sign_authenticated = true;
sign_local = true;

Vincule o milter e defina uma senha para a interface web:

echo "bind_socket = \"127.0.0.1:11332\";" > /etc/rspamd/local.d/worker-proxy.inc
rspamadm pw

Cole o hash resultante em /etc/rspamd/local.d/worker-controller.inc como password = "...". Acesse a interface por um túnel SSH em vez de abrir a porta 11334 para o mundo.

6. Inicie tudo

systemctl enable --now redis-server rspamd dovecot postfix
postfix check
systemctl --no-pager --failed

Adicione um hook de renovação para que um novo certificado alcance ambos os daemons:

echo "systemctl reload postfix dovecot" > /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh

Verifique

Três testes. O primeiro é local, o segundo é o que importa, o terceiro é o que o mantém fora das blocklists.

echo | openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com 2>/dev/null | grep -E "subject=|Verify return"

Depois envie uma mensagem do seu novo servidor para uma caixa de correio que você possui em um grande provedor de webmail, abra a mensagem recebida e leia seus cabeçalhos brutos. Você procura uma linha:

Authentication-Results: mx.receiver.example;
  dkim=pass [email protected];
  spf=pass smtp.mailfrom=example.com;
  dmarc=pass (p=NONE) header.from=example.com

Três passagens e você termina. Um dkim=none significa que o rspamd não está assinando, então verifique rspamadm configdump dkim_signing. Um spf=fail quase sempre significa que a mensagem saiu via IPv6 enquanto seu registro SPF cobre apenas o endereço do MX v4.

Por fim, prove que você não é um relay. De qualquer outra máquina, conecte-se e tente enviar e-mail entre dois domínios que você não possui:

apt install -y swaks
swaks --to [email protected] --from [email protected] --server mail.example.com

O resultado correto é uma rejeição na etapa de destinatário: 554 5.7.1 Relay access denied. Qualquer outra coisa significa que você configurou uma máquina que será abusada em pouco tempo, e você deve parar e reler o passo três.

Depois

Deixe o DMARC em p=none por uma semana e leia os relatórios agregados. Quando eles mostrarem apenas seu próprio servidor assinando seu próprio e-mail, mude para p=quarantine e, duas semanas depois, para p=reject. Adicione backup fora do nó para /var/vmail enquanto estiver nisso, porque e-mail é a única coisa que os usuários nunca têm uma segunda cópia, e nosso add-on de backup grava em um site diferente da instância.

Pronto quando você estiver

Escolha uma cidade. Escolha um tamanho. Pague em cripto.

Sem formulários sobre quem você é, sem esperar aprovação de um humano, sem ligação para verificar nada. O pagamento é confirmado e as credenciais chegam na sua caixa de entrada.