User Tools

Site Tools


doc:appunti:linux:sa:postfix

This is an old revision of the document!


Postfix

Configurazione

Il file di configurazione principale è /etc/postfix/main.cf. Per vedere tutti i parametri di configurazione in uso (le impostazioni di default e quelle specificate) si esegue postconf(1). Per vedere solo le impostazioni modificate rispetto al default aggiungere l'opzione -n.

La stessa utility postconf(1) può essere usata per editare da riga di comando il file di configurazione.

Apertura porta 25

Per mettere Postfix in ascolto su tutte le interfacce includere in /etc/postfix/main.cf:

inet_interfaces = all

Utilizzo delle Maildir

La configurazione predefinita di Postfix è di consegnare la posta locale nella Unix mbox /var/mail/login, per utilizzare la $HOME/Maildir basta aggiungere in /etc/postfix/main.cf:

home_mailbox = Maildir/

Attenzione alla posta per root, se in /etc/aliases non viene definito un alias, Postfix decide di consegnarla a nobody che probabilmente non ha un home directory né una Maildir, pertanto va a finire in /var/mail/nobody.

Sempre in main.cf si imposta la dimensione massima della mailbox (file) e del singolo messaggio. Utilizzando le Maildir non ha molto senso la dimensione della mailbox perché non viene gestita come singolo file, pertanto si disabilita impostando zero:

mailbox_size_limit = 0
message_size_limit = 52428800

Procmail

Per indicare a Postfix di effettuare la consegna locale tramite procmail si aggiunge la seguente direttiva in /etc/postfix/main.cf:

# Use procmail for local delivery.
mailbox_command = /usr/bin/procmail -a "$EXTENSION"

Il passaggio di ulteriori parametri con l'opzione -a è facoltativo. Ogni utente potrà configurarsi le proprie regole $HOME/.procmailrc, vedere questo esempio.

Maildrop

Un'alternativa a procmail è maildrop che tra le altre cose consente la gestione della quota volontaria (bisogna che tutti i servizi SMTP/IMAP/POP collaborino a mantenere $HOME/Maildir/maildirsize). In questo caso basta mettere:

# Use maildrop for local delivery.
mailbox_command = /usr/bin/maildrop

Questa configurazione usa maildrop come local delivery agent, non troppo efficiente ma consente ampia libertà all'utente Unix di configurarsi filtri, forward, ecc. In alternativa si usa il direct delivery, vedere Postfix + Maildrop Howto.

Con l'installazione predefinita Debian si deve abilitare il comportamento predefinito di maildrop in /etc/maildroprc:

DEFAULT="$HOME/Maildir"

Ogni utente può configurare il funzionamento di maildrop con un proprio $HOME/.mailfilter. Vedere questo esempio.

Domini virtuali

Per una configurazione minimale basta dichiarare l'elenco dei domini virtuali gestiti e memorizzare la mappa degli alias in un file Berkeley DB. Queste le direttive da mettere in /etc/postfix/main.cf:

virtual_alias_domains = virtual.domain1.com virtual.domain2.com
virtual_alias_maps = hash:/etc/postfix/virtual_alias_maps

Il file virtual_alias_maps.db (l'estensione .db è sottointesa nel file di configurazione) viene compilato a partire dal file di testo virtual_alias_maps, di questo tipo:

user.name@virtual.domain1.com  username1
user.name@virtual.domain2.com  username2, username3
user.name@virtual.domain2.com  email@other.host.com

La compilazione avviene con il il comando

postmap virtual_alias_maps

File map di dominio multipli

Una configurazione più complessa prevede che l'elenco dei domini sia in un file separato e l'elenco degli alias sia suddiviso in tanti file, uno per dominio.

virtual_alias_domains = /etc/postfix/virtual_alias_domains
virtual_alias_maps = hash:/etc/postfix/virtual_alias_maps

L'elenco dei domini è un semplice file di testo /etc/postfix/virtual_alias_domains.

Gli alias per ogni dominio sono contenuti in altrettanti file di testo /etc/postfix/virtual_alias/*.map. Per assemblare tutti i virtual alias map in un unico DB Berkley si può usare il seguente Makefile:

all: virtual_alias_maps.db

virtual_alias_maps.in:
        touch virtual_alias_maps.in

virtual_alias_maps.db: virtual_alias_domains virtual_alias/*.map virtual_alias_maps.in
        @echo '#' > virtual_alias_maps.in
        @echo '# WARNING!!! This file is auto-generated: do not edit!' >> virtual_alias_maps.in
        @echo '# Edit instead .map files under virtual_alias directory and re-run the "make" command.' >> virtual_alias_maps.in
        @echo '#' >> virtual_alias_maps.in
        cat virtual_alias/*.map >> virtual_alias_maps.in
        postmap virtual_alias_maps.in
        mv virtual_alias_maps.in.db virtual_alias_maps.db

In questo caso l'aggiunta di un dominio richiede il reload di Postfix, mentre l'aggiunta di un alias richiede solo la ricompilazione del virtual_alias_maps.db.

Problema virtual_alias_domains, myorigin e mydestination

Dopo che un indirizzo è stato valutato come locale (quando il dominio è contenuto in virtual_alias_domains), viene consultata la virtual_alias_maps per identificare l'account Unix a cui consegnare il messaggio. La mappa contiene infatti righe di questo tipo:

nome.cognome@domain.tld    login_name

A tutti gli effetti si ha quindi un destinatario locale non qualificato; in questo caso il destinatario viene qualificato automaticamente con $myorigin, diventando l'indirizzo login_name@$myorigin. È quindi necessario che $myorigin sia contenuto in $mydestination perché la consegna venga effettuata.

Il pacchetto Postfix di Debian configura myorigin = /etc/mailname e giustamente mette lo stesso mailname anche in mydestination. Se però si configura un virtual domain con lo stesso nome, otterremo il seguente warning nei file di log:

warning: do not list domain domain.tld in BOTH mydestination and virtual_alias_domains

Se davvero si deve gestire un virtual domain con quel nome, la soluzione più corretta è utilizzare un nome fittizio per myorigin e aggiungere quello in mydestination:

myorigin = myserver
mydestination = myserver localhost.localdomain localhost

Crittografia TLS

Per abilitare il TLS bisogna anzitutto generare il certificato (autofirmato). L'installazione predefinita di Postfix usa il certificato /etc/ssl/certs/ssl-cert-snakeoil.pem e la corrispondente chiave /etc/ssl/private/ssl-cert-snakeoil.key, noi creeremo due file:

  • /etc/postfix/ssl/postfix.crt
  • /etc/postfix/ssl/postfix.key

Questo è uno script basato sull'analogo exim-gencert:

#!/bin/sh -e
 
DIR=/etc/postfix/ssl
CERT=$DIR/postfix.crt
KEY=$DIR/postfix.key
 
# valid for four years
DAYS=1461
 
if [ [ -f $CERT ] && [ -f $KEY ]; then
  echo "[*] $CERT and $KEY exists!"
  exit 0
fi
 
SSLEAY="$(tempfile -m600 -pexi)"
 
cat > $SSLEAY <<EOM
RANDFILE = $HOME/.rnd
[ req ]
default_bits = 1024
default_keyfile = postfix.key
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
countryName = Country Code (2 letters)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company; recommended)
organizationName_max = 64
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_max = 64
commonName = Server name (eg. ssl.domain.tld; required!!!)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 40
EOM
 
echo "[*] Creating a self signed SSL certificate for Postfix!"
echo "    Please enter the hostname of your MTA at the Common Name (CN) prompt!"
echo "    "
openssl req -config $SSLEAY -x509 -newkey rsa:1024 -keyout $KEY -out $CERT -days $DAYS -nodes
rm -f $SSLEAY
 
chown root:postfix $KEY $CERT $DH
chmod 640 $KEY $CERT $DH
 
echo "[*] Done generating self signed certificates for postfix!"

Editare /etc/postfix/main.cf e impostare:

# TLS parameters
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/postfix/ssl/postfix.crt
smtpd_tls_key_file = /etc/postfix/ssl/postfix.key

Riavviare Postfix e verificare che il server annunci STARTTLS tra le opzioni disponibili:

server:~# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.rigacci.org ESMTP Postfix (Debian/GNU)
EHLO test
250-mail.rigacci.org
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

Autenticazione SMTP con SASL su PAM

Questa autenticazione si basa sul sistema PAM (in pratica loing e password di /etc/shadow) tramite il demone /usr/sbin/saslauthd. La catena di autenticazione è la seguente:

  • Postfix ⇒ saslauthd ⇒ PAM ⇒ /etc/shadow

In alternativa è possibile appoggiare Postfix all'autenticazione Courier o Dovecot (sistemi POP/IMAP) per sfruttare ad esempio l'autenticazione con utenti virtuali usando l'indirizzo email invece del login Unix.

Installare i pacchetti sasl2-bin e libsasl2-modules.

Attenzione: Debian fa girare Postfix in un chroot, quindi il socket di sasl2 deve stare in esso. Eventualmente Leggere le istruzioni in /usr/share/doc/sasl2-bin/README.Debian.gz.

Configurare /etc/default/saslauthd impostando:

START=yes
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"

Se si fanno girare altri clienti di saslauthd (ad esempio l'autenticazione Apache con libapache2-mod-authn-sasl conviene rendere raggiungibile il socket anche dal suo percorso tradizionale, con un symlink:

systemctl stop saslauthd.service
rmdir /var/run/saslauthd
ln -s /var/spool/postfix/var/run/saslauthd /var/run
systemctl start saslauthd.service

Invece di PAM si potrebbe utilizzare direttamente il file /etc/shadow impostando l'opzione MECHANISMS=“shadow”, ma non c'è alcun reale vantaggio.

Poiché abbiamo spostato il socket nella chroot di postfix, informiamo il gestore dei pacchetti Debian:

dpkg-statoverride --add root sasl 750 /var/spool/postfix/var/run/saslauthd

Per vedere se l'opzione è stata attivata si usa dpkg-statoverride --list.

Testare il funzionamento del demone di autenticazione (l'utente che chiede l'autenticazione deve appartenere al gruppo sasl):

testsaslauthd -u myusername -p mypassword -f /var/spool/postfix/var/run/saslauthd/mux

ATTENZIONE! Il test usa il MECHANISMS di autenticazione SASL indicato in /etc/default/saslauthd (default PAM), non l'eventuale metodo authdaemond configurato in /etc/postfix/sasl/smtpd.conf. Quindi il test con indirizzo email come login non funziona.

Aggiungere l'utente postfix al gruppo sasl:

adduser postfix sasl

Configurare postfix mettendo in /etc/postfix/sasl/smtpd.conf

pwcheck_method: saslauthd
mech_list: PLAIN LOGIN

Aggiungere nella configurazione principale /etc/postfix/main.cf

# Enable authentication via saslauthd.
smtpd_sasl_auth_enable = yes
# Set the service name passed to saslauthd.
smtpd_sasl_local_domain =

Riavviare postfix con systemctl restart postfix.service.

Verificare che l'autenticazione sia annunciata, deve comparire la stringa AUTH LOGIN PLAIN:

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.rigacci.org ESMTP Postfix (Debian/GNU)
EHLO test
250-mail.rigacci.org
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

Per consentire il relay della posta agli utenti autenticati si aggiunge in /etc/postfix/main.cf:

smtpd_recipient_restrictions =
        permit_sasl_authenticated,
        ...
        reject_unauth_destination

Per richiedere obbligatoriamente l'uso della crittografia durante l'autenticazione, si aggiunge anche la direttiva (ATTENZIONE! in questo modo AUTH viene annunciato solo dopo STARTTLS):

smtpd_tls_auth_only = yes

Il parametro di cui sopra è implicito se si attiva smtpd_tls_security_level = encrypt.

Autenticazione SMTP su Courier Authdaemon

ATTENZIONE: se si utilizza l'autenticazione Dovecot invece di Courier, la configurazione è diversa (e anche un po' più semplice), vedere Postfix SASL over Dovecot Auth.

Postfix può utilizzare l'autenticazione fornita da Courier Authdaemon invece di appoggiarsi al demone saslauthd e al sottostante sistema PAM. Questo può tornare utile ad esempio se è attiva l'autenticazione /etc/courier/userdb che utilizza l'indirizzo di posta elettronica come login, al posto dello username Unix.

La configurazione è del tutto simile al caso saslauthd/PAM, cambia solo il file /etc/postfix/sasl/smtpd.conf:

pwcheck_method: authdaemond
authdaemond_path: /var/run/courier/authdaemon/socket
mech_list: PLAIN LOGIN

ATTENZIONE: Postfix (da Debian 5 Lenny in poi) gira in ambiente chroot (/var/spool/postfix/), così anche saslauthd; pertanto il socket di Authdaemon deve trovarsi in esso. La directory authdaemon appartiene a courier:courier (almeno in Debian Stretch), nel nostro caso deve essere accessibile a saslauthd che viene eseguito da postfix.

Questa ricetta è stata verificata su Debian 9 Stretch, verificare il proprietario e i permessi della directory originale /var/run/courier/authdaemon prima di spostarla nel chroot e aggiustare di conseguenza. Ad esempio per Debian 8 Jessie sostituire gruppo e utente courier con daemon.

mkdir -p /var/spool/postfix/var/run/courier/authdaemon
chown root:courier /var/spool/postfix/var/run/courier/
chown courier:courier /var/spool/postfix/var/run/courier/authdaemon/
chmod 0755 /var/spool/postfix/var/run/courier/authdaemon/

dpkg-statoverride --add courier courier 755 /var/spool/postfix/var/run/courier/authdaemon
adduser postfix courier

È necessario rendere disponibile il socket sia alla posizione originale (per i servizi Courier POP/IMAP) sia nel chroot di Postfix. Il sistema più moderno è un mount bind. Invece di aggiungere una entry in /etc/fstab, vedere più avanti come montare in automatico la directory con il sistema di init systemd.

mount /var/run/courier/authdaemon /var/spool/postfix/var/run/courier/authdaemon \
    -t bind -o defaults,nodev,bind

Una alternativa obsoleta (valida fino alla Debian 6 Squeeze) era creare un symlink. Questo non funziona più con le distribuzioni moderne, perché la gerarchia /var/run/ è in tmpfs e viene cancellata ad ogni reboot.

# Obsolete: use only in Debian <= 6 (Squeeze).
systemctl stop courier-authdaemon.service
rm -r /var/run/courier/authdaemon
ln -s /var/spool/postfix/var/run/courier/authdaemon /var/run/courier/authdaemon
systemctl start courier-authdaemon.service

Socket in /var/run/ e nel chroot di Postfix: problema con tmpfs

Nelle moderne distribuzioni Debian (da 7 Wheezy in poi) la directory /var/run/ viene creata in tmpfs e quindi al reboot è totalmente vuota. Questo è un problema perché la soluzione con il link simbolico vista al paragrafo precedente non sopravvive al reboot. Una soluzione poco elegante è modificare lo script /etc/init.d/courier-authdaemon, in modo che crei il link prima di avviare il servizio; inoltre questo è sconsigliato se si utilizza il moderno systemd (a partire da Debian 8 Jessie).

Quindi la soluzione ottimale è utilizzare un mount bind della directory che contiene il socket e incaricare systemd di effettuare il mount prima di avviare Postfix. Il punto di montaggio deve essere creato come visto nel paragrafo precedente, la mount unit va creata in /etc/systemd/system/, deve avere il nome esatto var-spool-postfix-var-run-courier-authdaemon.mount e contiene:

[Unit]
Description=Mount Courier Authdaemon into Postfix chroot
Requires=courier-authdaemon.service
After=courier-authdaemon.service

[Mount]
What=/var/run/courier/authdaemon
Where=/var/spool/postfix/var/run/courier/authdaemon
Type=bind
Options=defaults,nodev,bind

[Install]
WantedBy=postfix.service

Infine si abilita la unit:

systemctl daemon-reload
systemctl enable var-spool-postfix-var-run-courier-authdaemon.mount

Al successivo reboot troveremo il socket authdaemon disponibile nel chroot di Postfix.

Smarthost

Per consegnare tutta la posta in uscita ad un relay SMTP si aggiunge in /etc/postfix/main.cf:

relayhost = smtp.example.org

Se lo smarthost richiede autenticazione con login e password questi sono i parametri necessari:

relayhost = smtp.example.org
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_mechanism_filter = plain, login
smtp_sasl_security_options =
smtp_tls_security_level = may

L'opzione smtp_tls_security_level definisce se deve essere usata una connessione TLS. Ricordarsi che se si vuole utilizzare SSL, si deve installare il pacchetto libsasl2-modules.

Le credenziali per l'autenticazione vanno messe nel file /etc/postfix/sasl_passwd che deve essere compilato con postmap:

smtp.example.org login:password

Blacklist e altre restrizioni

Per bloccare il relaying non autorizzato e per proteggersi con la blacklist zen.spamhaus.org sono state aggiunte le seguenti opzioni in /etc/postfix/main.cf:

# Restrictions upon recipient address.
smtpd_recipient_restrictions =
        permit_sasl_authenticated,
        permit_mynetworks,
        reject_rbl_client zen.spamhaus.org,
        reject_non_fqdn_sender,
        reject_non_fqdn_recipient,
        reject_unknown_sender_domain,
        reject_unauth_destination

È possibile aggiungere una whitelist/blacklist locale che agisce prima della blacklist basata su DNS:

smtpd_recipient_restrictions =
        permit_sasl_authenticated,
        ...
        check_sender_access hash:/etc/postfix/sender_access,
        reject_rbl_client zen.spamhaus.org,
        ...

Il file sender_access deve essere compilato con postmap ed avere il seguente formato:

myfriend@example.com   OK
junk@spam.com          REJECT
marketing@             REJECT
theboss@               OK
deals.marketing.com    REJECT
somedomain.com         OK

Esempio di RBL zen.spamhaus.org

In generale le RBL (real-time blackhole list) sono in effetti delle DNS-based Blackhole List cioè utilizzano il meccanismo del DNS per scoprire se un indirizzo IP è nella blacklist o meno.

Il funzionamento di zen.spamhaus.org è spiegato nella pagina Frequently Asked Questions, vediamo ad esempio come verificare lo stato dell'indirizzo IP 194.44.61.82. Anzitutto si deve invertire l'ordine degli ottetti e fare una query DNS sul nome 82.61.44.194.zen.spamhaus.org. È possibile effettuare da riga di comando Unix una richiesta per un record di tipo A (è la richiesta che effettua in automatico Postfix):

dig +short 82.61.44.194.zen.spamhaus.org @dns.provider.tld
127.0.0.4
127.0.0.3

anzitutto notiamo che la richiesta è stata inoltrata al server DNS dns.provider.tld, la risposta è stata positiva, con ben due risultati. I codici 127.0.0.x sono in effetti una convenzione di ciascuna RBL per significare lo stato dell'indirizzo IP; nel nostro caso risulta elencato sia in Spamhaus SBL CSS che in CBL.

Per avere un responso più descrittivo è possibile chiedere il record di tipo TXT:

dig +short -t TXT 82.61.44.194.zen.spamhaus.org @127.0.0.1
"https://www.spamhaus.org/query/ip/194.44.61.82"
"https://www.spamhaus.org/sbl/query/SBLCSS"

Attenzione al server DNS utilizzato! Alcuni server DNS pubblici e gratuiti (specificatamente quello di Google 8.8.8.8) non rispondono a questo tipo di query. Purtroppo un risultato negativo viene interpretato da Postifix come indirizzo IP pulito. È opportuno installare un server DNS locale per una maggiore efficienza delle interrogazioni.

smtpd_sender_restrictions

FIXME: Unificare con il paragrafo successivo.

Se si gestiscono numerosi domini locali è possibile fare un controllo sull'esistenza dell'indirizzo mittente, in pratica si rifiutano messaggi che hanno un mittente inesistente. Questo controllo è opportuno farlo solo per i domini locali, perché richiede un'interrogazione al server MX del mittente: host remoti potrebbero non gradire continue interrogazioni.

smtpd_sender_restrictions = hash:/etc/postfix/smtpd_sender_restrictions

nel file /etc/postfix/smtpd_sender_restrictions si mette:

domain1.com reject_unverified_sender
domain2.org reject_unverified_sender

Restrizioni sull'indirizzo mittente

Il controllo qui descritto va fatto solo sul servizio submission da parte di connessioni autenticate che chiedono il relay di un messaggio. Trattandosi di utenti con un account locale è possibile fare la verifica dell'indirizzo mittente e rifiutare messaggi da parte di indirizzi non esistenti.

Non è possibile fare tale controllo sulla normale porta SMTP (posta in arrivo da internet), perché la verifica del mittente richiederebbe una interrogazione sul server MX del mittente, non sempre possibile o accettata.

smtpd_sender_restrictions =
        hash:/etc/postfix/smtpd_sender_restrictions,
        check_sender_access hash:/etc/postfix/check_sender_access,
        reject

Le regole vengono applicte in seguito al comando MAIL FROM (smtpd_sender_restrictions), l'azione è determinata dal primo match. Il file /etc/postfix/smtpd_sender_restrictions elenca i domini locali con le relative azioni (vedere reject_unverified_sender e permit):

domain1.tld    reject_unverified_sender, permit
domain2.tld    reject_unverified_sender, permit
domain3.tld    reject_unverified_sender, permit

Eventuali eccezioni (mittenti non locali, ma che vengono accettati ugualmente) sono elencati in /etc/postfix/check_sender_access utilizzando la sintassi di una access table:

some.address@foreign.domain.tld    OK
other.address@other.domain.tld     OK
third.domain.tld                   OK
/etc/postfix/smtpd_sender_restrictions Rifiuta gli indirizzi non esistenti di domini locali, accetta gli indirizzi locali validi.
/etc/postfix/check_sender_access Eccezioni: accetta i mittenti elencati (sender whitelist).
reject Rifiuta tutti gli altri mittenti.

I messaggi rifiutati saranno evidenziati nel log con i seguenti errori (rispettivamente per indirizzi non validi di domini locali oppure per mittenti non locali rifiutati):

Sender address rejected: unverified address: User unknown in virtual alias table;
Sender address rejected: Access denied;

Con Postfix 2.11 la verifica dell'esistenza di un mittente viene fatta con un meccanismo analogo al comando VRFY del protocollo SMTP, in realtà lo scambio dati avviene via Unix socket con il processo verify lanciato al bisogno (vedere la riga opportuna in /etc/postfix/master.cf). Il processo verify resta in esecuzione solo per un paio di minuti e produce una cache delle risposte memorizzata in /var/lib/postfix/verify_cache.db.

Esiste il bug #578862, almeno fino a Postfix 2.11 (Debian 8 Jessie). Il file con la cache viene creato /var/lib/postfix/verify_cache.db, ma il processo verify esegue successivamente un chroot in /var/spool/postfix/ e pertanto produce un errore poiché tenta di chiudere l'inesistente file /var/spool/postfix/var/lib/postfix/verify_cache.db:

postfix/verify[22229]: close database /var/lib/postfix/verify_cache.db:
    No such file or directory (possible Berkeley DB bug)

Pare che il bug non abbia conseguenze (parola dell'autore di Postfix), per chi tuttavia preferisse non vederlo è possibile risolvere con un link simbolico:

mkdir -p /var/spool/postfix/var/lib/postfix
chown postfix.postfix /var/spool/postfix/var/lib/postfix
cp -p /var/lib/postfix/verify_cache.db /var/spool/postfix/var/lib/postfix/
ln -sf /var/spool/postfix/var/lib/postfix/verify_cache.db /var/lib/postfix/
chown -h postfix.postfix /var/lib/postfix/verify_cache.db

Restrizioni per localhost (es. PHP)

Per consegnare la posta in uscita ad un Postfix dallo stesso localhost esistono fondamentalmente due metodi:

  • Connessione TCP/IP su porta 25. Questa modalità può essere sperimentata ad esempio con il comando telnet localhost 25 utilizzando il linguaggio SMTP. Qualunque programma che giri su localhost e che possa aprire un socket TCP/IP può utilizzare questa modalità.
  • Apertura di un socket Unix. Questo è il metodo usato dai comandi mail o sendmail e l'impostazione predefinita della funzione mail() di PHP.

Nel primo caso i log segnalano qualcosa del genere:

postfix/smtpd[4283]: 3B544401A1: client=localhost[127.0.0.1]
postfix/cleanup[4287]: 3B544401A1: message-id=<23e2c7f-ef129-b1@texnet.it>
postfix/qmgr[3997]: 3B544401A1: from=<niccolo@texnet.it>, ...
postfix/smtp[4290]: 3B544401A1: to=<azz@azz.cc>, ...
postfix/qmgr[3997]: 3B544401A1: removed

nel secondo caso invece si ha:

postfix/pickup[5474]: 67F6A40310: uid=1006 from=<niccolo>
postfix/cleanup[5998]: 67F6A40310: message-id=<20140915092933.67F6A40310@texnet.it>
postfix/qmgr[3997]: 67F6A40310: from=<niccolo@texnet.it>, ...
postfix/smtp[5758]: 67F6A40310: to=<niccolo@rigacci.org>, ...
postfix/qmgr[3997]: 67F6A40310: removed

Nell'invio da parte della funzione mail() di PHP viene utilizzato l'utente generico del server web oppure l'utente specifico del sito web se si sta utilizzando una configurazione FastCGI e suEXEC.

L'invio su connessione SMTP per impostazione predefinita è libero da 127.0.0.0/8 (parametro mynetworks di Postfix). Un modo per limitarlo (accettando solo connessioni autenticate) è il seguente

smtpd_recipient_restrictions = permit_sasl_authenticated, reject

Relay to network

Per accettare la posta e farne il relay da un particolare indirizzo IP o network si usa la direttiva mynetworks di /etc/postfix/main.cf:

mynetworks = 127.0.0.0/8 192.168.2.0/24 82.61.251.143 [2b03:3610:cb00:124::1]/64

Notare che gli indirizzip IPv6 vanno racchiusi fra parentesi quadrate.

Modifica degli header

Esempio: come nascondere uno header Received: per non mostrare che la mail passa da un IP dinamico? Si aggiunge un file /etc/postfix/maps/header_checks con l'espressione regolare e l'azione:

/^Received: from mail.private.com/   IGNORE

quindi si aggiunge questo in /etc/postfix/main.cf:

# Filter unwanted headers.
# See http://www.postfix.org/header_checks.5.html
header_checks = regexp:/etc/postfix/maps/header_checks

Sender rewrite

È possibile riscrivere l'indirizzo di provenienza di una mail, utile soprattutto per le mail generate in automatico da account locale, che altrimenti potrebbero avere indirizzi brutti e poco graditi ai filtri antispam, del tipo root@localhost oppure nagios@host.domain.tld.

Postfix dispone della direttiva sender_canonical_maps; basta aggiungere in main.cf qualcosa del genere:

# Rewrite some sender addresses.
sender_canonical_maps = hash:/etc/postfix/sender_canonical

e predisporre il file /etc/postfix/sender_canonical:

root                  user@domain.tld
root@host.domain.tld  user@domain.tld

Il file deve essere compilato con postmap(1) per creare il relativo .db.

Destinatari locali non qualificati

Ad un destinatario privo di dominio (es. backup o root) viene aggiunto il dominio specificato dall'opzione myorigin, in Debian questo equivale al contenuto del file /etc/mailname.

Questa riscrittura avviene prima di applicare il contenuto di /etc/aliases. Pertanto gli alias specificati in /etc/aliases funzionano solo se il nome host specificato in /etc/mailname è uno dei domini riconosciuti come locali, cioè inclusi nell'opzione mydestination.

Messaggi di notifica a postmaster locale

I messaggi di notifica grave vengono inviati a postmaster, essendo un destinatario non qualificato viene trattato come descritto al paragrafo precedente.

Un host che non riceve mail da internet ma che vuole generare messaggi di sistema con mittente valido (quindi non locale) probabilmente ha myorigin non contenuto in mydestination. In questo caso c'è il rischio che i messaggi di notifica per postmaster@myorigin non arrivino a destinazione, in quanto non locali.

Conviene quindi dichiarare in /etc/postfix/main.cf:

mydestination = naxos.rigacci.org, localhost

# myorigin is not in mydestination and we use a smarthost:
# assure that notification messages can land somewhere locally.
bounce_notice_recipient = postmaster@localhost
2bounce_notice_recipient = postmaster@localhost

e in /etc/aliases:

postmaster:    user@localhost
root:          user@localhost

Delay Warning

Per impostazione predefinita Postfix non avvisa dei ritardi di consegna dei messaggi, se si vuole attivare questa opzione si imposta il parametro seguente:

delay_warning_time = 4h

Relay domains

To relay mail for non-local domains (domains not in mydestination and not in local virtual domains), use the relay_domains setting:

# Relay mail for non-local domains, separated by commas and/or whitespace:
relay_domains = www.mydomain.org, mydomain.org

If you want to relay mail to a specific host - eventually not the one listed in MX records - you must provide a specific transport map, writing a file /etc/postfix/transport with something like this:

mydomain.org  smtp:real.mx.host

Compile the file with postmap(1) and inform Postfix that you want to use it, in main.cf add:

# Some specific transports (e.g. smtp relay) are listed in this file:
transport_maps = hash:/etc/postfix/transport

With the same technique we can realay a single mailbox:

user@local.domain  smtp:remote.realay.host

HELO hostname

Some MTAs require that the HELO or EHLO hostname is a FQDN name that resolves to an A resource record or an address literal (see RFC2821).

Postfix will use the myhostname value for the HELO command, in a default Debian installation that is the simple hostname, without domain.

You can change the myhostname in /etc/postfix/main.cf or you can force the HELO name using smtp_helo_name setting, which defaults to myhostname:

smtp_helo_name = mail.mydomain.org
# If we don't have the name registered as an A record, use an IP literal:
#smtp_helo_name = [78.47.31.140]

Rimuovere messagi dalla coda

Per rimuovere un singolo messagio in base al sui ID:

postsuper -d 75F6F10039B

Per rimuovere tutti i messaggi ritardati per qualche motivo e rimasti in coda:

postsuper -d ALL deferred

Per forzare l'invio dei messaggi rimasti in coda, senza attendere il tempo naturale:

postfix flush

oppure:

postqueue -f

Limiti

Questi sono alcuni parametri che si possono impostare per limitare le risorse messe a disposizione dal server:

# Maximal number of Postfix child processes that provide a given service.
default_process_limit = 50
# The maximal size in bytes of a message, including envelope information. 
message_size_limit = 20971520
# Maximum number of recipients per message.
smtpd_recipient_limit = 20
smtpd_recipient_overshoot_limit = 4
local_recipient_limit = 20
relay_recipient_limit = 20
virtual_recipient_limit = 20
# Bounce headers only, not the message body (avoid to make backscatter SPAM).
bounce_size_limit = 1

Il parametro default_process_limit può essere scavalcato dall'impostazione maxproc di master.cf.

Messaggi DSN (delivery status notifications)

La configurazione predefinita di Postfix prevede la possibilità di richiedere una DSN all'invio del messaggio, vedere la capability DSN annunciata all'EHLO. Alcuni clienti email fanno questa richiesta per impostazione predefinita.

Nei log si trova traccia dell'invio di tale notifica:

postfix/bounce[27741]: B39AE1002D1: sender delivery status notification: 69D4E1002A6

Per disattivare questa capability basta aggiungere in /etc/postfix/main.cf:

# Disallow all use of DSN requests from the network.
smtpd_discard_ehlo_keywords = silent-discard, dsn

Verifica dei messaggi di errore (Delivery Status Notifications)

Per generare un messaggio di notifica si può usare l'interfaccia di compatibilità sendmail di Postfix. Ad esempio per generare un messaggio di notifica senza effettivamente mandare un messaggio ad un destinatario:

sendmail -bv name@domain.org
Mail Delivery Status Report will be mailed to <root>.

Se invece si vuole effettivamente effettuare un invio e ricevere una notifica dell'esito:

sendmail -v name@domain.org
Some text message...
.
Mail Delivery Status Report will be mailed to <root>.

SMTP over SSL su porta 465/tcp

Per avere una connessione cifrata è sufficiente attivare lo STARTTLS sulla porta standard 25, tuttavia può tornare utile abilitare una porta alternativa, ad esempio per quei provider che bloccano la porta 25 in uscita (notabilmente H3G dai suoi terminali mobili).

In questo caso si può usare la porta 465 TCP, storicamente usata per fare SMTP su SSL. SMTP su SSL differisce dal STARTTLS in quanto la connessione è cifrata via SSL da subito e non viene negoziata dal client con il comando STARTTLS.

ATTENZIONE poiché SMTP su SSL viene considerato superato da STARTTLS, alcuni decidono di fare STARTTLS sulla porta 465, forse una scelta un po' azzardata che contravviene il principio di minima sorpresa.

Con Postfix bisogna aver preparato il certificato SSL come visto sopra e quindi si aggiunge in /etc/postfix/master.cf:

smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  # Use the non-standard wrapper mode, i.e. direct SSL instead of STARTTLS.
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  # Allow only authenticated clients.
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject

Riavviando Postfix si vedrà che si pone in ascolto anche sulla porta 465/tcp. Nel mail.log si troveranno righe identificate da postfix/smtps/smtpd.

Meccanismi anti hammering

postfix-mx/anvil[919]: statistics: max connection rate 8/60s for (62.48.51.61:25:110.52.2.253) at Oct 15 23:26:21
postfix-mx/anvil[919]: statistics: max connection count 8 for (62.48.51.61:25:110.52.2.253) at Oct 15 23:26:21

SMTP su porta 587 TCP

Secondo il recente RFC 6409, l'invio di una mail da parte di un Mail User Agent (es. un programma come Thunderbird) andrebbe indirizzato al server SMTP sulla porta 587, dovrebbe essere autenticato con login e password, e sperabilmente crittografato tramite STARTTLS.

Con Postfix installato da pacchetto Debian si ha già una sezione predisposta in /etc/postfix/master.cf, basta togliere i commenti. La crittografia può essere obbligatoria (encrypt) oppure facoltativa (may). L'RFC la metterebbe facoltativa.

submission inet n       -       -       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject

Postgrey

Postgrey è una implementazione di greylisting per Postfix: le mail da un certo sender vengono rifiutate al primo tentativo e il sender viene inserito in una greylist per un breve periodo (default 300 secondi). Ad un tentetivo successivo la mail viene accettata. Il sender quindi resta inserito nella whitelist per un periodo abbastanza lungo (default 35 giorni).

Si installa il pacchetto Debain postgrey, il demone si pone in ascolto sulla porta 10023 dell'indirizzo localhost. In genere si aggiunge alle regole smtpd_recipient_restrictions in /etc/postfix/main.cf, ad esempio:

smtpd_recipient_restrictions =
    permit_sasl_authenticated,
    permit_mynetworks,
    check_policy_service inet:127.0.0.1:10023,
    reject_unauth_destination

Le opzioni si configurano in /etc/default/postgrey. Eventuali indirizzi whitelist si aggiungono in /etc/postgrey/whitelist_clients e etc/postgrey/whitelist_recipients.

doc/appunti/linux/sa/postfix.1573594892.txt.gz · Last modified: 2019/11/12 22:41 by niccolo