Fare il relay
Il nostro server di posta è quasi pronto per l’uso. Manca ancora un pezzo del puzzle. I nostri utenti possono già prelevare la posta ma devono essere in grado di poterla mandare. I server di posta sanno come mandare una mail tra loro guardando i record MX. Il server di posta ricevente accetterà volentieri ogni mail a lui destinata con un valido destinatario. I client mail invece devono prima mandare la mail al loro server di posta che poi la inoltra su internet. Ricevere una mail da un utente ed inoltrarla ad un altro server è chiamato fare il relay. Postfix agisce come un relay.
Perché i client mail non funzionano allo stesso modo? Non possono semplicemente guardare il record MX e mandare la mail al server destinazione? Tecnicamente si. Ma spesso gli utenti sono seduti a casa usando una linea DSL. E questi IP di rete sono di solito bloccati per mandare mail. Alcuni ISP bloccano la porta SMTP nei loro router. E la maggior parte dei server di posta controllano le blacklist in tempo reale per bloccare indirizzi IP DSL. La ragione è che gli utenti residenziali tendono maggiormente ad avere PC Wind*ws infetti che mandano spam.
Sto correndo troppo? Ok, Affrontiamo i vari scenari uno alla volta.
Mail in arrivo
Quando qualcuno su internet manda una mail a john@example.org, qualche altro server di posta consegnerà la mail usando SMTP al nostro server di posta. Postfix determinerà che è responsabile per gli indirizzi mail nel dominio example.org e accetterà la mail. John potrà poi usare POP3 o IMAP per scaricare la mail dal nostro server.
Mail in uscita (senza autenticazione)
John è su internet da qualche parte e vuole mandare una mail a lisa@example.com. Il nostro server di posta non è responsabile per il dominio “example.com”. Riceve la mail di John e dovrebbe inoltrarla (relay) al server di posta responsabile per gli indirizzi mail …@example.com. Potrebbe sembrare uno scenario innocuo ma il nostro server di posta deve rifiutarsi:
Perché? Perché chiunque può affermare di essere John e far inoltrare mail al nostro server di posta. Se un malintenzionato (come uno spammer) mandasse tonnellate di spam per conto di John usando il nostro server allora le organizzazioni accuseranno noi, come operatori di un server di posta, di mandare spam. Il nostro server di posta sarebbe quello che chiamano un open relay. E questo non è quello che vogliamo perché il nostro server di posta verrebbe messo nelle blacklist e non sarete più in grado di mandare mail alla maggior parte degli altri server. Quindi senza alcuna prova che John sia effettivamente John, il nostro server deve rifiutare la mail.
Mail in uscita (con autenticazione)
Quindi come fa John a provare la sua identità? deve usare SMTP autenticato. E’ simile al caso precedente ma il client mail manderà anche il suo username e password.
Naturalmente ci assicureremo che la sua autenticazione avvenga su una connessione criptata così che la password di John è offuscata.
Postfix: opzione “mynetworks”
In aggiunta ad usare l’autenticazione SMTP, possiamo dire a Postfix di fare sempre il relay mail per certi indirizzi IP. L’opzione mynetworks contiene la lista di reti o indirizzi IP di cui ci fidiamo. Di solito qui si definisce la nostra rete locale. Il motivo per cui John ha dovuto autenticarsi nell’esempio sopra è perché non sta mandando la mail da una rete locale.
Se i nostri utenti usano la webmail che gira sul nostro server, allora non devono autenticarsi. Roundcube manda le mail a localhost che è fidato secondo le impostazioni di mynetworks.
Far usare Dovecot a Postfix per l’autenticazione
Abilitare l’autenticazione SMTP in Postfix è sorprendentemente facile. Abbiamo già configurato Dovecot per quanto riguarda l’autenticazione utente. Facciamola utilizzare da Postfix dicendogli di chiedere al server Dovecot di verificare username e password. Postfix ha bisogno di qualche piccola configurazione extra. Lanciamo questi comandi nella shell:
postconf smtpd_sasl_type=dovecot
postconf smtpd_sasl_path=private/auth
postconf smtpd_sasl_auth_enable=yes
Questo abilita l’autenticazione SMTP e dice a Postfix che può parlare con Dovecot tramite un file socket situato in /var/spool/postfix/private/auth. Ricordate che Postfix gira in una cartella chroot isolata? Questa è in /var/spool/postfix. Non può accedere ad alcun file fuori da questa cartella. Ma fortunatamente nella sezione precedente abbiamo editato il file /etc/dovecot/conf.d/10-master.conf e fatto mettere a Dovecot un file socket in /var/spool/postfix/private/auth per permettere la comunicazione da Postfix.
Abilitare la criptazione
Le seguenti impostazioni abilitano la criptazione, definiscono chiave e certificato e forzano l’autenticazione solo su connessioni criptate:
postconf smtpd_tls_security_level=may postconf smtpd_tls_auth_only=yes postconf smtpd_tls_cert_file=/etc/letsencrypt/live/webmail.example.org/fullchain.pem postconf smtpd_tls_key_file=/etc/letsencrypt/live/webmail.example.org/privkey.pem postconf smtp_tls_security_level=may
Nota #1
In passato potreste aver configurato smtpd_recipient_restrictions per limitare il relay ad utenti autenticati. Attualmente Postfix ha un’opzione chiamata “smtpd_relay_restrictions” che gestisce le richieste per il relay nella fase “RCPT TO” della finestra SMTP. Essenzialmente funziona come il caro vecchio “smtpd_recipient_restrictions” ma è controllato prima. smtpd_relay_restrictions ha delle impostazioni predefinite ragionevoli quindi il relay autenticato funziona automaticamente.
Nota #2
Postfix 2.10 ha cambiato completamente il comportamento delle impostazioni smtpd_*_restrictions. Se una restrizione fa rifiutare a Postfix una mail, aspetterà fino alla fine della linea “RCPT TO”. Leggete la documentazione di Postfix per una descrizione delle ragioni di questo cambiamento.
smtpd_tls_security_level è settato a “may” per permettere la comunicazione criptata quando Postfix riceve una mail. Questo si applica non solo agli utenti che mandano le mail ma anche ai server di posta che mandano le mail a noi. Potreste essere tentati di cambiarlo a “encrypt” che forzerebbe la criptazione e rifiuterebbe qualsiasi tentativo di creare una connessione SMTP non criptata. Sfortunatamente nel mondo ci sono ancora server di posta che non sono in grado di criptare e quindi non potrebbero consegnarci la posta. Quindi “may” è l’impostazione giusta. Lo stesso vale per smtp_tls_security_level per le mail in uscita mandate agli altri server di posta.
Anche se le mail possono venir consegnate non criptate dagli altri server, dobbiamo assicurarci che gli utenti non mandino accidentalmente (o per ignoranza) le loro password non criptate su internet. Ecco perché forziamo “smtpd_tls_auth_only=yes”. Ora i nostri utenti sono al sicuro.
Come funziona l’autenticazione SMTP
Siete curiosi di sapere com’è l’autenticazione SMTP a livello protocollo? Vediamolo insieme. Nelle versioni precedenti di questa guida abbiamo usato “telnet” per conneterci alla porta TCP 25 e parlare SMTP. Ora che forziamo la criptazione non possiamo fare l’autenticazione non criptata. Priviamo la parte non criptata:
telnet localhost smtp
Il server ci farà entrare:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail ESMTP Postfix (Debian/GNU)
Salutiamo educatamente:
ehlo example.com
Postfix presenterà la lista di funzionalità disponibili durante il dialogo SMTP:
250-mailtest
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
Spieghiamo brevemente cosa significano queste linee:
- PIPELINING: Questa è una funzionalità per velocizzare la comunicazione SMTP. Normalmente il sistema remoto deve aspettare una risposta ad ogni comando che invia. Il “pipelining” consente al server remoto di mandare pù comandi senza aspettare una risposta. Postfix salverà questi comandi e li eseguirà uno alla volta. Se diciamo a Postfix di proibire il “pipelining” disconnetterà il server remoto quando cerca di mandare più comandi senza aspettare la risposta appropriata. E’ perlopiù una funzionalità contro i programmi che mandano spam.
- SIZE 10240000: Il server remoto è autorizzato a mandare mail grandi al massimo 10 MB. E’ stato per lungo tempo un limite di grandezza massimo comune per le mail. Tuttavia oggigiorno 40 MB o più sono dimensioni sempre più comuni perché le mail sono diventate sempre più grandi.
- VRFY: Consente ai server remoti di verificare un dato nome o indirizzo email. Per esempio il server remoto potrebbe mandare “VRFY john” e il nostro server potrebbe rispondere “250 John Doe <john@example.org>”. Può essere usato per verificare se ad un certo destinatario è possibile consegnare la posta.
- ETRN: Un comando che un server remoto può mandare per far rispedire la coda delle mail per un certo dominio. Può essere usato se un sistema remoto ha avuto problemi tecnici e non ha potuto ricevere mail per un po’ di tempo. Manda il comando ETRN per far spedire al nostro server le mail in sospeso per tal dominio. E’ usato raramente.
- STARTTLS: Dice al sistema remoto che può commutare la connessione da non criptata a criptata mandando il comando “STARTTLS”. Comincerà poi a negoziare una connessione criptata con TLS. E’ paragonabile ad una connessione HTTP che di colpo commuta ad una connessione HTTPS criptata. Il vantaggio è che possiamo parlare SMTP sulla porta TCP 25 senza dover aprire una seconda porta TCP come la 465 (= porta “SSMTP” (SMTP sicuro): accetta solo connessioni criptate).
- ENHANCEDSTATUSCODES: Questo abilita più codici di ritorno a 3 cifre per vari stati. Vedete l’RFC2034 se siete curiosi.
- 8BITMIME: In tempi antichi SMTP processava solo caratteri 7-bit. Non era possibile trasferire caratteri speciali come “Ä” o “ß” senza codifiche speciali. 8BITMIME permette una trasmissione di mail usando caratteri 8-bit. Molte mail sono codificate apposta usando ISO8859-1 o UTF-8.
- DSN: Abilita DNS (delivery status notofication) che permette al mittente di controllare i messaggi che Postfix crea quando una mail non può essere consegnata come previsto.
Tuttavia manca una linea importante che ci permetterebbe di mandare il nostro username e password:
250-AUTH PLAIN LOGIN
Abbiamo detto a Postfix di permettere l’autenticazione solo quando la connessione è criptata. Quindi non ci viene offerta l’autenticazione su questa connessione in chiaro.
Siete ancora connessi? Bene. Abbiamo quindi bisogno di una connessione criptata usando TLS. Diamo STARTTLS:
STARTTLS
E il server risponderà:
220 2.0.0 Ready to start TLS
Ora però diventa complicato perché dovremmo parlare TLS che non è un linguaggio che gli umani parlano. Quindi usciamo usando il comando “QUIT”.
Ma possiamo usare OpenSSL per aiutarci con la decriptazione. Lanciamo:
openssl s_client -connect localhost:25 -starttls smtp
Ora vedrete molto output. OpenSSL si è connesso alla porta TCP 25 e ha lanciato il comando STARTTLS per passare ad una connessione criptata. Qualsiasi cosa scriviamo sarà criptato. Digitiamo:
ehlo example.com
E Postfix manderà una lista di possibilità che assomigliano a questo:
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
E ora che stiamo usando una connessione criptata, Postfix ci offre di autenticarci. Mandiamo quindi la stringa di autenticazione con una password codificata in Base64:
AUTH PLAIN am9obkBleGFtcGxlLm9yZwBqb2huQGV4YW1wbGUub3JnAHN1bW1lcnN1bg==
Il server accetterà l’autenticazione:
235 2.7.0 Authentication successful
Eccellente. Siamo loggati tramite SMTP. Disconnettiamoci da Postfix:
QUIT
Ciao:
221 2.0.0 Bye
L’autenticazione funziona. Ben fatto.
Password codificate in Base644
Vi starete chiedendo da dove ho tirato fuori quella lunga stinga criptica che a quanto pare contiene l’indirizzo email di John e la sua password. E’ semplicemente una versione codificata (non criptata!) in Base64 della stringa “john@example.org<NULL-BYTE>john@example.org<NULL-BYTE>summersun”.
Un modo per crearla è usare Perl:
perl -MMIME::Base64 -e
'print encode_base64("john@example.orgjohn@example.orgsummersun")';
La porta submission (opzionale)
Anche se ho parlato di SMTP sulla porta 25 per fare il relay delle mail, in realtà c’è un modo migliore: usare la porta submission sulla porta TCP 587 (come descritto nell’RFC 4409). L’idea è di usare la porta 25 per trasportare la posta (MTA) da server a server e la porta 587 per inviare la posta (MSA) da un utente ad un server di posta. Siccome molti utenti usano ancora SMTP di default, dovrete probabilmente usare entrambe le porte.
Editiamo il file /etc/postfix/master.cf e aggiungiamo un servizio per la porta submission come questo (attenzione all’indentazione dalla seconda linea in avanti). Non usate i servizi suggeriti e commentati in master.cf – ignorateli e basta.
submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_sasl_security_options=noanonymous
-o smtpd_sender_login_maps=mysql:/etc/postfix/mysql-email2email.cf
-o smtpd_sender_restrictions=reject_sender_login_mismatch
-o smtpd_sasl_local_domain=$myhostname
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
In pratica questo nuovo servizio usa il demone “smtpd” che è un pezzo di software che risponde se si apre una connessione SMTP sulla porta 25. Ma ha un paio di opzioni in più…
- in /var/log/mail.log segna la le connessioni sulla porta submission come “postfix/submission/smtpd” (syslog)
- forza la criptazione su questa porta (security level)
- forza l’autenticazione utente (sasl)
- assicura che un utente autenticato possa mandare solo mail per suo conto (sender_login_maps)
Riavviamo il server Postfix:
service postfix restart
I nostri utenti ora possono usare la porta submission per spedire mail.
Proteggersi contro indirizzi del mittente falsi
Aspetta un momento. Quindi possiamo essere sicuri che un utente può mandare mail solo se usa il proprio indirizzo come mittente? Fico. Come funziona? Guardate questa linea che abbiamo appena usato sopra quando abbiamo aggiunto il servizio submission:
smtpd_sender_login_maps=mysql:/etc/postfix/mysql-email2email.cf
smtpd_sender_login_maps è una mappatura Postfix con due colonne:
- l’indirizzo email che l’utente vuole usare come mittente
- l’username usato nell’autenticazione con il server di posta
Il motivo per cui uso la mappatura /etc/postfix/mysql-email2email.cf è che qui calza a pennello. Infatti mappa l’indirizzo mail con se stesso, se esiste. Confusi? Guardate la query SQL che la mappatura “email2email” lancia:
SELECT email FROM virtual_users WHERE email='%s'
Quando un utente vuole trasmettere una mail, Postfix cerca il mittente nella tabella virtual_users. Supponiamo che John voglia mandare una mail dal suo indirizzo “john@example.org”. Postfix controlla la tabella virtual_users se c’è una riga con un campo email come questo. Ne trova uno e ritorna il campo email – che è di nuovo l’indirizzo email. Postfix si aspetta di ottenere l’username usato per il login. Noi usiamo l’indirizzo email come username per il login – quindi la mappatura funziona. Solo se John provasse a mandare una mail con un mittente falso allora Postfix vedrebbe che non corrisponde al suo account, rifiutando la mail. Nel mail.log ci sarebbe qualcosa tipo:
NOQUEUE: reject: RCPT from foo.bar[…]: 553 5.7.1 <forged@email.address>: Sender address rejected: not owned by user john@example.org; from=<forged@email.address> to=<…>
E’ una vostra decisione se usare smtpd_sender_restrictions in questo modo.