Configurare il Sender Rewriting Scheme (SRS) su qmail

10 luglio 2023 by Roberto Puzzanghera 0 commenti

SPF è in conflitto con il reindirizzamento delle email. SRS è un metodo che consente di risolvere questo problema mediante la riscrittura degli indirizzi email.

Configurazione

Configurare srsfilter in modo tale che il programma sia lanciato ogni qual volta viene ricevuto un messaggio per l'utente srs:

echo "| /var/qmail/bin/srsfilter" > /var/qmail/alias/.qmail-srs-default

Quindi creare e configurare un dominio virtuale da usare esclusivamente per l'SRS. Si tenga presente questo dominio virtuale non deve essere creato, come siamo abituati a fare, dal programma vadddomain, poichè esso ha il solo scopo di lanciare srsfilter attraverso l'account fittizio alias/.qmail-srs-default che abbiamo creato prima. Notare la  differente sintassi di questa linea nel file virtualdomains rispetto ai domini virtuali regolari:

echo srs.mydomain.tld:srs >> /var/qmail/control/virtualdomains

Quell'srs dopo i due punti : sarà usato da qmail-local come un prefisso negli indirizzi locali associati a srs.mydomain.tld e sarà gestito da .qmail-srs-default, dal momento che nessun altro utente srs esiste. Per esempio:

2023-06-20 22:55:51.265166500 starting delivery 62: msg 32560286 to local srs-SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld

Fare riferimento alla "bibbia" Life With Qmail per comprendere meglio la logica sottostante, specialmente per quanto concerne i concetti relativi a virtual domains, aliases, .qmailextensions addresses.

Aggiungere srs.mydomain.tldrcpthosts di modo che qmail-smtpd sappia che deve spedire localmente i messaggi per quel dominio. Non aggiungerlo al file control/locals altrimenti il file virtualdomains sarà ignorato e srsfilter non verrà lanciato.

echo srs.mydomain.tld >> /var/qmail/control/rcpthosts

Porre srs.mydomain.tld nel file srs_domain, di modo che srsfilter lo utilizzi nella riscrittura degli indirizzi per tutti i domini virtuali. Creare anche il file srs_secret. E' una stringa casuale che serve a generare e controllare gli indirizzi SRS.

echo srs.mydomain.tld > /var/qmail/control/srs_domain
echo "xxxxxxxxxxxxxxxxxxxxxx" > /var/qmail/control/srs_secrets

Queste sono le uniche impostazioni obbligatorie; vedere i link in testa a questa pagina per avere informazioni riguardanti gli altri parametri che è possibile impostare.

Naturalmente è necessario dotare, nel proprio DNS, il dominio srs_domain appena creato di un record MX valido e anche di un record SPF come il seguente:

srs.mydomain.tld. IN TXT "v=spf1 a mx -all"

Dovremmo aver già creato un analogo record SPF anche per il dominio che compare in control/me. Se non lo si è ancora fatto, sarà bene farlo ora.

Possiamo ora riavviare qmail e testare il nostro sistema SRS.

Test

Andremo a testare la capacità del nostro sistema SRS di riscrivere gli indirizzi nel caso estremo di un forwarder non funzionante. Useremo un account gmail.com come mittente originale, dal momento che gmail è noto per essere un provider molto restrittivo e con un sistema anti spam efficientissimo.

In ciò che segue mydomain.tld è un dominio virtuale nello stesso server dove abbiamo configuraro SRS, srs.mydomain.tld è il dominio SRS definito in control/srs_domain, sender@gmail.com è il mittente originale del messaggio, mentre fake@remotedomain.tld è l'account inesistente ove il forwarder dovrebbe reindirizzare la posta che gli viene recapitata. Naturalmemnte essa verrà respinta e la nostra MTA dovrà eseguire la riscrittura (attraverso il programma srsfilter) e notificare il mittente originale senza violare le regole SPF.

Creare un forwarder nel proprio server, tale che i messaggi verso srstest@mydomain.tld siano reindirizzati a fake@remotedomain.tld:

echo "&fake@remotedomain.tld" > ~vpopmail/domains/mydomain.tld/.qmail-srstest
chown vpopmail:vchkpw ~vpopmail/domains/mydomain.tld/.qmail-srstest
chmod 600 ~vpopmail/domains/mydomain.tld/.qmail-srstest

Nel server remotedomain.tld, disabilitare chkuser nel proprio run file (commentare CHKUSER_START=ALWAYS) e impostare il file .qmail-default del dominio remotedomain.tld in modo che i messaggi per le mailbox inesistenti non vengano cancellati, ma respinti

|~vpopmail/bin/vdelivermail '' bounce-no-mailbox

Dal momento che fake@remotedomain.tld è un destinatario inesistente, remotedomain.tld ci rimanderà indietro il messaggio, e noi dovremo informare sender@gmail.com in accordo con le regole SRS, dopo la riscrittura dell'indirizzo.

Vediamo il viaggio di questo messaggio nella rete

Questo invece è ciò che si vede dai nostri log di qmail.

1. qmail-smtpd riceve e accetta il messaggio dal mittente orginale

2023-06-20 22:54:52.607641500 tcpserver: pid 16574 from 209.85.128.49 
2023-06-20 22:54:52.627258500 tcpserver: ok 16574 smtp.mydomain.tld:10.0.0.4:25 mail-wm1-f49.google.com:209.85.128.49::44523 
2023-06-20 22:55:13.058900500 qlogenvelope: result=accepted code=250 reason=rcptto detail=chkuser  
       helo=mail-wm1-f49.google.com  
       mailfrom=sender@gmail.com  
       rcptto=srstest@mydomain.tld  <---- questo è il forwarder
       ................ 
       qp= pid=16574

2. qmail-send passa il messaggio al forwarder srstest@mydomain.tld

2023-06-20 22:55:19.493086500 info msg 32560286: bytes 3377 
       from <sender@gmail.com>
       qp 16615 uid 89 
2023-06-20 22:55:19.493086500 starting delivery 60: msg 32560286 
       to local mydomain.tld-srstest@mydomain.tld <---- qmail converte srstest@mydomain.tld in mydomain.tld-srstest@mydomain.tld e tratta il risultato come se mydomain.tld fosse un indirizzo locale
2023-06-20 22:55:19.493087500 status: local 1/10 remote 0/20 
2023-06-20 22:55:19.495105500 delivery 60: success: did_0+1+0/qp_16617/

Vediamo un po' più in dettaglio le cose:

  1. qmail apre il file control/virtualdomains alla ricerca di una riga relativa al dominio destinatario ovvero mydomain.tld. Ecco il contenuto di quella riga:
    mydomain.tld:mydomain.tld
    Ora, i due campi prima e dopo i : non sono affatto un doppione. Quello alla sinistra è il dominio, mentre quello alla destra è l'utente il cui file .qmail andrà a gestire i messaggi per quel dominio.
  2. qmail antepone il campo alla destra dei due punti : all'indirizzo destinatario, che diventa quindi mydomain.tld-srstest@mydomain.tld, e tratta mydomain.tld come un indirizzo locale a cui recapitare il messaggio.
  3. qmail-local cerca l'utente mydomain.tld (tecnicamente è un semplice utente, prima ancora che un dominio) nel file users/assign (in realtà la sua versione compilata users/cdb) trovando qualcosa del genere:
    +mydomain.tld-:mydomain.tld:89:89:/home/vpopmail/domains/mydomain.tld:-::
    e ne ricava la cartella home, che in questo esempio è /home/vpopmail/domains/mydomain.tld.
  4. qmail-local apre dunque la cartella home e cerca il file srstest/.qmail che dovrà gestire la spedizione del messaggio (delivery). Se non lo trova cercherà nell'ordine un file ~mydomain.tld/.qmail-srstest e infine un file ~mydomain.tld/.qmail-default.
  5. Nel nostro caso esiste il file .qmail-srstest e, trattandosi del forwarder creato prima, istruisce qmail-send affinché giri il messaggio a qualcun alttro.

3. L'indirizzo del primo mittente viene riscritto in SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld e il messaggio spedito al server remoto da qmail-remote

2023-06-20 22:55:19.495905500 info msg 32560301: bytes 3491 
       from <SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld>   <----- il controllo SPF, se effettuato, sarebbe soddisfatto
       qp 16617 uid 89 
2023-06-20 22:55:19.495918500 starting delivery 61: msg 32560301 
       to remote fake@remotedomain.tld 
2023-06-20 22:55:19.495920500 status: local 0/10 remote 1/20 
2023-06-20 22:55:23.822750500 delivery 61: success: 
       <From:SRS0=jiQ3=CI=gmail.com=sender@srs.domain.tld_To:fake@remotedomain.tld>_<remoteip>_accepted_message./Remote_host_said:_25> 

4. qmail-smtpd riceve il messaggio di rifiuto (bounce, in realtà nel caso il server remoto abbi la teconologia SRS esso sarà lui stesso in grado di inviare il messaggio di rifiuto a gmail.com senza passare per mydomain.tld)

2023-06-20 22:55:24.049537500 tcpserver: pid 16687 from <remoteip>
2023-06-20 22:55:24.049945500 tcpserver: ok 16687 smtp.mydomain.tld:10.0.0.4:25 <remoteip>.<remotehost>:<remoteip>::37391 
2023-06-20 22:55:44.826126500 qlogenvelope: result=accepted code=250 reason=rcptto detail=chkuser  
       helo=<remotehelo> 
       mailfrom=        <------ null sender, dato che si tratta di un messaggio di sistema
       rcptto=SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld  <------- il destinatario ha il dominio definito in srs_domain
       ................. 
       qp= pid=16687 

5. qmail-send spedisce il bounce all'indirizzo locale SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld, che ha il dominio SRS che noi abbiamo legato a srsfilter

2023-06-20 22:55:51.265166500 info msg 32560286: bytes 5688 
       from <> <------- null sender, l'SPF è soddisfatto
       qp 16716 uid 89
2023-06-20 22:55:51.265166500 starting delivery 62: msg 32560286 
       to local srs-SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld <------- il prefisso srs fa in modo che il messaggio sia gestito dall'account srs di default, che a sua volta lancerà srsfilter
2023-06-20 22:55:51.265167500 status: local 1/10 remote 0/20 
2023-06-20 22:55:51.270712500 delivery 62: 
       success: srsfilter:_qp_16720/did_0+0+1/   <------- srsfilter in azione... lui sa cosa fare di quell'indizzo

Anche qui è necessario mettere bene a fuoco cosa succede "dietro le quinte"

  1. qmail riceve un messaggio per un utente del dominio srs.mydomain.tld e controlla la presenza di una riga che il campo srs.mydomain.tld alla sinistra dei due punti : nel file virtualdomains:
    srs.mydomain.tld:srs
  2. La parte alla destra dei due punti : viene anteposto all'indirizzo locale del ricevente, che diventa quindi srs-SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld, che ha ora ha il prefisso srs. Questo prefisso rappresenta l'utente il cui file .qmail dovrà gestire la spedizione del messaggio.
  3. qmail-local apre il file users/assign (in realtà la sua versione compressa users/cdb) alla ricerca di una riga che abbia srs nel primo campo ma non lo trova.
  4. Dato che non esiste alcun utente srs, viene cercato un alias alias/.qmail-srs, che non viene nemmeno trovato. In ultimis viene individuato il file alias/.qmail-srs-default, che funge da file .qmail deputato alla gestione del messaggio.
  5. Il file alias/.qmail-srs-default contiene le istruzioni per lanciare srsfilter.
  6. srsfilter è in grado di "smontare" l'indirizzo SRS0=jiQ3=CI=gmail.com=sender@srs.mydomain.tld per ricavare l'indirizzo del destinatario ultimo, che sarà sender@gmail.com.

6. qmail-send spedisce il bounce al mittente originale, il campo mailfrom è il null sender <>

2023-06-20 22:55:51.271507500 info msg 32560301: bytes 5707 
       from <>      <------ null sender
       qp 16720 uid 1000 
2023-06-20 22:55:51.271507500 starting delivery 63: msg 32560301 
       to remote sender@gmail.com 
2023-06-20 22:55:51.271508500 status: local 0/10 remote 1/20 
2023-06-20 22:55:51.915441500 delivery 63: 
       success: <From:_To:sender@gmail.com>_74.125.133.26_accepted_message./Remote_host_said:_250_2.0.0_OK__1687294551_f7-20020adff8c700000>

e gmail mostrerà un controllo SPF avvenuto con successo. Questa la parte importante dell'intestazione così come viene vista da sender@gmail.com:

Delivered-To: sender@gmail.com
[...]
Return-Path: <> Received: from smtp.mydomain.tld (smtp.mydomain.tld. [94.23.219.84]) by mx.google.com with ESMTPS id v28-20020a5d591c000000b0030e57d7da1dsi2291075wrd.363.2023.06.21.00.15.28 for <sender@gmail.com> [...] Received-SPF: pass (google.com: domain of postmaster@smtp.mydomain.tld designates <smtp.mydomain.tld IP> as permitted sender) client-ip=<smtp.mydomain.tld IP>; Authentication-Results: mx.google.com; dkim=temperror (no key for signature) header.i=@smtp.remotedomain.tld header.s=default header.b=M9b4zh72; spf=pass (google.com: domain of postmaster@smtp.mydomain.tld designates <smtp.mydomain.tld IP> as permitted sender) smtp.helo=smtp.mydomain.tld smtp.helo=smtp.mydomain.tld
[...]
Date: 20 Jun 2023 22:55:59 +0200 From: postmaster@smtp.remotedomain.tld <---- <bouncefrom>@<bouncehost> To: sender@gmail.com Subject: failure notice Hi. This is the qmail-send program at smtp.remotedomain.tld. <--- control/bouncehost
I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. <fake@remotedomain.tld>: Sorry, no mailbox here by that name. (#5.1.1) --- Below this line is a copy of the message. Return-Path: <SRS0=YBjh=CJ=gmail.com=sender@srs.mydomain.tld>

Si noti come il controllo SPF sia stato fatto su smtp.mydomain.tld,ovvero il dominio contenuto in control/me, dato che il messaggio verso il mittente originale è stato spedito dal null sender <>. Questo dominio è stato recuperato dall'HELO. Questa è la ragione per cui dobbiamo definire un record SPF anche per il dominio posto in control/me.

Il bounce che abbiamo reindirizzato ha il campo From: postmaster@smtp.remotedomain.tld. Come si può notare, l'indirizzo è stato ricavato dai file control/bouncefromcontrol/bouncehost.

Aggiungi un commento