Introduction

This turorial use "postscreen", a feature to reduce spambot that was introduced in Postfix 2.8.0. To get this version on Lucid, you need to enable the backports repository. You can also enable my "mail" PPA to use the most recent Postfix version (as well as some other updated packages).

# Enable my "mail" PPA
echo "deb http://ppa.launchpad.net/sdeziel/mail/ubuntu lucid main" > /etc/apt/sources.list.d/sdeziel.list

# Import the associated key
wget -O - "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0xD79A41E52A38B3EB" | apt-key add -

# Update the package list
apt-get update

Content filter/Antispam setup

Install Amavisd-new, Spamassin, ClamAV and Pyzor (the only component from "universe") :

apt-get install --no-install-recommends amavisd-new libmail-spf-perl libio-socket-inet6-perl spamassassin perl-doc clamav clamav-daemon pyzor

ClamAV

Add clamav user to the amavis group and vice versa in order for Clamav to have access to scan files:

adduser clamav amavis
adduser amavis clamav

Enable the Google SafeBrowsing DB

cat << "EOF" >> /etc/clamav/freshclam.conf

# Check for signatures in Google Safe Browsing database
SafeBrowsing Yes
EOF

# Force the first download of the safebrowsing DB
service clamav-freshclam restart

Start the daemon

service clamav-daemon start

Spamassassin

Spamassassin can either run as a daemon or be invoked by Amavisd-new (prefered method here).

# Create the required dirs with appropriate permissions
mkdir -m 0700 /var/lib/amavis/.spamassassin
chown amavis:amavis /var/lib/amavis/.spamassassin

# Note that the 2 seds below are only needed when running spamd
# Drop root privileges allow SPAM/HAM learning from spamc and do not create
# user_prefs as the customization is done in /etc/spamassassin/local.cf directly
sed -i 's|^OPTIONS="\(.*\)"$|#OPTIONS="\1"\nOPTIONS="--max-spare=1 --max-children 2 -u amavis -g amavis --helper-home-dir=/var/lib/amavis --allow-tell --nouser-config"|' /etc/default/spamassassin
# Store the PID where spamd can read/write once setuid to the new low privileges user
sed -i 's|^PIDFILE="\(/var/run/spamd\.pid\)"$|#PIDFILE="\1"\nPIDFILE="/var/run/amavis/spamd.pid"|' /etc/default/spamassassin

# Enable auto update of Spamassassin's ruleset
sed -i 's/^\(CRON=0$\)/#\1\NCRON=1/' /etc/default/spamassassin

# Trigger a manual update
sa-update --verbose

# Customize Spamassassin's configuration
cat << "EOF" >> /etc/spamassassin/local.cf
# See 'perldoc Mail::SpamAssassin::Conf' for details of what can be tweaked.
###########################################################################

# Set which networks or hosts are considered 'trusted' by your mail
# server (i.e. not spammers)
trusted_networks 172.16.0.0/12 2001:470:b1c3::/48

# == reporting ==
#spamcop_from_address $obfuscated$
#spamcop_to_address   $obfuscated$

# == performance ==
# The Bayes DB is local (not on NFS)
lock_method flock

# == language ==
# TextCat - language guesser
loadplugin Mail::SpamAssassin::Plugin::TextCat
ifplugin Mail::SpamAssassin::Plugin::TextCat
# Mail using languages used in these country codes will not be marked
# as being possibly spam in a foreign language.
# - dutch english french
ok_languages            en fr

# Mail using locales used in these country codes will not be marked
# as being possibly spam in a foreign language.
ok_locales              en
endif # Mail::SpamAssassin::Plugin::TextCat

# == scores ==
# Speakers of any language that uses non-English, accented characters may wish
# to uncomment the following lines.   They turn off rules that fire on
# misformatted messages generated by common mail apps in contravention of the
# email RFCs.
score SUBJ_ILLEGAL_CHARS      0
EOF

# Start the daemon
service spamassassin start

Amavis

Configure Amavis to our taste

cat << "EOF" > /etc/amavis/conf.d/50-user
use strict;

#
# Place your configuration directives here.  They will override those in
# earlier files.
#
# See /usr/share/doc/amavisd-new/ for documentation and examples of
# the directives you can use in this file
#

# == 15-content_filter_mode ==
@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

# == 20-debian_defaults ==
$sa_tag_level_deflt  = -999; # Always add spam info headers
$sa_tag2_level_deflt = 5.0;  # add 'spam detected' headers at that level
$sa_kill_level_deflt = 12.0; # triggers spam evasive actions

# Do not add a useless header that also reveils the OS
$X_HEADER_LINE = undef;

# Reduce the number of amavis processes
$max_servers = 1;

# All spam will be forward to a mailbox
$spam_quarantine_to = "sa+spam\@$mydomain";
# Spam notification will be send to
$spam_admin = "sa+spam\@$mydomain";

# All virus infected mail will be forward to a mailbox
$virus_quarantine_to = "sa+virus\@$mydomain";
# Virus notification will be send to
$virus_admin = "sa+virus\@$mydomain";

#------------ Do not modify anything below this line -------------
1;  # ensure a defined return
EOF

DKIM signing

Setup DKIM

mkdir /etc/amavis/dkim

# Generate a private key (1024 bit is the default size)
amavisd-new genrsa /etc/amavis/dkim/sdeziel.info-key.pem


Start the daemon and test if

Start and test Amavis

# Start Amavis
service amavis start

# Test if amavis is working
amavisd-nanny -c 1

Configure Postfix to use Amavis


# Add required transports to master.cf
cat << "EOF" >> /etc/postfix/master.cf

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
# Injection point for mail going to the content filtering
lmtp-filter unix -      -       -       -       2       lmtp
    -o lmtp_data_done_timeout=1200
    -o lmtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o lmtp_tls_note_starttls_offer=no
    -o max_use=20

# Reinjection point for mail comming from the contentfilter
127.0.0.1:10025     inet  n       -       -       -       -       smtpd
    -o content_filter=
    -o smtpd_delay_reject=no
    -o smtpd_helo_restrictions=
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o smtpd_restriction_classes=
    -o mynetworks=127.0.0.0/8
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
    -o local_header_rewrite_clients=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o strict_rfc821_envelopes=yes
    -o smtpd_authorized_xforward_hosts=$mynetworks
    -o smtp_tls_note_starttls_offer=no

# == Spamassassin ==
# Spam report + spam training
spamreport    unix  -       n       n       -       -       pipe
  flags=D user=amavis argv=/usr/bin/spamc --reporttype=report
# Spam revoke + ham training
spamrevoke    unix  -       n       n       -       -       pipe
  flags=D user=amavis argv=/usr/bin/spamc --reporttype=revoke
# Spam training
spamtraining  unix  -       n       n       -       -       pipe
  flags=D user=amavis argv=/usr/bin/spamc --learntype=spam
# Ham training
hamtraining   unix  -       n       n       -       -       pipe
  flags=D user=amavis argv=/usr/bin/spamc --learntype=ham
EOF

# Enable the content filter
postconf -e "content_filter = lmtp-filter:[127.0.0.1]:10024"

Postfix

# Install additional lookup table engines apt-get install postfix-cdb postfix-pcre

pflogsum

doorway

Install the pflogsumm to have analysis reports :

apt-get install pflogsumm

Enable daily and weekly reports :

# This is important to install them with a name that have them called by cron before
# any logrotation occurs. Using the "00" prefix takes care of that on Ubuntu.
install -m 755 /usr/share/doc/pflogsumm/examples/cron.daily /etc/cron.daily/00pflogsumm
install -m 755 /usr/share/doc/pflogsumm/examples/cron.weekly /etc/cron.weekly/00pflogsumm

# Properly handle aggregation of the daily rotated (and compressed) logs to get last day's logs (and some more but the -d yesterday will use the timestamps)
sed -i 's#^\([[:space:]]\+\)\(/usr/sbin/pflogsumm -d yesterday --problems_first\).*$#\1(cat /var/log/mail.log.1 /var/log/mail.log) | \2#' /etc/cron.daily/00pflogsumm

# Properly handle aggregation of the daily rotated (and compressed) logs to get a week worth of the logs
sed -i 's#^\([[:space:]]\+\)\(/usr/sbin/pflogsumm --problems_first\).*$#\1for i in $(seq 8 -1 2); do zcat /var/log/mail.log.$i.gz; done | \2#' /etc/cron.weekly/00pflogsumm