bley – gewichtetes Greylisting + Cache

Auf der openrheinruhr.de habe ich gestern einen sehr interessanten Vortrag über Greylisting von Evgeni Golov gehört.


Ich selber hatte bis vor einigen Stunden noch eine Kombination aus Black- & Greylisting + SpamAssassin + ClamAV. Das Problem welches einige kennen ist, dass E-Mails dadurch ggf. verloren gehen oder zumindest verzögert werden, wenn ein “guter” Absender auf einer Blacklist kommt.

Das gewichtetet Greylisting erweitert das normale Greylisting um eine selektive Komponente, somit wenden nur auffällige Sender (welche in einer DNSBL (Blackliste) ist, nicht RFC-konformes EHLO übergibt etc…) werden gegreylisted. Das heißt, dass dem Absender mitgeteilt wird, dass momentan die E-Mail nicht zugestellt werden kann und er es gleich noch einmal versuchen soll, alle anderen werden durchgelassen. Spamer kommen jedoch (noch) nicht noch-einmal, um die selbe E-Mail ein zweites Mal zuzustellen.

Normalerweise werden bei “normalem” Greylisting unbekannten Absender direkt temporär abgewiesen und dessen Reaktion abgewartet. Bei dem “gewichtetem” (intelligentem) Greylisting wird der erste Zustellversuch zunächst analysiert. Anhand dieser Analyse wird entschieden, ob die E-Mail sofort angenommen werden soll oder ob Greylisting zum Einsatz kommt und die E-Mail somit mit einem temporären Fehler abgelehnt wird.


die Analyse:
  1. Absender hat bereits eine E-Mail erfolgreich zugestellt -> E-Mail sofort annehmen
  2. Absender in einer bekannten Whitelist -> E-Mail sofort annehmen
  3. Absender in einer bekannten Blacklist -> Greylisting
  4. Absender verwendet einen nicht standardkonformen Namen im SMTP-HELO, Absender kommt aus einem DialUp-Netzwerk etc… -> Greylisting
  5. SPF-Check (Sender Policy Framework) schlägt fehl -> Greylisting
  6. ansonsten -> E-Mail annehmen
Golov2009a.pdf (docs.google.com) -> S.42


Bley verwendet die Policy-Daemon-Schnittstelle des SMTP-Servers Postfix und ist somit leicht in existierende Umgebungen integrierbar bzw. “policyd-weight” zu ersetzen.
Als Vergleich wurde “bley” & “policyd-weight” auf einem Server mit ca 20.000 E-Mails/Tag getestet, dabei filterte policyd-weight 97,5% der E-Mails als Spam, bley 97%, der Vorteil von bley ist jedoch, dass E-Mails ggf. nicht Verzögert und nicht verloren gehen.
Für den praktischen Einsatz wird die Kombination von bley mit einer inhaltsbasierten Spam-Erkennung (z.B. SpamAssassin) vorgeschlagen. Dadurch, dass bley bereits die meisten Spam-Mails mit minimalem Rechenaufwand auf Protokollebene abweisen kann, müssen rechenaufwändige inhaltsbasierte Verfahren (z.B. SpamAssassin) nur noch auf eine sehr viel geringere Zahl von E-Mails angewendet werden.


Es folgt noch ein kurzes How-To: ;-)


Software nachinstallieren:

aptitude install python-setuptools python-twisted-core python-twisted-names python-spf python-psycopg2 postgresql python-pgsql

bley herunterladen und entpacken:

cd /usr/src
mkdir bley && cd bley
wget http://bley.mx/download/bley-0.1.4.tar.gz
tar xzvf bley-0.1.4.tar.gz
cd bley-0.1.4/

Datenbank anlegen:

su postgres
createuser bley
Enter password for new role: ********
Enter it again: ********
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n

createdb --owner=bley bley

exit

bley installieren:

python setup.py build
python setup.py install

cp -vp build/scripts-2.6/bley /usr/bin/

Konfiguration anpassen (Datenbank -> Passwort):

vim /etc/bley/bley.conf

Autostart für bley anlegen:

vim /etc/init.d/bley
#! /bin/sh
### BEGIN INIT INFO
# Provides:          bley
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: bley initscript
# Description:       intelligent greylisting daemon for Postfix.
### END INIT INFO

# Author: Evgeni Golov <evgeni@debian.org>

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="intelligent greylisting daemon for Postfix"
NAME=bley
DAEMON=/usr/bin/$NAME
DAEMON_ARGS=""
DAEMON_USER=$NAME
PIDFILE=/var/run/$NAME/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# Add pidfile to DAEMON_ARGS
DAEMON_ARGS="-p $PIDFILE $DAEMON_ARGS"

#
# Function that starts the daemon/service
#
do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started

	# prepare /var/run/bley which can be gone if /var/run is cleaned on reboot
	if [ ! -d /var/run/bley ]; then
		mkdir /var/run/bley
		chown bley:bley /var/run/bley
	fi

	# start bley
	start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON --test > /dev/null \
		|| return 1
	start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $DAEMON_USER --startas $DAEMON -- \
		$DAEMON_ARGS \
		|| return 2
	# Add code here, if necessary, that waits for the process to be ready
	# to handle requests from services started subsequently which depend
	# on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   2 if daemon could not be stopped
	#   other if a failure occurred
	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
	RETVAL="$?"
	[ "$RETVAL" = 2 ] && return 2
	# Wait for children to finish too if this is a daemon that forks
	# and if the daemon is only ever run from this initscript.
	# If the above conditions are not satisfied then add some other code
	# that waits for the process to drop all resources that could be
	# needed by services started subsequently.  A last resort is to
	# sleep for some time.
	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
	[ "$?" = 2 ] && return 2
	# Many daemons don't delete their pidfiles when they exit.
	rm -f $PIDFILE
	return "$RETVAL"
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  restart|force-reload)
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;; # Old process is still running
			*) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
	  	# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
	exit 3
	;;
esac

:
chmod +x bley

update-rc.d bley defaults

User anlegen & Rechte setzen:

adduser --system --quiet --disabled-password --no-create-home --home "/var/run/bley" --gecos "intelligent greylisting daemon for Postfix" --group bley
chown root:bley /etc/bley
chmod 750 /etc/bley
chown bley:bley /etc/bley/bley.conf
chmod 600 /etc/bley/bley.conf
vim /etc/bley/bley.conf

log_file = /var/log/bley/bley.log

cd /var/log
mkdir bley
chown bley:bley bley/
mkdir /var/run/bley
chown bley:bley /var/run/bley
/etc/init.d/bley start

Postfix anpassen:

vim /etc/postfix/main.cf
smtpd_recipient_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        #reject_invalid_hostname,
        #reject_unknown_recipient_domain,
        #reject_unauth_pipelining,
        reject_unauth_destination,
        #reject_non_fqdn_hostname,
        #reject_non_fqdn_sender,
        #reject_non_fqdn_recipient,
        #reject_unknown_sender_domain,
        #reject_unknown_recipient_domain,
        #reject_unauth_pipelining,
        #reject_unauth_destination,
        #check_client_access hash:/etc/postfix/rbl_override,
        check_policy_service inet:127.0.0.1:1337,
        ##check_policy_service inet:127.0.0.1:12525,
        #reject_rbl_client multi.uribl.com,
        #reject_rbl_client dsn.rfc-ignorant.org,
        ##reject_rbl_client dul.dnsbl.sorbs.net,
        #reject_rbl_client list.dsbl.org,
        #reject_rbl_client sbl-xbl.spamhaus.org,
        #reject_rbl_client bl.spamcop.net,
        ##reject_rbl_client dnsbl.sorbs.net,
        #reject_rbl_client cbl.abuseat.org,
        ##reject_rbl_client ix.dnsbl.manitu.net,
        #reject_rbl_client combined.rbl.msrbl.net,
        #reject_rbl_client rabl.nuclearelephant.com,
        permit

Postfix: E-Mails weiterleiten

Da ich momentan noch eine dynamische IP-Adresse zu-hause habe und somit keine E-Mails direkt verschicken kann, jedoch meine E-Mails welche von intern verschickt werden mit meiner Astaro-Firewall transparent auf Viren scanne, diese somit abgefangen werden und daher an einen anderen Mail-Server weiterleiten muss müssen, habe ich meinen entsprechenden Mail-Server, welche diese E-Mails erhält, so konfiguriert das alle E-Mails welche nicht intern zugestellt werden können, zum Relayhost weitergeleitet werden.

1.) als erstes müssen wir die Postfix-Konfiguration ein wenig anpassen

vim /etc/postfix/main.cf

[...]
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/saslpasswd
smtp_always_send_ehlo = yes
relayhost = smtp.deinProvider.de
[...]

“smtp.deinProvider.de” muss natürlich durch den DNS-Namen bzw. IP-Adresse ersetzt werden, zu der du die E-Mails schicken willst, bzw. welcher diese annimmt.

falls du die Mails an einen bestimmten Port weiterleiten musst,
Z.B. weil dein Provider die Authentifiezierung nur auf Port 587 zulasst, kannst du dies wie folgt bewerkstelligen.

relayhost = [smtp.deinProvider.de]:587

2.) nun müssen wir den entsprechenden Benutzernamen und das Passwort hinterlegen

wie bereits soeben in der Konfiguration angegeben hinterlegen wir den entsprechenden Benutzernamen und das Passwort an folgender Stelle…

vim /etc/postfix/saslpasswd

smtp.deinProvider.de Benutzernamen:Passwort

… mehr als diese eine Zeile muss/darf nicht in der Datei stehen.

3.) Hash /etc/postfix/saslpasswd

nun müssen wir die Datei noch kurz für Postfix vorbereiten

postmap /etc/postfix/saslpasswd

Postfix noch fix neu-starten und schon kannst du deine E-Mails auch von zu-hause aus verschicken.

/etc/init.d/postfix restart