Postfix Dovecot MySQL su Ubuntu 22.04

Introduzione

Questa guida vi accompagnerà passo dopo passo nella configurazione di un mail server completo e sicuro utilizzando Postfix (SMTP), Dovecot (IMAP/POP3), MariaDB (database utenti) e Rspamd (antispam). Il server utilizzerà esclusivamente connessioni crittografate con certificati Let’s Encrypt.

Al termine avrete un server email professionale con:

  • Domini e utenti virtuali gestiti via database
  • Crittografia TLS obbligatoria per tutte le connessioni
  • Filtri antispam avanzati
  • Protezione contro attacchi brute-force
  • Supporto per filtri Sieve lato server

1. Prerequisiti e Preparazione del Sistema

Requisiti Base

Per questa guida avrete bisogno di:

  • Una VPS con IP statico (consiglio Hetzner per affidabilità e prezzi)
  • Ubuntu 22.04 LTS installato
  • Un dominio registrato con accesso alla configurazione DNS
  • Almeno 2GB di RAM (4GB consigliati)

Configurazione DNS

Prima di iniziare, configurate correttamente i record DNS del vostro dominio:

# Record A per il server mail
mail.esempio.com    A    [IP_VPS]

# Record MX per il dominio
esempio.com         MX   10 mail.esempio.com

# Record PTR (reverse DNS) - da configurare nel pannello del provider VPS
[IP_VPS]           PTR  mail.esempio.com

# Record SPF per autorizzare il server a inviare mail
esempio.com         TXT  "v=spf1 mx -all"

Importante: Il record PTR deve corrispondere all’hostname del server. Verificate con:

hostname -f
# Deve restituire: mail.esempio.com

Installazione Pacchetti

Aggiorniamo il sistema e installiamo tutti i componenti necessari:

apt update && apt upgrade -y

apt install -y \
  mariadb-server \
  postfix postfix-pcre postfix-mysql \
  dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd \
  dovecot-mysql dovecot-sieve dovecot-managesieved \
  rspamd redis-server \
  certbot \
  pwgen \
  fail2ban \
  ufw

Durante l’installazione di Postfix, selezionate “Internet Site” e inserite il vostro dominio (esempio.com).

2. Certificati SSL/TLS con Let’s Encrypt

Generiamo subito i certificati SSL che proteggeranno tutte le comunicazioni:

# Fermiamo temporaneamente i servizi che usano la porta 80
systemctl stop apache2 nginx

# Generiamo il certificato con chiave RSA 4096 bit
certbot certonly --standalone --rsa-key-size 4096 -d mail.esempio.com

# Configuriamo il rinnovo automatico con riavvio servizi
cat > /etc/letsencrypt/cli.ini << EOF
post-hook = systemctl restart postfix dovecot
EOF

3. Configurazione Database MariaDB

Sicurezza Database

Prima di tutto, mettiamo in sicurezza MariaDB:

mysql_secure_installation

# Rispondete:
# - Set root password? [Y]
# - Remove anonymous users? [Y]
# - Disallow root login remotely? [Y]
# - Remove test database? [Y]
# - Reload privilege tables? [Y]

Creazione Database e Utente

Generiamo una password sicura per l'utente del database:

# Genera password di 30 caratteri
pwgen -s1 30
# Esempio output: rEfsoI2KSejLEHmDNvAYnVEHr8o1ig

Ora creiamo il database e le tabelle:

mysql -u root -p

-- Creazione database e utente
CREATE DATABASE mailserver;
CREATE USER 'mailuser'@'localhost' IDENTIFIED BY 'rEfsoI2KSejLEHmDNvAYnVEHr8o1ig';
GRANT ALL PRIVILEGES ON mailserver.* TO 'mailuser'@'localhost';
FLUSH PRIVILEGES;

USE mailserver;

-- Tabella domini
CREATE TABLE IF NOT EXISTS `virtual_domains` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Tabella utenti
CREATE TABLE IF NOT EXISTS `virtual_users` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `email` varchar(100) NOT NULL,
  `password` varchar(150) NOT NULL,
  `quota` bigint(20) NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Tabella alias
CREATE TABLE IF NOT EXISTS `virtual_aliases` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `source` varchar(100) NOT NULL,
  `destination` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

EXIT;

Aggiunta Domini e Utenti

Per aggiungere un dominio e un utente, prima generiamo una password criptata:

# Genera password utente
pwgen -s1 20
# Esempio: xK9mNp2Lq8Rt5Yw3Zb7

# Cripta la password con SHA256
doveadm pw -s SHA256-CRYPT
# Inserite la password quando richiesto
# Output esempio: {SHA256-CRYPT}$5$xvxyx8xOf5MSGsK.$zEBRszEg...

Ora aggiungiamo dominio e utente al database:

mysql -u root -p mailserver

-- Aggiungi dominio
INSERT INTO virtual_domains (name) VALUES ('esempio.com');

-- Aggiungi utente (usa l'hash generato sopra)
INSERT INTO virtual_users (domain_id, email, password) 
VALUES (1, 'info@esempio.com', '{SHA256-CRYPT}$5$xvxyx8xOf5MSGsK.$zEBRszEg...');

-- Aggiungi alias
INSERT INTO virtual_aliases (domain_id, source, destination) 
VALUES (1, 'postmaster@esempio.com', 'info@esempio.com');

EXIT;

4. Configurazione Postfix

File di Mapping MySQL

Creiamo i file che permettono a Postfix di interrogare il database:

# File: /etc/postfix/mysql-virtual-mailbox-domains.cf
cat > /etc/postfix/mysql-virtual-mailbox-domains.cf << EOF
user = mailuser
password = rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'
EOF

# File: /etc/postfix/mysql-virtual-mailbox-maps.cf
cat > /etc/postfix/mysql-virtual-mailbox-maps.cf << EOF
user = mailuser
password = rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'
EOF

# File: /etc/postfix/mysql-virtual-alias-maps.cf
cat > /etc/postfix/mysql-virtual-alias-maps.cf << EOF
user = mailuser
password = rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'
EOF

# Impostiamo i permessi corretti
chmod 640 /etc/postfix/mysql-*.cf
chown root:postfix /etc/postfix/mysql-*.cf

Configurazione main.cf

Configuriamo Postfix modificando il file principale:

# Backup del file originale
cp /etc/postfix/main.cf /etc/postfix/main.cf.backup

# Configurazione base
postconf -e "myhostname = mail.esempio.com"
postconf -e "mydomain = esempio.com"
postconf -e "myorigin = \$mydomain"
postconf -e "mydestination = localhost"
postconf -e "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"

# Domini e mailbox virtuali
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf"
postconf -e "virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf"
postconf -e "virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf"

# Autenticazione SASL via Dovecot
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_sasl_auth_enable = yes"
postconf -e "broken_sasl_auth_clients = yes"

# TLS/SSL
postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.esempio.com/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.esempio.com/privkey.pem"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtpd_tls_auth_only = yes"
postconf -e "smtp_tls_security_level = may"
postconf -e "smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1"
postconf -e "smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1"
postconf -e "smtpd_tls_mandatory_ciphers = high"
postconf -e "tls_high_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305"

# Restrizioni
postconf -e "smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination"
postconf -e "smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination"

# Limiti
postconf -e "message_size_limit = 52428800"
postconf -e "mailbox_size_limit = 0"

Configurazione master.cf

Abilitiamo la submission port (587) per l'invio autenticato:

# Modifichiamo /etc/postfix/master.cf
# Decommentiamo e modifichiamo le seguenti righe:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_auth_only=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

Creazione Utente e Directory Mail

# Creiamo utente e gruppo per le mailbox virtuali
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/vmail -m
chown -R vmail:vmail /var/vmail

Configurazione Autenticazione

Modifichiamo /etc/dovecot/conf.d/10-auth.conf:

# Meccanismi di autenticazione
auth_mechanisms = plain login

# Disabilita autenticazione in chiaro senza TLS
disable_plaintext_auth = yes

# Commenta la riga auth-system e decommenta auth-sql
#!include auth-system.conf.ext
!include auth-sql.conf.ext

Configurazione SQL

Creiamo /etc/dovecot/dovecot-sql.conf.ext:

driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=rEfsoI2KSejLEHmDNvAYnVEHr8o1ig

default_pass_scheme = SHA256-CRYPT

password_query = SELECT email as user, password FROM virtual_users WHERE email='%u'

user_query = SELECT email as user, \
  'vmail' as uid, 'vmail' as gid, \
  '/var/vmail/%d/%n' as home, \
  '*:storage=1G' as quota_rule \
  FROM virtual_users WHERE email='%u'

iterate_query = SELECT email AS user FROM virtual_users

Configurazione Mail Location

Modifichiamo /etc/dovecot/conf.d/10-mail.conf:

mail_location = maildir:~/Maildir
mail_uid = vmail
mail_gid = vmail
first_valid_uid = 5000
last_valid_uid = 5000

Configurazione SSL

Modifichiamo /etc/dovecot/conf.d/10-ssl.conf:

ssl = required
ssl_cert = 

Configurazione Master Services

Modifichiamo /etc/dovecot/conf.d/10-master.conf:

service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3-login {
  inet_listener pop3 {
    port = 0  # Disabilitato
  }
  inet_listener pop3s {
    port = 0  # Disabilitato
  }
}

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
  }
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
  }
}

service auth-worker {
  user = vmail
}

Abilitazione Sieve

Modifichiamo /etc/dovecot/conf.d/20-lmtp.conf:

protocol lmtp {
  mail_plugins = $mail_plugins sieve
}

E /etc/dovecot/conf.d/90-sieve.conf:

plugin {
  sieve = file:~/sieve;active=~/.dovecot.sieve
  sieve_global_path = /var/vmail/sieve/default.sieve
  sieve_dir = ~/sieve
  sieve_max_script_size = 1M
}

6. Configurazione Rspamd (Antispam)

Rspamd è un sistema antispam avanzato che proteggerà il server da spam e malware.

Configurazione Base

# Configuriamo rspamd per integrarsi con Postfix
cat > /etc/rspamd/local.d/worker-controller.inc << EOF
password = "\$2\$zy8npwwgqbpgo5ujnug6of3zy3rgpbmj\$k6mmm9xe3jugxr1bii4o5gxjfhqjjh4pg3iyhka4rq3479bjqzny";
enable_password = "\$2\$zy8npwwgqbpgo5ujnug6of3zy3rgpbmj\$k6mmm9xe3jugxr1bii4o5gxjfhqjjh4pg3iyhka4rq3479bjqzny";
EOF

# Configurazione milter
cat > /etc/rspamd/local.d/worker-proxy.inc << EOF
bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;
upstream "local" {
  default = yes;
  self_scan = yes;
}
EOF

# Aggiungiamo rspamd a Postfix
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"

# Riavviamo rspamd
systemctl restart rspamd

DKIM Signing

# Generiamo chiave DKIM
mkdir -p /var/lib/rspamd/dkim/
rspamadm dkim_keygen -b 2048 -s mail -k /var/lib/rspamd/dkim/mail.key > /var/lib/rspamd/dkim/mail.txt
chown -R _rspamd:_rspamd /var/lib/rspamd/dkim

# Configuriamo DKIM
cat > /etc/rspamd/local.d/dkim_signing.conf << EOF
selector = "mail";
path = "/var/lib/rspamd/dkim/\$selector.key";
allow_username_mismatch = true;
EOF

# Il record DNS DKIM da aggiungere si trova in:
cat /var/lib/rspamd/dkim/mail.txt

7. Configurazione Fail2ban

Proteggiamo il server da attacchi brute-force:

# Creiamo jail per Postfix
cat > /etc/fail2ban/jail.d/postfix.conf << EOF
[postfix-sasl]
enabled = true
filter = postfix-sasl
action = iptables-multiport[name=postfix-sasl, port="25,587,465", protocol=tcp]
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
EOF

# Jail per Dovecot
cat > /etc/fail2ban/jail.d/dovecot.conf << EOF
[dovecot]
enabled = true
filter = dovecot
action = iptables-multiport[name=dovecot, port="143,993,110,995", protocol=tcp]
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
EOF

# Riavviamo fail2ban
systemctl restart fail2ban

8. Configurazione Firewall

# Configuriamo UFW
ufw allow 22/tcp    # SSH
ufw allow 25/tcp    # SMTP
ufw allow 587/tcp   # Submission
ufw allow 143/tcp   # IMAP
ufw allow 993/tcp   # IMAPS
ufw allow 80/tcp    # HTTP (per Let's Encrypt)
ufw allow 443/tcp   # HTTPS

# Abilitiamo il firewall
ufw enable

9. Test e Verifica

Test Database

# Test mapping Postfix
postmap -q esempio.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
# Output atteso: 1

postmap -q info@esempio.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
# Output atteso: 1

postmap -q postmaster@esempio.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
# Output atteso: info@esempio.com

Test Servizi

# Verifica configurazione Postfix
postfix check

# Verifica configurazione Dovecot
dovecot -n

# Test connessione SMTP
telnet localhost 25
EHLO test
# Dovrebbe mostrare STARTTLS e AUTH

# Test IMAP
telnet localhost 143
a1 LOGIN info@esempio.com password
# Dovrebbe autenticarsi correttamente

Test SSL/TLS

# Test certificato SMTP
openssl s_client -connect mail.esempio.com:587 -starttls smtp

# Test certificato IMAP
openssl s_client -connect mail.esempio.com:993

Per configurare un client email (Thunderbird, Outlook, etc.), usate questi parametri:

  • Server IMAP: mail.esempio.com, Porta 993, SSL/TLS
  • Server SMTP: mail.esempio.com, Porta 587, STARTTLS
  • Username: indirizzo email completo (info@esempio.com)
  • Password: la password dell'utente
  • Autenticazione: Password normale

11. Manutenzione e Monitoraggio

Log Files

I log principali da monitorare:

# Log mail generale
tail -f /var/log/mail.log

# Log errori
tail -f /var/log/mail.err

# Log rspamd
tail -f /var/log/rspamd/rspamd.log

# Statistiche rspamd
rspamc stat

Backup

# Script backup database
#!/bin/bash
mysqldump mailserver > /backup/mailserver-$(date +%Y%m%d).sql

# Backup mailbox
rsync -av /var/vmail/ /backup/vmail/

# Backup configurazioni
tar czf /backup/mail-config-$(date +%Y%m%d).tar.gz \
  /etc/postfix /etc/dovecot /etc/rspamd

Aggiornamenti

# Aggiornamento sicuro del sistema
apt update
apt upgrade -y
systemctl restart postfix dovecot rspamd

Risoluzione Problemi Comuni

Errore "Relay access denied"

Verificate che l'utente sia autenticato e che il dominio sia configurato correttamente nel database.

Certificati non funzionanti

Verificate i permessi e i percorsi dei certificati. Dovecot necessita del carattere < prima del percorso.

Mail in spam

Assicuratevi di aver configurato correttamente SPF, DKIM e DMARC. Verificate anche il PTR record.

Conclusioni

Ora avete un mail server completo e sicuro. Ricordate di:

  • Monitorare regolarmente i log
  • Mantenere il sistema aggiornato
  • Fare backup regolari
  • Testare periodicamente la deliverability
  • Aggiornare i certificati SSL prima della scadenza

Per ulteriore sicurezza, considerate l'implementazione di SPF, DKIM e DMARC record DNS completi per migliorare la reputazione del vostro server.