Bayesian-filtering en (bijna) geen backups

Elk bestand en database moet op tape worden gezet is het motto bij veel sysadmins, maar is dat wel zo. En in veel gevallen hebben ze gelijk, maar helaas niet als het een database betreft die wordt gebruikt voor Bayesian-filtering. Maar waarom maak je backups? Om data die waarde heeft veilig te stellen is eigenlijk de stelregel.

Maar wat maakt Bayesian-filtering nu zo anders? Laten we eens kijken op een testnode.

$ sudo sa-learn --dump magic
0.000 0 3 0 non-token data: bayes db version
0.000 0 25556 0 non-token data: nspam
0.000 0 11331 0 non-token data: nham
0.000 0 204764 0 non-token data: ntokens
0.000 0 1262669327 0 non-token data: oldest atime
0.000 0 1263329413 0 non-token data: newest atime
0.000 0 0 0 non-token data: last journal sync atime
0.000 0 1263273928 0 non-token data: last expiry atime
0.000 0 345600 0 non-token data: last expire atime delta
0.000 0 21267 0 non-token data: last expire reduction count

Wat we zien is dat de database is gevuld met z’n dikke 25000 spamberichten en 11000 hamberichten, maar ook dat de database ruim 204000 kenmerken bevat om zijn berekeningen op laten plaats vinden. Twee leuke kenmerken van dit overzicht zijn dat er een data in de journal zit omdat dit direct in echte database zit ipv in de standaard BerkelyDB en de tweede is de hoeveelheid tokens. In een standaard database zitten maximaal 150000 tokens en welke bij een expire automatisch worden opgeschoond naar 75% van die 150000 tokens. Deze installatie heeft auto-expire uitstaan waardoor dit extern moet worden geregeld, maar ook dat de database meer dan een normaal aantal tokens mag bevatten.

Maar wat heeft dit met backups te maken? Waarom zou je data in veiligheid brengen als er elke uur een nieuwe tokens worden toegevoegd en elke dag een expire wordt gedaan? Een constante stroom aan nieuwe data zorgt ervoor dat de database altijd in flux is zoals het hoort en in het slechtste geval is je database een paar uur aan het bijleren. Om dit laatste te overkomen zou je spam- en hamberichten bijvoorbeeld in de Trash-folder van de IMAP-server kunnen laten staan die na een paar dagen deze automatisch verwijdert uit standaard policy. Het verplaatsen van alle berichten van de Trash-folder naar de INBOX en bij de volgende ronde komt alles weer vanzelf in de database. Deze methode werkt ook vrij goed als de layout van de database wordt aanpast bij een upgrade en de database moet opnieuw worden opgebouwd.

De vraag die sysadmins misschien wat meer moeten vragen of de data echt naar tape moet, want we leven steeds meer in een tijdperk dat backups onmogelijk(er) beginnen te worden. Er zullen dus andere oplossingen moeten worden gezocht om data veilig te houden voor gebruikers. De eerste stap is het niet op tape zetten van data die je kan reproduceren.

Bayesian-filtering na ongeveer een jaar

In mei 2009 besteede ik in postings PostgreSQL voor Bayesian-filtering in SpamAssassin en Een Bayesian-filter vullen met data de nodige aandacht aan Bayesian-filtering, maar hoe staat het er nu voor? En het eerste wat zal opvallen is de titel, want er staat “na ongeveer een jaar” en de postings waren in mei. Dit klopt, maar gelukkig was de opzet van Bayesian-filtering met een PostgreSQL-backend al eerder opgezet om zeker te zijn dat het zinvol was.

Een jaar later is goed te zeggen dat de keuze voor het starten van een Bayesian-filter een goede keuze was. Veel spamberichten welke normaal gesproken niet door SpamAssassin zouden worden herkent worden nu als spam gemarkeerd. Ook het snelle leren van nieuwe type spamberichten gaat redelijk vlot, hoewel je wel voldoende berichten moet voeden aan het systeem. Naarmate de tijd vorderde ging de interval dat sa-learn draaide van eenmaal per dag naar elke zes uur, naar elke vier uur en uiteindelijk naar elk uur om bij te blijven. Zeker nadat de spamdomeinen geen bescherming meer hadden van de Spamhaus regels in de mailserver.

De komende maanden zal er een herimplementatie moeten komen van het statistiekensysteem om zo duidelijk te krijgen wat de belangrijkste regels in SpamAssassin zijn en of het mogelijk is om zonder oa SURBL, URIBL en Spamhaus te kunnen, maar ook welke SARE-regels nog zinvol zijn. Een andere optie is om te kijken of een herintroductie van Spamikaze kan plaats vinden om bepaalde e-mails toch op basis van een eigen blacklist/whitelist af te handelen.

Marketeers en Tweets

Het was te verwachten uiteraard, maar bij het bekijken waarom sommige spamberichten niet netjes naar de Junk-folder viel me iets grappigs op. Sommige partijen zijn begonnen om niet alleen hun responses te monitoren met Google Analytics, maar laten nu ook automagisch een Tweet aanmaken om zo hoger op sommige lijsten te scoren. Of het fair is laat ik even in het midden, maar het lijkt wel langzaam een trend te worden om Twitter-achtige dingen te gebruiken in marketing en de kans dat gebruikers dit naar elkaar doorsturen is vrij klein.

describe LOCAL_TWEET Mailing with Tweet-API
rawbody __A_LOCAL_TWEET /\bhttp:\/\/api\.tweetmeme\.com\/share\?url/i
rawbody __B_LOCAL_TWEET /\bunsubscribe\b/i
meta LOCAL_TWEET ( __A_LOCAL_TWEET && __B_LOCAL_TWEET )
score LOCAL_TWEET 0.001

Met de bovenstaande ruleset voor SpamAssassin is te controleren wat de impact gaat zijn. Een paar dagen loslaten op de honeypot die het bayesianfilter van kenmerken voorziet zou voldoende moeten zijn om te kijken wat de score daadwerkelijk moet gaan zijn en of het effectief is.

Een Bayesian-filter vullen met data

In een vorige posting werd SpamAssassin zo geconfigureerd dat het Bayesian-filter gebruik maakte van PostgreSQL om de data in op te slaan. Ook werd aangegeven dat er niet automatisch werd geleerd met de optie bayes_auto_learn 0 om zo te voorkomen dat het filter zijn eigen waarheid ging verzinnen van wat spam was en wat niet.

Een manier om aan data te komen voor het filter is door een mailbox met alleen ham en een mailbox met alleen spam regelmatig te importeren. De ham is natuurlijk nog wel gemakkelijk aan te komen door deze mailbox aan te melden op een paar mailinglists en nieuwsbrieven waarvan je weet dat ze te vertrouwen zijn en bijna 100% non-spam zijn en dus geschikt zijn voor de ham mailbox.

Voor spam zelf wordt het wat lastiger. Je kan vertrouwen op wat je gebruikers markeren als spam en dan importeren, maar hierdoor loop je altijd achter de feiten aan. Een makkelijkere en betrouwbare methode is door spamtraps op te zetten, maar het kan even duren voordat deze functioneel zijn. Je kan op sommige websites die jezelf onder beheer hebt de onderstaande string opnemen en hopen dat de robotjes van e-mailverzamelaars het oppakken.

<!-- <a href="mailto:spamtrap@example.org">spamtrap@example.org</a> -->

Het kan lang duren voordat er resultaat is. Een tweede optie kan zijn door in bepaalde groepen zoals bijvoorbeeld in nl.test op usenet te posten en dit kan redelijk snel resultaat opleveren. Een derde optie kan zijn door een PGP-key te uploaden naar de keyservers, maar deze methode is niet aan te bevelen aangezien het echt vervuiling is en je wordt traceerbaar.

Nu je spam en ham netjes in hun eigen mailbox binnenkomen kan je met de volgende commando’s op gestelde tijden je filter opschonen en vullen met spam en ham:

sa-learn -u amavis --force-expire
sa-learn -u amavis --spam --mbox spam.mbox
sa-learn -u amavis --ham --mbox ham.mbox

Zoals te zien is forceer ik dat alles gedaan wordt onder de gebruiker amavis aangezien amavisd-new de daemon is die tussen Postfix en SpamAssassin en ClamAV zit om de mail te scannen, te beoordelen en in geval van een virus ook in quarantine te plaatsen. Er kan binnen SpamAssassin met de optie bayes_sql_override_username amavis in local.cf hetzelfde effect worden afgedwongen.