====== SPF check con Postfix ====== Installare il pacchetto Debian **postfix-policyd-spf-python**. Secondo quanto riportato dal sito **[[http://www.openspf.org/Software|openspf.org]]** l'implementazione Python è tecnicamente superiore a quella Perl. Secondo le specifiche **[[https://tools.ietf.org/id/draft-ietf-spfbis-4408bis-09.html|Sender Policy Framework]]** si possono effettuare dei controlli di validità durante una sessine SMTP verificando il contenuto dei comandi **HELO/EHLO** e **MAIL FROM**. Per soddisfare il controllo SPF su **MAIL FROM** il provider mittente deve aggiungere al DNS un record di tipo **TXT** relativamente al dominio mittente, un esempio per example.org: example.org. IN TXT "v=spf1 a:mail.example.org -all" Per soddisfare il check SPF su **HELO/EHLO** si deve anzitutto configurare correttamente il comando HELO sul server di posta che invia i messaggi, supponendo che il comando sarà **EHLO mail.example.org** e che un record di tipo **A** sia correttamente configurato per quel nome, si deve aggiungere un record **TXT** del tipo: mail.example.org. IN TXT "v=spf1 a -all" **ATTENZIONE**! Nei **record TXT** è necessario specificare **il nome esatto** del **dominio** e quello dell'**host**, inoltre il nome dell'host deve avere un corrispondente record di tipo **A** (IPv4) ed eventualmente di tipo **AAAA** (IPv6). Non è possibile definire i nome dell'host con un **CNAME** poiché il software Bind non accetta che un ''CNAME'' coesista con altri record, in questo caso un ''TXT''. ===== Configurazione ===== Il file di configurazione del programma è **/etc/postfix-policyd-spf-python/policyd-spf.conf**. debugLevel = 2 TestOnly = 1 HELO_reject = Fail Mail_From_reject = Fail PermError_reject = False TempError_Defer = False skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1 Il parametro **HELO_reject** determina il comportamento durante il check di **HELO/EHLO**, l'impostazione predefinita **Fail** significa che il reject avviene solo nel caso di SPF **Fail**, cioè di una situazione esplicitamente vietata. Si può essere più restrittivi con l'opzione **SPF_Not_Pass**, in tal caso il reject avviene anche nei casi di **Softfail** (//weak statement//, ad esempio la clausola ''~all''), **Neutral** (il DNS fornisce informazioni, ma vuote) e **PermError** (es. record SPF non valido). L'impostazione predefinita prevede il log su **/var/log/syslog**. Attenzione al parametro **TestOnly** che fa **esattamente il contrario di quello che si intuisce**! Impostando **TestOnly = 1** significa che **il filtro è attivo** (restituisce a Postfix il codice dell'azione da intraprendere), invece con un valore zero si ha solo il log del risultato, ma nessuna azione conseguente. Attenzione che il **reload** o il **restart** del servizio dopo aver cambiato configurazione non esiste, in quanto il processo viene avviato da Postfix solo quando necessario (vedi più avanti la configurazione). Pertanto in caso di variazione della configurazione è necessario fare il **restart di Postfix**. ===== Manual Testing ===== Per verificare il funzionamento del programma con la configurazione corrente è sufficiente eseguire da linea di comando **policyd-spf**, sullo standard input si forniscono alcune righe che caratterizzano un messaggio di posta, seguite da una **riga vuota**: request=smtpd_access_policy protocol_state=RCPT protocol_name=ESMTP helo_name=testhost.rigacci.org queue_id=8045F2AB23 instance=12345.6789 sender=test.sender@rigacci.org recipient=test.recipient@rigacci.org client_address=192.222.46.168 client_name=testhost.rigacci.org Questi sono i parametri che Postfix passa ad un altro programma quando esegue una **SMTP access policy delegation request**, la documentazione si trova in **[[https://www.postfix.org/SMTPD_POLICY_README.html|Postfix SMTP Access Policy Delegation]]**. **ATTENZIONE**: Il **sender** che viene passato da Postfix è il contenuto del **MAIL FROM** della sessione SMTP, **non è** l'eventuale contenuto dell'header **From:**. Infatti il controllo viene effettuato ancora prima che venga ricevuto il contenuto del messaggio con tutti gli header. Questo è un problema abbastanza importante perché un sender malevolo può forgiare il MAIL FROM in modo che sia compatibile con l'IP sorgente (la verifica SPF viene soddisfatta) e poi inserire un header **From:** a piacimento. Purtroppo i client di posta mostrano come mittente il contenuto dell'header, mentre l'originale MAIL FROM di solito è visibile solo nel sorgente del messaggio, generalmente nell'header **Return-Path:**. Per fare una verifica di coerenza fra **MAIL FROM** e header **From:** è possibile aggiungere a Postfix un controllo con **[[opendmarc|opendmarc]]**. Il programma risponde con qualcosa del tipo: action=550 5.7.23 Message rejected due to: SPF fail - not authorized. Please see http://www.openspf.net/Why?s=mfrom;id=... L'invocazione da riga di comando risponde ad **una sola richiesta**. ===== IPv6 e record AAAA ===== Nei record SPF è possibile indicare direttamente anche degli indirizzi IPv6, usando la sintassi **%%ip6:2a01:4f8:d16:1355::2%%**. Più comodo è indicare il nome di un host, con la sintassi **%%a:testhost.rigacci.org%%** si includono automaticamente tutti i record di tipo **A** (IPv4) e di tipo **AAAA** (IPv6) associati al nome. Nel test del paragrafo precedente è possibile specificare un indirizzo IPv6 come //client_address//. ===== Problema record TXT ed helo_name ===== **ATTENZIONE**! Il programma è predisposto per effettuare due controlli SPF, il primo è su **HELO/EHLO**, il secondo su **MAIL FROM**, sono entrambi comandi usati durante la sessione SMTP. Per il controllo HELO/EHLO il programma **policyd-spf** richiede il **record TXT** di **//helo_name//** prima di richidere quello del dominio del **//sender//**. Se tale record esiste, viene eventualmente utilizzato il suo contenuto SPF per controllare l'indirizzo IP di //client_address//. Per questo motivo - quando si configura un server di posta - è opportuno controllare l'**//helo_name//**: se ad esso è **associato un record TXT**, questo deve includere l'indirizzo IP che verrà usato come **//client_address//**. Ad ogni modo - dopo che **policyd-spf** ha controllato la corrispondenza fra SPF di //helo_name// e //client_address// - verrà fatto anche il controllo tra SPF del dominio di //sender// e il //client_address//. ===== Problema envelope_sender e From ===== Una mail può contendere informazioni non coerenti sul mittente, tale informazione infatti compare sia nell'header **From:** che nell'**envelope sender**, cioè quello che compare come **Return-Path:** nel messaggio ricevuto. Si tratta di due informazioni distinte che è possibile configurare in modo indipendente soprattutto quando si desidera **forgiare una mail**. Se esiste l'envelope sender il controllo SPF viene fatto su questo ed è possibile creare una mail con un **From:** spoofed che sarebbe altrimenti stato bloccato dalla logica di SPF. FIXME Come fare ad evitare questo? ===== Configurazione di Postfix ===== Anzitutto si configura Postfix in modo che attivi uno **Unix socket** collegato al programma **policyd-spf**; nel file di configurazione **/etc/postfix/master.cf** si deve aggiungere: policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf Il socket viene creato in **/var/spool/postfix/private/policyd-spf**. Si deve quindi configurare Postfix per aggiungere il controllo SPF alle **smtpd_recipient_restrictions**, di solito subito dopo il **reject_unauth_destination**. Nel file **/etc/postfix/main.cf** si imposta: smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, ... reject_unauth_destination, check_policy_service unix:private/policyd-spf Il programma **policyd-spf** non viene eseguito immediatamente, ma quando necessario; cioè quando viene ricevuto un messaggio da controllare. In quel momento risulterà un processo a nome dell'utente **postfix** del tipo: spawn -z -n policyd-spf -t unix user=policyd-spf argv=/usr/bin/policyd-spf inoltre a nome dell'utente **policyd** risulta: /usr/bin/python3 /usr/bin/policyd-spf ===== Web References ===== * **[[https://www.linode.com/docs/email/postfix/configure-spf-and-dkim-in-postfix-on-debian-9/|Configure SPF and DKIM With Postfix on Debian 9]]**