L'uso di questo sito
autorizza anche l'uso dei cookie
necessari al suo funzionamento.
(Altre informazioni)

Wednesday, May 21, 2014

Sendmail and procmail mailer for egress mail filtering.

Ok, this is basically an annotated version of recipe 6.8 from O'Reilly's sendmail cookbook. As a bonus, though, it contains also a useful (if spooky) working example AND the relevant procmail configuration. It takes about a day to setup and test without guidance, so enjoy. If you need to be told how to rebuild sendmail.cf from .mc or what is mailertable, this post will be Tralfamadorian to you - go read the Bat Book.

The italian version is here.

Summary

  • Create the sendmail configuration to use mailertable and the procmail mailer.
/etc/mail/sendmail.mc
dnl Enable support for the mailertable
FEATURE(`mailertable')
dnl Add procmail to the list of available mailers
MAILER(procmail)
  • Ath the bottom, insert local rules to fend off loops (watch out for the TAB between '>' e '$')
/etc/mail/sendmail.mc
LOCAL_CONFIG
# Add .PROCMAIL to the pseudo-domain list
CP.PROCMAIL
LOCAL_RULE_0
# Strip .PROCMAIL and send via esmtp
R$+ < @ $+ .PROCMAIL . >        $#esmtp $@ $2 $: $1<@$2>
  • Set up mailertable to route mail sent to specific domains (or even all mail, as in the last line) through the procmail mailer:
/etc/mail/mailertable
example.com       procmail:/etc/mail/procmailrcs/spam-filter
wrotethebook.net  procmail:/etc/mail/procmailrcs/spam-filter
fake.ora.com      procmail:/etc/mail/procmailrcs/uce-filter
.                 procmail:/etc/mail/procmailrcs/any.rc
  • Create procmail recipe files (owned by root.root, perms 644) in  /etc/mail/procmailrcs (root.root, perms 755). Forwarded mail should extend with the .PROCMAIL pseudo-domain all addresses liable to be rerouted through the procmail mailer.

Discussion and example

The procmail mailer and mailertable

The MAILER(procmail) macro adds the  procmail mailer defintion. This mailer is independent and separate form the local_procmail feature (used to filter incoming local mail).

Using the mailer requires routing mail to it through mailertable:
/etc/mail/mailertable
example.com       procmail:/etc/mail/procmailrcs/spam-filter
.                 procmail:/etc/mail/procmailrcs/any.rc
First rule sends mail going to example.com to the rules defined in spam-filter, the second line sends all mail to any.rc.

# sendmail -bv crooks@example.com
crooks@example.com... deliverable: mailer procmail, host /etc/mail/procmailrcs/spam-filter, user crooks@example.com
# sendmail -bv spammers@spammers.net
spammers@spammers.net... deliverable: mailer procmail, host /etc/mail/procmailrcs/any.rc, user spammers@wrotethebook.net

sendmail invokes procmail as follows:


procmail -Y -m $h $f $u

The -Y flag selects Berkely Unix mailbox format, -m tells procmail that it's being invokde as a general mail filter, $h is set to the full path of the rule file, $f is set to the envelope sender address, $u to the envelope recipient address: these last two can ber referenced in tha rc file as $1 and $2.

Local rules

If, after processing, the message is going to be forwarded again, care must be taken as to avoid mail loop when (if) the message gets back to mailertable processing. The standard technique is to add the pseudo domain .PROCMAIL to the  recipient address within the procmail recipe files, and intercept this domain within sendmai.cf  adding rules to the bottom of  sendmail.mc like this (there must be  a literal  TAB between '<' and '$'):
/etc/mail/sendmail.mc

LOCAL_CONFIG
# Add .PROCMAIL to the pseudo-domain list
CP.PROCMAIL
LOCAL_RULE_0
# Strip .PROCMAIL and send via esmtp
R$+ < @ $+ .PROCMAIL . >        $#esmtp $@ $2 $: $1<@$2>

  • LOCAL_CONFIG starts the section that will be copied to sendmail.cf verbatim;
  • CP.PROMAIL inserts .PROCMAIL in class P: pseudo-domains that sendmail does not look up in the DNS;
  • LOCAL_RULE_0 starts a section whose content is added to  ruleset 0—also called the  parse ruleset. The code is entered in the  ParseLocal ruleset (ruleset 98). The parse ruleset risolvs an addresse in a delivery triplet.
  • The R rule matches addresses of the form user@domain.PROCMAIL, and rewrites them as a triplet with with “esmtp”, as mailer, “domain” as hast and “user@domain” as recipient.
 After regenerating sendmail.cf, we have:

# sendmail -bv crooks@example.com.PROCMAIL
crooks@example.com.PROCMAIL... deliverable: mailer esmtp, host example.com, user 
crooks@example.com

Procmail rule files, and an example


The  (objectionable) purpose of this example is creating a sendmail instance who does a stealth forward of a copy of all transient mail to a set of configured addresses, while also delivering it to the intended address.
  • /etc/mail/sendmail.mc is as above.
  • Mailertable:
/etc/mail/mailertable
.                 procmail:/etc/mail/procmailrcs/any.rc
/etc/mail/procmailrcs has perms 755, owner root.root; the files within, 644, root.root. SELinux users: no doubt SELinux will mess this up, as it does with everything else when it's turned on - I can offer no guidance, suit yourselves as best you can.
  • We use two auxiliary rule files to set-up and tear down tha stage.
/etc/mail/promailrcs/000_setup

# Debugging (use =no and =no to turn off)
VERBOSE=on
LOGABSTRACT=all
#
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
LOGFILE=/var/log/proc_log   #recommended
#this is clearer
OSENDER=$1
ORECIPIENT=$2
#Echoed to logfile at the end
TRAP="echo '---------- End of procmailer ------' "
#
# Antiloop belt+suspender. This should never be triggered.
:0 w
* 1^0 ^X-Our-Anti-Loop: SET
! -f $OSENDER $ORECIPIENT.PROCMAIL
000_setup must be included before any other ruel: besides some standard setting, it copies $1 and $2 to the more mnemonic $OSENDER, $ORECIPIENT and checks wether a header tht we add on exit exists (it should never be present): if it does it shortcircuits the processing with a copy of the final rule. This is also found in the file 999_end:
/etc/mail/promailrcs/999_end
#
# Insert Anti-loop header, add .PROCMAIL to recipient
:0 w
| (formail \
  -A"X-Our-Loop: SET" \
  ) | $SENDMAIL -oi -f $OSENDER $ORECIPIENT.PROCMAIL
the message is sent to the final recipient, after .PROCMAIL has been tacked to the recipient address, to trigger the sendmail.cf rules. This file must be included at the very end.
  • In any.rc is where the meat and potatoes are:
/etc/mail/promailrcs/any.rc

# Setup 
INCLUDERC=/etc/mail/procmailrcs/000_setup
#
#flag 'c' creates a carbon copy for processing
# Avoid sending duplicates
:0 Whc
| formail -D 16384 /tmp/idcache
#
#flag 'c' creates a carbon copy for processing
#flag 'e' executes only if previous command failed.
#espiones must contain addresses that are either local or .PROCMAIL terminated
:0 ec
| (formail -A"X-Our-Processed: SET" ) | $SENDMAIL -oi -f $OSENDER espiones
#clean up and forward
INCLUDERC=/etc/mail/procmailrcs/999_end

After setup, the second rule  checks if the message ID is already in a cache file, and add it there if it isn't. This will avoid sending multiple copies of the message to the  “espiones” when we have several recipients  (in  from:,  cc: or bcc:). Lastly the message gets added a watermark header, for debugging.
  • Since espiones is an aliased adress, non-local addresses in the alias need protection, too (as would literal addresses specified in the rule)
/etc/aliases
      espiones: foo@bar.com.PROCMAIL, baz@sna.fu.PROCMAIL, snafu
snafu, being local, is not  .PROCMAIL protected.

Additional Considerations

No doubt a task like this could be performed with a milter. Usage of the procmail mailer, as everything,  has pros and cons.

Pros

  • You do not need to select, write, or buy a suitable milter
  • Yu do not have to learn the ins and outs of yet another piece of MTA related software
  • You do not have to set up/debug the relevant communication between milter and sendmail
  • You have one less demon (the milter) to take care of

Cons

  • The mail flow becomes more involved and it is now controlled by yet another layer of configuration files (the rule files), and the same message will go through sendmail more than once. 
  • God help you if you come to rely on multiple loops of this machinery (it is tempting, I know).
  • Procmail syntax sucks.

Tuesday, May 20, 2014

Sendmail e procmail mailer per il filtraggio della posta in uscita

Ok, questa è più o meno la ricetta 6.8 dal sendmail cookbook, annotata. Però contiene anche la parte di procmail, è testata e funziona - e farlo senza guida richiede una giornata e giù di lì, quindi... enjoy.

Sommario

  • Creare la configurazione di sendmail per utilizzare mailertable e il mailer procmail, come segue.
/etc/mail/sendmail.mc
dnl Enable support for the mailertable
FEATURE(`mailertable')
dnl Add procmail to the list of available mailers
MAILER(procmail)
  • Inserire regole locali per permettere il reinvio di posta senza loop (attenzione al TAB tra '>' e '$')
/etc/mail/sendmail.mc
LOCAL_CONFIG
# Add .PROCMAIL to the pseudo-domain list
CP.PROCMAIL
LOCAL_RULE_0
# Strip .PROCMAIL and send via esmtp
R$+ < @ $+ .PROCMAIL . >        $#esmtp $@ $2 $: $1<@$2>
  • Usare mailertable per inviare la posta di domini specifici (o tutti i domini) al mailer procmail (l'ultima linea si applica a tutta la posta):
/etc/mail/mailertable
example.com       procmail:/etc/mail/procmailrcs/spam-filter
wrotethebook.net  procmail:/etc/mail/procmailrcs/spam-filter
fake.ora.com      procmail:/etc/mail/procmailrcs/uce-filter
.                 procmail:/etc/mail/procmailrcs/any.rc
  • Nel direttorio /etc/mail/procmailrcs creare i file per filtrare la posta, ricordandosi di estendere gli indirizzi dei destinatari finali con lo pseudodominio .PROCMAIL

Discussione ed esempi

Il mailer procmail e mailertable

La macro MAILER(procmail) aggiunge la definizione del procmail mailer. Questo è completamente separato ed indipendente dalla feature local_procmail (che si può usare per filtrare la posta in ingresso)
La macro MAILER(procmail) non aggiunge codice alla configurazione, e per usare il mailer stesso bisogna usare mailertable o aggiungere regole a sendmail.cf
/etc/mail/mailertable
example.com       procmail:/etc/mail/procmailrcs/spam-filter
.                 procmail:/etc/mail/procmailrcs/any.rc
Delle 2 regole nell' esempio qui sopra, la prima passa lapost diretta ad example.com alle regole contenuti in spam-filter, la seconda passa tutta l'altra posta alle regole in any.rc.

# sendmail -bv crooks@example.com
crooks@example.com... deliverable: mailer procmail, host /etc/mail/procmailrcs/spam-filter, user crooks@example.com
# sendmail -bv spammers@wrotethebook.net
spammers@wrotethebook.net... deliverable: mailer procmail, host /etc/mail/procmailrcs/any.rc, user spammers@wrotethebook.net

sendmail chiama procmail dal mailer mailer nel modo seguente

procmail -Y -m $h $f $u

Il flag -Y selezione il formato Berkeley Unix mailbox; il flag -m invoca procmail come un filtro di posta di uso generale. $h contiene il path del file di regole, $f è il valore dell'envelope sender (mittente) del messaggio, $u quello dell'envelope recipient (destinatario) del messaggio: nel file rc essi possono essere referenziati come le variabili $1 e $2.

Regole locali

Se l'intento è tornare ad inviare la posta dopo il filtraggio, bisogna proteggersi dai loop che si possono provocare rientrando nel mailer procmail inavvertitamente; per fare ciò, aggiungiamo lo pseudodominio .PROCMAIL all'indirizzo del destinatario utilizzando le regole di procmail: in questo modo il messaggio no sarà mai selezionato tra quelli di mailertable. Ecco le regole da aggiungere in fondo a /etc/mail/sendmail.mc (attenzione al TAB tra '>' e '$'):
/etc/mail/sendmail.mc

LOCAL_CONFIG
# Add .PROCMAIL to the pseudo-domain list
CP.PROCMAIL
LOCAL_RULE_0
# Strip .PROCMAIL and send via esmtp
R$+ < @ $+ .PROCMAIL . >        $#esmtp $@ $2 $: $1<@$2>

  • La macro LOCAL_CONFIG delimita una sezione che sarà aggiunta a sendmail.cf verbatim;
  • CP.PROMAIL inserisce .PROCMAIL nell classe P degli pseudodomini che sendmail non cercherà di risolvere via DNS.
  • La macro LOCAL_RULE_0 dà inizio alla sezione di codice da aggiungere al ruleset 0—more - anche detto il parse ruleset; questo codice farà parte del ParseLocal ruleset (anche detto ruleset 98). L'intento del parse ruleset è risolvere l'indirizzo di consegna nella tripla di consegna della posta.
  • Il comando R riconosce indirizzi della forma user@domain.PROCMAIL, riscrivendoli in una tripla con mailer “esmtp”, host uguale a “domain” e destinatario “user@domain”. Dopo aver rigenerato la configurazione, si dovrà vedere:

# sendmail -bv crooks@example.com.PROCMAIL
crooks@example.com.PROCMAIL... deliverable: mailer esmtp, host example.com, user 
crooks@example.com

Regole di procmail


Passiamo ora ad un esempio completo. Lo scopo (discutibile) è la creazione di un'isanza di sendmail che inoltri tutti i messaggi che transitano per la macchina a indirizzi terzi.
  • Il file /etc/mail/sendmail.mc è come sopra
  • Mailertable:
/etc/mail/mailertable
.                 procmail:/etc/mail/procmailrcs/any.rc
il direttorio /etc/mail/procmailrcs ha diritti 755, proprietario root.root; i file in esso contenuti, 644, root.root
  • Utilizziamo regole a carattere generale per organizzare l'ambiente.
/etc/mail/promailrcs/000_setup

# Per debugging (usare =no e =no per spegnerle)
VERBOSE=on
LOGABSTRACT=all
#
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
LOGFILE=/var/log/proc_log   #recommended
#per non confondersi
OSENDER=$1
ORECIPIENT=$2
#Viene scritta nel logfile alla fine.
TRAP="echo '---------- End of procmailer ------' "
#
# Controllo antiloop: usiamo cintura e bretelle - di qui non si dovrebbe passare mai
:0 w
* 1^0 ^X-Our-Anti-Loop: SET
! -f $OSENDER $ORECIPIENT.PROCMAIL
000_setup dev'essere incluso prima di iniziare la manipolazione della posta. Setta alcune direttive standard, assegna le variabili $1 e $2 ad altre due variabili più mnemonice (OSENDER, ORECIPIENT) e controlla l'esistenza di un header che viene settato anche all'uscita - terminando in questo caso il processing replicando quello che avrebbe dovuto fare la regola finale, che nel file 999_end:
/etc/mail/promailrcs/999_end
#
# Controllo antiloop
:0 w
| (formail \
  -A"X-Our-Anti-Loop: SET" \
  ) | $SENDMAIL -oi -f $OSENDER $ORECIPIENT.PROCMAIL
inoltra il messaggio al destinatario finale, dopo aver concatenato lo pseudo dominio .PROCMAIL per attivare le regole inserite poco sopra in sendmail.cf.
  • In any.rc si includono all'inizio e alla fine i file di cui sopra: tra i due si effettua l'inoltro in copia:
/etc/mail/promailrcs/any.rc

# Setup generale
INCLUDERC=/etc/mail/procmailrcs/000_setup
#
#flag 'c' creates a carbon copy for processing
#Evita i duplicati per indirizzi multipli
:0 Whc
| formail -D 16384 /tmp/idcache
#
#flag 'c' creates a carbon copy for processing
#flag 'e' executes only if previous command failed.
#espiones must contain addresses that are either local or .PROCMAIL terminated
:0 ec
| (formail -A"X-Our-Processed: SET" ) | $SENDMAIL -oi -f $OSENDER espiones
#clean up and forward
INCLUDERC=/etc/mail/procmailrcs/999_end
Il file 000_setup (q.v.) sistema l'ambiente; la seconda regola controlla che l'ID del messaggio corrente non sia in un file di cache (e lo aggiunge se manca). Questo server ad evitare di inviare agli “espiones” tante copie del messaggio quanti sono i destinatari (nel from:, o nel cc: o nel bcc:). Infine viene aggiunto un header che consenta l'identificazione di questo passaggio (a fini di debug).
  • I messaggi saranno inviati in copia ad un alias; gli indirizzi non locali vanno essi stessi protetti:
/etc/aliases
      espiones: foo@bar.com.PROCMAIL, baz@sna.fu.PROCMAIL, snafu
L'unico alias non protetto dall'estensione .PROCMAIL è snafu, che viene riconosciuto come locale e quindi non attiva mailertable. 

Wednesday, May 14, 2014

Volevi scrivere un libro, ma è un prodotto cartaceo

Bisogna commiserare l'altra metà del cielo.

Le donne, a quanto pare, sono condannate a stare da sole, o tra di loro, o ad adattarsi a scegliere tra alternative poco attraenti. Consideriamo che il maschio della specie umana:

  • A 20 anni è primitivo
  • A 30 anni è adolescenziale, o mammone, o irresponsabile (tutt'e tre, spesso)
  • A 40 anni è un porco
  • A 50 anni è ridicolo e giovanilista
  • A 60 anni è stanco
  • A 70 anni è depresso
  • A 80 anni è vecchio
  • A 90 anni è spesso morto
Tanto vale allora prendersi un cane, o un gatto.

Se state pensando che questi elenchi non erano già più divertenti quando cominciavano con:
  • A 20 anni l'uomo è come il locale: ferma a tutte le stazioni
o, simmetricamente, con:
  • A 20 anni, la donna è come l'Africa: lussureggiante e inesplorata
e si compravano (e tuttora si comprano) nelle tabaccherie assieme ad altre insegne di pari arguzia, avete ragione.

Allora qualcuno mi spieghi come mai si pubblicano e trovano un pubblico - quantomeno giornalistico, però ci sono anche 1600 like su FB -   prodotti cartacei, ché chiamarli libri è indebito, di questo tipo. Nelle tabaccherie non si vendono, per leggerli ci vuol più impegno che a leggere gli elenchi sopra citati (penso che invece, a scriverli, ce ne voglia un po' meno: non bisogna sforzarsi di essere concisi). 

Sicuramente, da ultracinquantenne, sono ipersensibile, ma immaginiamo il caso, simmetrico, di un prodotto cartaceo dal titolo "Le ragazzone", che se la prende con le donne ultracinquantenni, le insicurezze premenopausa. la paura d'invecchiare etc. Sarebbe correttamente sotterrato da una montagna di guano. Mi auguro che non sarebbe pubblicato. Sono quasi certo che non sarebbe recensito da quotidiani trendy.

Forse sono troppo ottimista, però.  
Sessismo? Non credo. Stupidità? E' una buona ipotesi di lavoro. 

La metto assieme agli altri stereotipi age-based quae quello, abbastanza popolare su twitter (twitter: che medium del cazzo. Ecco, l'ho detto, ora sto meglio) e in blog assortiti "Ah, questi ultraXXenni che vogliono usare internet, ma se andassero nel parco".  In questo caso:

XX=10+età dello scrivente

Lo scrivente, dopo aver twittato la sua irritazione contro i matusa (sì, sono datato) posta poi la foto di un micetto, o un like di Justin Bieber, così, per il gusto di mostrare un po' di internet prowess.

Nota a me stesso: Ricordarsi di questo post, quando si stanno per dire cose matusa del tipo "I ragazzi adesso, mamma mia, che disastro".


Wednesday, May 7, 2014

Lampo di genio

Un fisico stava cercando di dimostrare una sua teoria sociologica secondo la quale, sottoponendo ad un matematico ed un fisico un problema che abbia sia  una soluzione laboriosa e diretta sia una semplice, ma meno evidente, il matematico opterà per la prima, il fisico per la seconda.

Per questo sottopose a  John Von Neumann (la cui capacità di calcolo era leggendaria, così come la sua distrazione), il seguente problema:

"Due treni, sullo stesso binario, si muovono uno verso l'altro, in direzioni opposte, a una velocità rispettiva  di 30 e 50 Km/h. Un uccello parte dalla motrice di uno dei due volando a 120 Km/h, quando i treni distano 100 Km uno dall'altro, fino a incontrare il secondo treno, poi torna indietro alla stessa velocità e continua allo stesso modo finchè i due treni si scontrano. Che distanza percorre l'uccello?"

Von Neumann rispose quasi istantaneamente: "240 Km".
Il collega allora gli disse piuttosto deluso: "Ecco, ci sei arrivato subito e hai scompigliato la mia teoria. Avrei scommesso che tu, essendo un matematico, avresti preso la strada lunga, quella con la somma della serie infinita."
E Von Neumann, imbarazzato: "Ah, lo sapevo che c'era anche una soluzione facile!"

La soluzione è qui

sotto...

sotto...

sotto..

sotto..

sotto..

sotto..

sotto..

sotto..

sotto..

sotto..

sotto...

sotto...

sotto..

sotto..

sotto..

sotto..

sotto..

sotto..

sotto..

sotto..

Soluzione semplice

I treni collidono due ore dopo che l'uccello ha spiccato il volo:
Tt= D0/(V1+V2) = 100/50 dove 50 è la velocità relativa dei due treni.
Per tutto questo tempo l'uccello vola a 120 Km/h, e quindi percorre St=Vb*D0/(V1+V2) = 240 Km.

Soluzione complessa

La soluzione complessa segue il dettaglio del volo dell'uccello e riduce il problema alla somma di una serie geometrica.

Per abbozzare questa soluzione e svolgere i calcoli c'ho messo circa venti minuti. Ma siccome avevo commesso un errore concettuale, poi l'ho cercato per due giorni, senza vederlo, finchè una domanda su  math.stackexchange.com no mi ha messo sulla strada giusta. Lo sapevo che tra me e Von Neumann c'era una certa distanza...

All'inizio i treni sono separati dalla distanza D0  che l'uccello copre in tempoe T0=D0/(Vb+V2) e percorrendo la distanza S0=Vb*T0

Al ritorno, con analoga notazione:

D1 = D0-T0 * (V1+V2) = D0 * (Vb-V1)/(Vb+V2);
T1=D0 * (V1-Vb)/((V1+Vb)*(V2+Vb))=T0 * (Vb-V1)/(Vb+V1)
S1=VB*T1

Al terzo viaggio, ripetendo i calcoli di cui sopra, emerge una ricorrenza:

D2 = D0 * ((V1-Vb)*(V2-Vb))/((V1+Vb)*(V2+Vb))
T2 = T0 * ((V1-Vb)*(V2-Vb))/((V1+Vb)*(V2+Vb))
S2 = S0 * ((V1-Vb)*(V2-Vb))/((V1+Vb)*(V2+Vb)) = Vb*T2

Ricorrenza che vale anche per D3 e D1, T3 e  T1 e S3 e S1

Ponendo

R=(V1-Vb)*(V2-Vb))/((V1+Vb)*(V2+Vb))

La somma che dà il totale del tempo impiegato (o distanza percorsa):

Tt=T0+T1+T2+T3...=(T0+T1)+(T0+T1)*R+(T0+T1)*R^2....

Siccome R< 1 la somma converge a:

Tt=(T0+T1)/(1-R)
St=Vb*Tt

Effettuando il calcolo con la sostituzione di R si ha , come prima:

Tt= D0/(V1+V2) = 100/50 =2 
St=Vb*D0/(V1+V2)= 240