/ BLOG / Karmasphere and Exim4, on Debian

I’ve rambled on about Karmasphere in the past, but I’ve not actually done anything with it since mentioning it.

Sadly today was the day when spam started getting through my crazy system. This clearly was a signal from the gods themselves; to take the next step. The dreaded DNSBL. You might be surprised, but I don’t like DNSBLs. In the past they’ve made my life hard at work - especially when we’ve inherited an IP that was previously used by spammers, in some way, shape or form. You see the thing is that some are actually on the ball and will check out and change their lists easily. Others won’t. The problem is that maintaining your knowledge of the good ‘uns and the bad 'uns is… well boring.

Karmasphere is supposed to take this hassle and make it easier; you can aggregate results from multiple sources, not just DNSBLs, and let Karmasphere decide for you. So if one or two don’t keep up.. well that won’t matter so much. In theory.

At the moment I’m adding headers to my mails and not rejecting, just to see how things fare, however in the future (assuming all goes well) I’d actually like to see this in real use. Perhaps even at work, in conjunction with our other spam filtering solutions.

So how did I do it (remember this is just logging, not actively rejecting)? Pretty easily, it must be said (I’m not going into detail);

  1. Installed the Karmasphere client:

    perl -MCPAN -e 'install Mail::Karmasphere::Client'

  2. Created an SysV init script to run the karmad server on startup:

    #! /bin/sh
    # Starts KarmaSphere Daemon
    set -e
    DESC="KarmaSphere Daemon"
    # Gracefully exit if the package has been removed.
    test -x $DAEMON || exit 0
    case "$1" in
            echo -n "Starting $DESC: $NAME"
            nohup $DAEMON --feedset=karmasphere.email-sender-ip --username=$KUSR --password=$KPWD --socketuser=Debian-exim 2>/dev/null 1>/dev/null &
            echo "."
            echo "Stopping $DESC: $NAME."
            killall -9 $NAME &> /dev/null
            echo "Restarting $DESC: $NAME."
            $0 stop && sleep 1
            $0 start
            echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
            exit 1
    exit 0

    (and then created the relevant symlinks using update-rc.d)

  3. Created and added the following to /etc/exim4/conf.d/acl/10_karmad-exim (which is pretty much line for line what you can find on Karmasphere’s website):

        # Check envelope sender
        warn set acl_m9  = ${readsocket{/tmp/karmad}\
                               \nsender=$sender_address\n\n}{20s}{\n}{socket failure}}
        # Continue quietly on socket error
        accept condition   = ${if eq{$acl_m9}{socket failure}{yes}{no}}
                 message     = Cannot connect to karmad
        # Prepare answer and get results
        warn  set acl_m9  = ${sg{$acl_m9}{\N=(.*)\n\N}{=\"\$1\" }}
                set acl_m8  = ${extract{value}{$acl_m9}{$value}{unknown}}
                set acl_m7  = ${extract{data}{$acl_m9}{$value}{}}
        # Check for fail
        # Once happy with testing, replace with deny & condition - or perhaps do filtering into Junk as part of ~/.forward?
        warn message = X-Karma: $acl_m8: $acl_m7

  4. Added the following to my CHECK_RCPT_LOCAL_ACL_FILE (one of the magic Debian macros for adding your own RCPT TO checks):

    deny !acl = karma_rcpt_acl

If you’re not aware of what’s going on here, then I’d suggest reading the Debian Exim4 split config documentation, and also the Karmasphere docs - you could break your mail server.

What this will now do is mark all of my mails, if it can talk to karmad, with X-Karma: 0: Comment. The lower the number, the more likely it is to be spam. -1000 to 1000 is the range, with it defaulting to 0 for neutral/unknown.

The only thing that would need to be altered is to add my whitelisting acl, if I do go live with it, and to decide whether or not I do filtering in ~/.forward or during SMTP rejection.