Dodici build

Un server di posta self-hosted che arriva davvero nella inbox

Postfix, Dovecot e rspamd su una singola istanza, con SPF, DKIM e DMARC configurati correttamente e un passaggio di verifica che legge le intestazioni del ricevente.

Cosa costruisce questa guida

Un server di posta completo per un singolo dominio: Postfix per il trasporto, Dovecot per IMAP e consegna locale, rspamd per il filtraggio e la firma DKIM, e i tre record DNS che determinano se i grandi provider mettono la tua posta nella inbox o in una cartella che nessuno apre. Invia, riceve, autentica e non è un relay aperto.

Gestire la propria posta è un consiglio fuori moda e per buone ragioni. La deliverability è la parte difficile, non il software. Se sbagli il DNS, il Postfix più curato del mondo invierà messaggi nel vuoto.

Prima di iniziare

  • Una R-8 o superiore. Il filtraggio è CPU-bound e rspamd userà volentieri ogni core che gli dai durante un'ondata di spam.
  • Un dominio di cui controlli il DNS e pazienza per la propagazione.
  • Reverse DNS impostato sull'indirizzo dell'istanza verso il nome del tuo server di posta. È modificabile dal pannello ed è obbligatorio: i riceventi rifiutano mittenti non risolvibili.
  • Un ticket al supporto per chiedere se la porta 25 in uscita è aperta sulla tua istanza. Chiedi prima di iniziare, non dopo.
  • mail.example.com in tutto. Sostituisci con i tuoi.

1. Hostname e DNS

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

Pubblica questi record ora, perché il passaggio dei certificati richiede il record A e la firma richiede un posto per la chiave. I valori nella tabella indicano a cosa serve ogni record, non cosa incollare.

RecordNomeContenuto
A / AAAAmailGli indirizzi dell'istanza dal pannello
MX@10 mail.example.com.
TXT@v=spf1 mx -all
TXT_dmarcv=DMARC1; p=none; rua=mailto:[email protected]; adkim=s; aspf=s
PTRindirizzo istanzamail.example.com — impostato nel pannello

Il record SPF dice: i miei MX inviano la mia posta, tutto il resto è falsificato. Hard fail invece di soft fail, perché ~all invita i riceventi a fare la propria scelta e la loro scelta non sarà quella generosa. DMARC inizia a p=none così raccogli i report per una settimana prima che qualcosa venga rifiutato per tuo conto.

2. Certificati

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

Nessun servizio è in ascolto sulla porta 80, quindi la modalità standalone è la strada più semplice. I hook di rinnovo arrivano alla fine, quando i daemon esistono per il reload.

3. Postfix

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

Ora imposta la configurazione del trasporto. Ogni riga qui sotto è intenzionale; postconf le scrive in place così non c'è editor da sbagliare:

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"

La riga più importante è smtpd_relay_restrictions. Termina con reject_unauth_destination, che impedisce a tutta internet di usare la tua macchina per inviare la sua posta. Un relay aperto ti fa finire in blacklist in poche ore e viola la politica di uso accettabile.

Abilita la porta submission per i tuoi client, con autenticazione richiesta e nessun accesso anonimo:

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

Caselle in Maildir sotto un singolo utente di sistema mantiene questa build semplice. Crea l'utente e lo storage:

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

Scrivi /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
  }
}

Crea una casella. Il comando chiede due volte e scrive un hash, mai la password in chiaro:

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

Genera la chiave di firma, poi pubblica la parte pubblica:

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

Il comando stampa un record DNS su standard output. Pubblicalo come record TXT su mail._domainkey.example.com, esattamente come stampato, unendo i segmenti tra virgolette secondo le istruzioni del tuo provider DNS. Poi di' a rspamd dove si trova la chiave, in /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;

Collega il milter e imposta una password per l'interfaccia web:

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

Incolla l'hash risultante in /etc/rspamd/local.d/worker-controller.inc come password = "...". Raggiungi l'interfaccia tramite tunnel SSH piuttosto che aprire la porta 11334 al mondo.

6. Avvia tutto

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

Aggiungi un hook di rinnovo così il nuovo certificato arriva a entrambi i daemon:

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

Verifica

Tre test. Il primo è locale, il secondo è quello che conta, il terzo è quello che ti tiene fuori dalle blacklist.

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

Poi invia un messaggio dal tuo nuovo server a una casella che possiedi presso un grande provider di webmail, apri il messaggio ricevuto e leggi le intestazioni raw. Cerchi una riga:

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

Tre passaggi e hai finito. Un dkim=none significa che rspamd non sta firmando, quindi controlla rspamadm configdump dkim_signing. Un spf=fail quasi sempre significa che il messaggio è partito su IPv6 mentre il tuo record SPF copre solo l'indirizzo v4 del MX.

Infine, dimostra che non sei un relay. Da qualsiasi altra macchina, connettiti e prova a inviare posta tra due domini che non possiedi:

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

Il risultato corretto è una reiezione allo stadio del destinatario: 554 5.7.1 Relay access denied. Qualsiasi altra cosa significa che hai configurato una macchina che verrà abusata entro la giornata, e dovresti fermarti e rileggere il passo tre.

Dopo

Lascia DMARC a p=none per una settimana e leggi i report aggregati. Quando mostrano solo il tuo server che firma la tua posta, passa a p=quarantine, poi p=reject due settimane dopo. Aggiungi il backup fuori nodo per /var/vmail finché ci sei, perché la posta è l'unica cosa di cui gli utenti non hanno mai una seconda copia, e il nostro add-on di backup scrive in un sito diverso dall'istanza.

Pronto quando lo sei

Scegli una città. Scegli una dimensione. Paga in criptovaluta.

Nessun modulo su chi sei, nessuna attesa per l'approvazione di una persona, nessuna chiamata per verificare nulla. La fattura viene saldata e le credenziali arrivano nella tua casella di posta.