Prevent spam with Mail Avenger, exim, SpamAssassin, bogofilter, procmail, and DNS
Problem
You receive too much spam.Keywords
spam, mailavenger, Mail Avenger, exim, DNS, procmail, SpamAssassin, bogofilter, Ubuntu, Debian.Solution
It's not really a solution. It's a half-hearted attempt.The attempt breaks down into several categories: making it hard to find you, making it hard to mail you, and then using the obvious tools to flag mail as spam.
Obviously, I'm not the first one to take a crack at this problem. Pretty much everything you read here I stole from other places.
Making it hard to find you: DNS
This is taken from the Spamassassin / OtherTricks wiki page. Instead of configuring a single MX, configure many, most of them fake:domain.com. 28800 IN MX 10 fake0.domain.com. domain.com. 28800 IN MX 20 realmx.domain.com. domain.com. 28800 IN MX 30 fake1.domain.com. domain.com. 28800 IN MX 40 fake2.domain.com. domain.com. 28800 IN MX 50 fake3.domain.com. domain.com. 28800 IN MX 60 fake4.domain.com. domain.com. 28800 IN MX 70 fake5.domain.com. domain.com. 28800 IN MX 80 fake6.domain.com. domain.com. 28800 IN MX 90 fake7.domain.com.Most spam / zombie software will give up after trying (and failing) on the first MX (fake0.domain.com). However, RFC compatible mail servers will move on to realmx.domain.com. Also, zombies that pick an MX at random have a reduced chance of picking the correct MX.
I strongly advise you to configure the lowest numbered MX to immediately reject TCP connections (by letting the operating system send a TCP RST packet, for example using an iptables REJECT rule) rather than having clients time out.
Preparation: configuring exim to work with Mail Avenger
First, it is likely you'll want to support virtual domains. This document assumes you followed the instructions for handling mail for multiple virtual domains with exim4.The changes you need to make to exim are to (among other things) allow emails with a '+' in them to work properly, which is one of the neat things you can do with Mail Avenger.
Create an avenger transport file /etc/exim4/conf.d/transport/30_exim4-config_avenger_pipe.
# /etc/exim4/conf.d/transport/30_exim4-config_avenger_pipe avenger_pipe: debug_print = "T: avenger_pipe for $local_part@$domain" driver = pipe path = "/bin:/usr/bin:/usr/local/bin" command = "/usr/local/libexec/avenger.local -D $local_part@$domain -d $local_part" return_path_add delivery_date_add envelope_to_addSecondly, create an avenger router /etc/exim4/conf.d/router/650_exim4-config_avenger.
# /etc/exim4/conf.d/router/650_exim4-config_avenger avenger: debug_print = "R: avenger for $local_part@$domain" driver = accept domains = +local_domains check_local_user transport = avenger_pipe require_files = /usr/local/libexec/avenger.local no_verify no_expnFinally, modify /etc/exim4/conf.d/router/350_exim4-config_vdom_aliases to accept '+' in email addresses.
# /etc/exim4/conf.d/router/350_exim4-config_vdom_aliases vdom_aliases: driver = redirect allow_defer allow_fail local_part_suffix = +* local_part_suffix_optional domains = dsearch;/etc/exim4/conf.d/virtual data = ${expand:${lookup{$local_part}lsearch*@{/etc/exim4/conf.d/virtual/$domain}}} retry_use_local_part pipe_transport = address_pipe file_transport = address_file no_moreFinally, you need to make sure exim only listens on localhost port 25. On Debian and Ubuntu, edit /etc/exim4/update-exim4.conf.conf and make sure that:
[...] dc_local_interfaces='127.0.0.1' [...]This frees up port 25 for Mail Avenger. Restart exim.
sudo /etc/init.d/exim4 restartIt is a good idea to keep an eye on /var/log/exim4/mainlog and /var/log/exim4/paniclog.
Making it hard to mail you: Mail Avenger
Mail Avenger is an elegant SMTP server that allows intended recipients to verify mail even before the mail has been accepted. Simply put, Mail Avenger picks up the phone, asks who's talking, puts the caller on hold, then talks to you, and hangs up on the caller should you decide you're not interested. You can decide this based on the sender address, based on the actual body of the message, and even on things like the TCP SYN fingerprint of the client SMTP server.Mail Avenger does a number of standard checks for you. First, it verifies that the sender can receive bounce messages (without actually sending one), which weeds out bogus senders. Secondly, it performs SPF checks on the sender, and, optionally, it can perform greylisting: deferring the sender, telling it to try again in a few minutes. This will, in some cases, slow down email a little bit, but it discourages most spammers, while RFC compliant senders will keep trying to deliver the message every few minutes.
There is no Ubuntu / Debian package for Mail Avenger (yet), so you have to compile and install it by hand. Follow the steps outlined in the Mail Avenger installation instructions. I remember having to install quite a few packages before being able to compile and build Mail Avenger. I configured and installed Mail Avenger as follows.
sudo ./configure --enable-sasl --enable-ssl sudo make installAfter step 5 from the Mail Avenger installation instructions (when you create /etc/avenger), make sure the directory is readable to the newly created avenger user:
sudo chmod 755 /etc/avenger/Here is my /etc/avenger/asmtpd.conf.
# /etc/avenger/asmtpd.conf # replace with your real IP BindAddr 123.123.123.123 Separator + Sendmail /usr/sbin/rmail AvengerUser Debian-exim SPFfail include:spf.trusted-forwarder.org MaxClients 60 MaxConPerIP 10 MaxRcpts 5 MaxMsgSize 104857600 SMTPTimeout 300 # see the smtpd.conf man page # SMTPFilter /etc/avenger/smtp-filter MXLocalRcpt 1 RBL zen.spamhaus.org RBL cbl.abuseat.org RBL combined.njabl.org RBL bl.spamcop.net RBL list.dsbl.org RBL dnsbl.sorbs.net RBL dul.dnsbl.sorbs.net DebugSMTP 1 DebugSMTPc 1 DebugAvenger 1 NoCheck postmaster NoCheck abuseObviously, you need to set the BindAddr variable. See also the asmtpd.conf(5) man page.
Make sure you fill the /etc/domains file with domains that you want Mail Avenger to accept mail for, or make sure MXLocalRcpt is set to 1 (and the BindAddr is the same IP as the MX for the domain(s) you want Mail Avenger to receive mail for). Here is an example /etc/avenger/domains file:
# /etc/avenger/domains domain1.com: domain2.com: domain3.com:Here is my /etc/avenger/default file (which happens to be also my /etc/avenger/unknown through a symbolic link: I am relying on exim to discard email to non-existent addresses).
# /etc/avenger/default and /etc/avenger/unknown errcheck case "$SPF0" in error) defer "Temporary error in SPF record processing" ;; pass) accept "SPF sender PASS" ;; esac greylist_delay=10m greylist_ttl1=5h greylist_ttl2=30D greylist "${CLIENT_IP%.*} $RECIPIENT $SENDER" bodytest /etc/avenger/clam acceptSee also the avenger(1) manual page.
This default file discards email that Mail Avenger has flagged as coming from a non-existent sender (errcheck). Then it immediately accepts email that comes from a SPF-verified sender (accept "SPF sender PASS"). Otherwise it greylists the sender's IP address (in fact, the /24) by telling it to send the email again in 10 minutes (greylist "${CLIENT_IP%.*} $RECIPIENT $SENDER"). Then (when the email comes a few minutes later), it gets scanned on viruses (bodytest) and, finally, provided it is clean, gets accepted and handed to exim (which is responsible for delivering it to the user).
Here is the /etc/avenger/clam file (which should probably be executable).
#!/bin/sh # this is /etc/avenger/clam edinplace out="`/usr/bin/clamdscan --no-summary - 2>&1`" if test "$?" = 1; then echo This message appears to be infected with a virus printf "%s\n" "$out" \ | sed -e '/Warning:/d' -e 's/^[^:]*: //' | sort -u exit 100 fi exit 0Notice that this relies on the clamav-daemon package being installed.
Make sure asmtpd starts on reboot by adding a @reboot root crontab entry or by adding it to rc.local! I opted for the former.
sudo crontab -eAdd a @reboot entry:
@reboot /usr/local/sbin/asmtpdFire up Mail Avenger.
sudo /usr/local/sbin/asmtpdYou can follow Mail Avenger's output by tailing /var/log/mail.info. It's probably a good idea to do that for a while.
sudo tail -f /var/log/mail.info
Train bogofilter
Plenty has been written about bogofilter already.My ~/.bogofilter.cf file.
bogofilter_dir=~/.bogofilter spam_header_name=X-Bogosity spamicity_tags = Yes, No, Unsure header_format = %h: %c, spamicity=%p ham_cutoff = 0.10 spam_cutoff= 0.90I train bogofilter on my email as follows (this assumes you created a file, ~/ham with non-spam, and a file, ~/spam with spam). Make sure the files contain roughly the same number of messages.
perl /usr/share/doc/bogofilter-common/examples/contrib/bogominitrain.pl -fnv \ ~/.bogofilter ~/ham ~/spam '-o 0.99,0.01'One thing I always get confused about is the following.
To tell bogofilter that a piece of mail is spam, where it wasn't sure yet:
/usr/bin/bogofilter -sTo tell bogofilter that a piece of mail is ham, where it wasn't sure yet:
/usr/bin/bogofilter -nTo tell bogofilter that a piece of mail is spam, where it wrongly classified and registered it as ham:
/usr/bin/bogofilter -N -sTo tell bogofilter that a piece of mail is ham, where it wrongly classified and registered it as spam:
/usr/bin/bogofilter -n -S
Configure SpamAssassin
Plenty has been written about SpamAssassin already.My ~/.spamassassin/user_prefs file, generated using the SpamAssassin Configuration Generator. (This file assumes you're OK with Dutch, English, German, and Hebrew mail!)
required_score 5.0 report_safe 0 use_bayes 0 bayes_auto_learn 1 skip_rbl_checks 0 use_razor2 1 use_dcc 1 use_pyzor 1 # OK with Dutch, English, German, and Hebrew ok_languages nl en de he ok_locales en add_header all Status _YESNO_, _HITS_, _TESTS(,)_Notice that, first of all, I disabled bayes learning because bogofilter does that already. One might argue that I should also disable RBL checks since Mail Avenger is doing it already. Secondly, this config relies on several Debian / Ubuntu packages being installed: razor, pyzor, and dcc-client.
I had to add the following lines to /etc/spamassassin/v320.pre.
loadplugin Mail::SpamAssassin::Plugin::TextCat loadplugin Mail::SpamAssassin::Plugin::DCCNow verify your configuration.
spamassassin --lint
Configure procmail
Plenty has been written about procmail already.Here are the relevant parts from my ~/.procmailrc file. This procmailrc assumes you're using Maildir and it assumes you have a spam/ folder and an unsure/ folder.
MAILDIR=$HOME/Maildir/ DEFAULT=$MAILDIR/ # Uncomment for debugging; set to no if you want minimal logging VERBOSE=yes LOGABSTRACT=all PMDIR=$HOME/.procmail LOGFILE=$PMDIR/log LINEBUF=32768 # ... # score it with bogofilter :0wf | /usr/bin/bogofilter -e -p -u -c ~/.bogofilter.cf # bogofilter says it's spam :0: * ^X-Bogosity: Yes spam/ # bogofilter says it's not spam. see what SpamAssassin thinks. :0fw |/usr/bin/spamassassin # If bogofilter isn't sure, but SpamAssassin is really sure, train # bogofilter and mark it as spam. :0 * ^X-Spam-Status: Yes * ^X-Bogosity: Unsure { :0wf | /usr/bin/bogofilter -e -s -c ~/.bogofilter.cf :0: spam/ } # bogofilter isn't sure, and SpamAssassin didn't say an outright yes :0: * ^X-Bogosity: Unsure unsure/ # ...It's a good idea to keep an eye on ~/.procmail/log while you're debugging this.