Gedanken zu Spamerkennung mittels bogofilter

Hier können Probleme und alles andere in Deutscher Sprache gelöst werden.
el*Loco
Regular
Posts: 11
Joined: Thu Jul 07, 2005 1:42 pm

Gedanken zu Spamerkennung mittels bogofilter

Post by el*Loco »

Huhu Serendipity User,

da Akismet und auch TypePad Antispam tlw. ein wenig viel wegfiltern - gerade Kommentare auf Deutsch - habe ich gestern ein wenig begonnen, mir über Alternativen Gedanken zu machen. Erst wollte ich Spamassassin zur Erkennung von Spam/Ham verwenden, bin dann aber bei bogofilter gelandet, da Spamassassin sehr viele Tests für Mailheader hat und diese auch erwartet (Received-Zeilen etc.).

Da bogofilter ein Bayes-basierter Filter ist, muss er erst lernen, was gut und was schlechte Kommentare sind. Dazu habe ich zwei Dinge getan:

Alle guten Kommentare je in eine Datei pro Kommentar geschrieben:

Code: Select all

SELECT author,url,body FROM serendipity_comments WHERE status = 'approved';
Alle erkannten und abgelehnten Spamkommentare in je eine Datei pro Kommentar geschrieben:

Code: Select all

SELECT author,url,body FROM serendipity_spamblocklog WHERE type = 'REJECTED';
In meinem Fall ergab das dann zwei Verzeichnisse, einmal "blogspam" mit fat 370.000 abgelehnten Spams und ein "blogham" Verzeichnis mit 700 guten Kommentaren und Trackbacks. Jede der Dateien hatte untereinander author, url und body stehen. Jetzt zum lernen:

Code: Select all

loco@bigboy ~ $ bogofilter -v -H -n -B blogham/
# 6663 words, 696 messages

Code: Select all

loco@bigboy ~ $ bogofilter -v -H -s -B blogspam/
# 331002 words, 369836 messages
Wenn ich jetzt je einen neue Spamkommentar und einen erfundenen, aber validen sauberen Kommentar zur Prüfung durch den bogofilter jage, erkennt er das brav:

Code: Select all

loco@bigboy ~ $ bogofilter -v -H < test.blog 
X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.1.7

Code: Select all

loco@bigboy ~ $ bogofilter -v -H < test.blog 
X-Bogosity: Spam, tests=bogofilter, spamicity=1.000000, version=1.1.7
Manuell tut das jetzt alles - aber wie verwende ich das in Serendipity? Ich bin SysAdmin, habe es überhaupt nicht mit der PHP Programmierung. Gäbe es denn Interessierte, die diesen Ansatz der Spamfilterung mittels Bayesfilter weiter verfolgen möchten und evtl. in ein Spamblock-Plugin giessen möchten?

Gruß aus dem närrischen Köln,

Peter
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by garvinhicking »

Hi!

Eigentlich ist das halbwegs einfach zu programmieren. Ich empfehle ausdrücklich, nicht das Haupt-Spamblock-Plugin als Grundlage zu nehmen (das ist überfüllt) sondern z.b. serendipity_event_spamblock_rbl (Spartacus).

Daraus abgeleitet mal folgendes Minigrundgerüst:

Code: Select all

<?php
class serendipity_event_spamblock_bogo extends serendipity_event {
    function introspect(&$propbag) {
        global $serendipity;

        $this->title = 'Bogobogo';

        $propbag->add('name',          $this->title);
        $propbag->add('version',       '0.1');
        $propbag->add('event_hooks',    array('frontend_saveComment' => true));
        $propbag->add('groups', array('ANTISPAM'));
    }

    function generate_content(&$title) {
        $title = $this->title;
    }

    function bogo(&$comment) {
        $f = '/tmp/bogo.log';
        $fp = fopen($f, 'w');
        flock($fp, LOCK_EX);
        fwrite($fp, $comment['name'] . "\n" . $comment['url'] . "\n" . $comment['comment'] . "\n");
        fclose($fp);
        $return = `bogofilter -v -H < $f`;
        if (preg_match('@X-Bogosity: Spam@imsU', $return)) {
            return true;
        }
        
        return false;
    }

    function event_hook($event, &$bag, &$eventData, $addData = null) {
        global $serendipity;

        $hooks = &$bag->get('event_hooks');

        if (isset($hooks[$event])) {
            switch($event) {
                case 'frontend_saveComment':
                    if (!is_array($eventData) || serendipity_db_bool($eventData['allow_comments'])) {
                        $serendipity['csuccess'] = 'true';
                        if ($this->bogo($addData)) {
                            $eventData = array('allow_comments' => false);
                            $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_RBL . ' ('.implode(', ', $dnsbl->getTxt($remoteIP)).')';
                            return false;
                          }
                    }

                    return true;
                    break;
                
                default:
                    return false;
                    break;
            }
        } else {
            return false;
        }
    }
}
Das führt in der bogo Methode eigentlich alles aus und liefert "true" wenn's ein Spam ist. Entsprechend wird dann ein Kommentar hart geblockt. Wenn Du es lieber moderieren willst, muss man innerhalb der if ($this->bogo(...)) Bedingung stattdessen folgendes nehmen:

Code: Select all

$eventData['moderate_comments'] = true;
$serendipity['csuccess']        = 'moderate';
$serendipity['moderate_reason'] = 'Bogobogo!';
Ehrlich gesagt weiß ich nicht, ob Bayes hier gut greifen kann. Kommentare sind meist viel zu kurz um daraus verlässliche bayesische Filter erstellen zu können, fürchte ich....

Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
Lux
Regular
Posts: 764
Joined: Fri Aug 12, 2005 4:36 pm
Location: Grüt, Zürich, Switzerland
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by Lux »

el*Loco wrote:Manuell tut das jetzt alles - aber wie verwende ich das in Serendipity? Ich bin SysAdmin, habe es überhaupt nicht mit der PHP Programmierung. Gäbe es denn Interessierte, die diesen Ansatz der Spamfilterung mittels Bayesfilter weiter verfolgen möchten und evtl. in ein Spamblock-Plugin giessen möchten?
Ich finde die Idee immer noch grossartig und würde das auch gerne in einem Plugin sehen.

Gruss

Dirk
el*Loco
Regular
Posts: 11
Joined: Thu Jul 07, 2005 1:42 pm

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by el*Loco »

garvinhicking wrote: Ehrlich gesagt weiß ich nicht, ob Bayes hier gut greifen kann. Kommentare sind meist viel zu kurz um daraus verlässliche bayesische Filter erstellen zu können, fürchte ich....
Mmh, viele Spam-Mails sind meist auch nicht so viel länger. Den Vorteil, den ich sehe, ist daß der Bayes Filter pro Blog trainiert werden kann. Bei Akismet und TypePad Antispam habe ich mittlerweile das Gefühl, daß deutschsprachige Kommentare und Trackbacks eher mal als Spam gewertet werden.

Gruß,

Peter
onli
Regular
Posts: 2829
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by onli »

Ist es hier weitergegangen, vielleicht sogar ein Plugin entstanden? Als Alternative zu Akismet und Captcha wäre das schon toll.
onli
Regular
Posts: 2829
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by onli »

Entschuldigt den Doppelpost.
Ich glaube, wollte man das als Plugin realisieren, könnte man statt bogofilter besser b8 nutzen. B8 ist ein PHP-Bayes-Filter angepasst für Gästebucheinträge und Blogs - also genau das, was wir suchen. Ein Plugin könnte die vorhandenen Kommentare und den Spam in der install() zum Lernen nutzen und danach die neuen Kommentare bewerten, das genau so, wie es garvins code zeigt. Jemand Lust, das zu bauen?
Gruß

PS: Wie könnte man das Lernen anhand von nach der Installation eingetroffenen Kommentaren bewerkstelligen?
kleinerChemiker
Regular
Posts: 765
Joined: Tue Oct 17, 2006 2:36 pm
Location: Vienna/Austria
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by kleinerChemiker »

Gibts da sonst noch interesse? Ein Bayse Filter mit PHP klingt interessant. Ich werds mir auf jeden Fall mal anschauen und wenn Interesse besteht vielelicht ein Plugin basteln.
onli
Regular
Posts: 2829
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by onli »

Ich habe mich mit kleinerChemiker abgesprochen und mich an b8 versucht. Dabei bin ich jetzt in drei Probleme gelaufen. Wahrscheinlich werde ich den b8-Weg sein lassen und stattdessen http://aktuell.de.selfhtml.org/artikel/ ... e-software testen, aber den bisherigen Code hänge ich mal an. Die Probleme bisher:

1. Ein generelles: Ein bayes-Filter muss lernen, und wir können uns eigentlich nicht darauf verlassen, dass in der spamlog-Tabelle was drin steht. Auch manuelles kennzeichnen müsste möglich sein, ein "Spam"-Knopf beim Moderieren von Kommentaren wäre ideal. Nur: Wie den einfügen? Ein Event im core beim Formular-Erstellen feuern und das im Plugin greifen?

Die folgenden Probleme sind spezielle zum bisherigen Code:
2. Ist keine Datenbank vorhanden, wird createDB auf true gesetzt. Direkt danach scheitert aber die Initialisierung von b8, woraufhin nicht gelernt werden kann.

3. Beim zweiten Installieren ist die DB schon da und das Lernen klappt, aber im folgenden wirft b8 die Warnung, dass die Datenbank zu alt sei. Liegt wohl daran, dass die $version-Variable im b8-Code leer bleibt. Das muss irgendwas damit zu tun haben, wie mein Code die b8-Dateien anpackt, vor den Versuchen die Datenbankerstellung zu automatisieren trat dieser Fehler nicht auf. Ich tippe auf das Editieren der config_storage, diese Funktion (setCreate($value)) empfinde ich selbst als hässlich.

4. Versucht man sowas:

Code: Select all

$this->b8 = new b8;
if (! $this->b8->constructed) {
       $this->b8 = new b8;
}
weil man vermutet, dass b8 beim ersten Mal immer fehlschlägt, gibt der Webserver die PHP-Datei als Textdatei zurück, also zum Downloaden. Ist das ein generelles PHP-Ding oder hat das mit b8 zu tun?

Gruß

PS: Ich bin nicht überzeugt davon, dass der selfhtml-Filter vergleichbar gute Ergebnisse bringt, es würde mich daher schon interessieren, die Probleme auszuräumen - ist ja gut möglich, dass sie durch von mir gemachten Fehlern entstanden.
Last edited by onli on Wed Jul 01, 2009 7:50 pm, edited 4 times in total.
onli
Regular
Posts: 2829
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by onli »

Doppelpost, weil edit scheitert: Bisheriger Code.

(Bis auf die Warnmeldung, die Unmöglichkeit Spam nachträglich zu markieren und das zweimalige Installieren sollte es durchaus schon funktionieren, "Berkeley DB"-Unterstützung vorausgesetzt.)
kleinerChemiker
Regular
Posts: 765
Joined: Tue Oct 17, 2006 2:36 pm
Location: Vienna/Austria
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by kleinerChemiker »

Ich wüe nicht, weshalb die selfhtml Lösung schlechter sein sollte. Bayes-Filter basieren auf irgendsoeiner Wahrscheinlichkeitstheorie. Da die Berechnungen daher eigentlich ziemlich gleich sein sollten, sollte da kein allzu großer Unterschied sein.

Ich würde auch eher nur die wichtigen Funktionen übernehmen und das ganze enger auf s9y anpassen, z.B. die DB-Layer von s9y verwenden.
onli
Regular
Posts: 2829
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by onli »

Hast du dir die readme genauer angeguckt? Ich fand an b8 verlockend, dass sich da jemand Gedanken gemacht hat. Beispiel:
The other thing is, that most Bayesian filters count one token one time, no matter how often it appears in the text (as Graham describes it in [1]). b8 does count how often it is there and learns or considers this. Additionally, the number of learned ham and spam texts are saved and used as the calculation base for the single possibilities. Why this? Because a text containing one link (no matter where it points to, just indicated by a "http://" or a "www.") might not be spam, but a text with 20 links in it might be.
Ebenso ist http://nasauber.de/opensource/b8/discussion/ eine scheinbar ordentliche Grundlage. Nichtsdestotrotz, der gemeinsame Versuch ist interessant.
kleinerChemiker
Regular
Posts: 765
Joined: Tue Oct 17, 2006 2:36 pm
Location: Vienna/Austria
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by kleinerChemiker »

Wörter, die nur einmal vorkommen sind im Allgemeinen auch charakteristischer als Wörter wie "ist, und, wird, ..." die eben sehr oft vorkommen. Aber es spricht ja nichts dagegen, die Berechnungsgrundlagen von b8 für s9y anzupassen. Nur ie PHP Skripts von b8 halte ich persönlich für aufgebläht und die DB-Abfragen sind stark verbesserungswürdig.
onli
Regular
Posts: 2829
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by onli »

Ich denke, der Rahmen ohne Bayes-Funktionalität ist so brauchbar.
Gruß
Attachments
serendipity_event_spamblock_bayes.tar.gz
(5.91 KiB) Downloaded 383 times
kleinerChemiker
Regular
Posts: 765
Joined: Tue Oct 17, 2006 2:36 pm
Location: Vienna/Austria
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by kleinerChemiker »

Es fehlt nur noch die Berechnung des Spamlevles. Das werd ich in den nächsten Tagen machen, wenn nix dazwischen kommt.
serendipity_event_spamblock_bayes.zip
(7.09 KiB) Downloaded 380 times
kleinerChemiker
Regular
Posts: 765
Joined: Tue Oct 17, 2006 2:36 pm
Location: Vienna/Austria
Contact:

Re: Gedanken zu Spamerkennung mittels bogofilter

Post by kleinerChemiker »

So, die Berechnung nun auch hinzugefügt. Eigentlich sollte es funzen, kann es aber derzeit leider nicht testen, da ich derzeit nur meinen alten Laptop zur verfügung habe.
Was mir noch aufgefallen ist, du bindest kein Langue-File ein und du solltest bei DB-Tabellen nicht "serendipity_" voraussetzen. Das Plugin wird allerdings erst mit s9y laufen, da ein Patch am Core notwendig ist, den ich Garvin noch schicken muß.
Attachments
serendipity_event_spamblock_bayes.php.tar.gz
(7.44 KiB) Downloaded 355 times
Post Reply