Debian: Postfix + Amavis (Spamassassin + Clamav)

amavisd-new is a high-performance interface between mailer (MTA) and content checkers: virus scanners, and/or SpamAssassin. It is written in Perl for maintainability, without paying a significant price for speed. It talks to MTA via (E)SMTP or LMTP, or by using helper programs. Best with Postfix, fine with dual-sendmail setup and Exim v4, works with sendmail/milter, or with any MTA as a SMTP relay. For Courier and qmail MTA integration there is a patch in the distributed package.

Step 1: Install Packages

First, make sure that amavis, spamassassin and clamav are installed. On a Debian instance, you can do this with:

# apt install amavisd-new spamassassin clamav-daemon clamav-freshclam razor
# apt install arj bzip2 cabextract cpio file gzip lha nomarch pax rar unrar unzip unzoo zip zooCode language: PHP (php)

Step 2: ClamAV

The default behaviour of Clamav will fit our needs. A daemon is launched (clamd) and signatures are fetched every day. For more Clamav configuration options, check the configuration files in /etc/clamav.

Make sure the clamd service is enabled and restart it:

# systemctl enable clamd
# systemctl restart clamdCode language: PHP (php)

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

# adduser clamav amavis
# adduser amavis clamavCode language: PHP (php)

Step 3: Spamassassin

As amavis is its own spamassassin-daemon (amavis uses the spamassassin libraries), there is no need in configuring or starting spamassassin. amavis will not use any running instance of spamd! Even changes in /etc/spamassassin will have no effect on the behaviour of amavis.

Edit the local spamassassin configuration file /etc/spamassassin/local.cf

# This is the right place to customize your installation of SpamAssassin.
# See 'perldoc Mail::SpamAssassin::Conf' for details of what can be
# tweaked.
# Only a small subset of options are listed below
############################################################################

#   Add *****SPAM***** to the Subject header of spam e-mails
#
# rewrite_header Subject *****SPAM*****

#   Save spam messages as a message/rfc822 MIME attachment instead of
#   modifying the original message (0: off, 2: use text/plain instead)
#
# report_safe 1

#   Set which networks or hosts are considered 'trusted' by your mail
#   server (i.e. not spammers)
#
# trusted_networks 212.17.35.
# 192.168.x already included
trusted_networks 45.138.55.145 2a10:3781:53c::1 2001:41d0:701:1100::6807 135.125.133.125

#   Set file-locking method (flock is not safe over NFS, but is faster)
#
# lock_method flock

#   Set the threshold at which a message is considered spam (default: 5.0)
#
# required_score 5.0

#   Use Bayesian classifier (default: 1)
#
use_bayes 1

#   Bayesian classifier auto-learning (default: 1)
#
bayes_auto_learn 1

#   Set headers which may provide inappropriate cues to the Bayesian#   classifier
#
# bayes_ignore_header X-Bogosity
# bayes_ignore_header X-Spam-Flag
# bayes_ignore_header X-Spam-Status

#   Whether to decode non- UTF-8 and non-ASCII textual parts and recode
#   them to UTF-8 before the text is given over to rules processing.
#
# normalize_charset 1

#   Some shortcircuiting, if the plugin is enabled
#
ifplugin Mail::SpamAssassin::Plugin::Shortcircuit
#
#   default: strongly-whitelisted mails are *really* whitelisted now, if the
#   shortcircuiting plugin is active, causing early exit to save CPU load.
#   Uncomment to turn this on
#
# shortcircuit USER_IN_WHITELIST       on
# shortcircuit USER_IN_DEF_WHITELIST   on
# shortcircuit USER_IN_ALL_SPAM_TO     on
# shortcircuit SUBJECT_IN_WHITELIST    on

#   the opposite; blacklisted mails can also save CPU
#
# shortcircuit USER_IN_BLACKLIST       on
# shortcircuit USER_IN_BLACKLIST_TO    on
# shortcircuit SUBJECT_IN_BLACKLIST    on

#   if you have taken the time to correctly specify your "trusted_networks",
#   this is another good way to save CPU
#
# shortcircuit ALL_TRUSTED             on

#   and a well-trained bayes DB can save running rules, too
#
# shortcircuit BAYES_99                spam
# shortcircuit BAYES_00                ham

endif # Mail::SpamAssassin::Plugin::ShortcircuitCode language: PHP (php)

The use of razor and pyzormust be enabled by

# su - amavis -s /bin/bash
# razor-admin -create
# razor-admin -register
# pyzor discoverCode language: PHP (php)

Step 4: Amavis

Edit /etc/amavis/conf.d/15-content_filter_mode to activate ClamAV and SpamAssassin:

use strict;

# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.

#
# Default antivirus checking mode
# Uncomment the two lines below to enable it
#
@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

#
# Default SPAM checking mode
# Uncomment the two lines below to enable it
#
@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

1;  # insure a defined returnCode language: PHP (php)

Edit /etc/amavis/conf.d/50-user to activate ClamAV and SpamAssassin:

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
#
$myhostname = 'mailcore-01.<domain.com>';  # Replace with your FQDN
@local_domains_maps = ( [".<domain.com>"] );  # Your domain
$inet_socket_port = [10024];  # Listen for Postfix
$forward_method = 'smtp:127.0.0.1:10025';  # Reinject to Postfix
$sa_tag_level_deflt  = 2.0;   # Add spam headers at this score
$sa_tag2_level_deflt = 6.0;   # Mark as spam
$sa_kill_level_deflt = 10.0;  # Quarantine or reject
$sa_spam_subject_tag = '[SPAM] ';  # Tag spam subject
$final_virus_destiny = D_DISCARD;  # Discard viruses
$final_spam_destiny  = D_BOUNCE;   # Reject spam (or D_DISCARD for quarantine)
$sa_mail_body_size_limit = 400000; # Max email size for SA
#@av_scanners = (
  #['ClamAV-clamd', \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.ctl"],
   #qr/\bOK$/, qr/\bFOUND$/, qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
#);

# adding additional decoders
@decoders = (
  ['lrz',  ['lrzip', '-q', '-k', '-d', '-o', '-']],
  ['lz4',  ['lz4c', '-d']],
  ['zoo',  ['zoo']],
  ['doc',  ['catdoc'], ['antiword']],
);

$enable_dkim_signing = 0;

#------------ Do not modify anything below this line -------------
1;  # ensure a defined return
Code language: PHP (php)

Make sure the amavis service is enabled and restart it:

# systemctl enable amavis
# systemctl restart amavisCode language: PHP (php)

Step 5: Postfix Integration

Define the content_filter configuration in the Postfix configuration file in  /etc/postfix/main.cf

# postconf -e "content_filter = smtp-amavis:[127.0.0.1]:10024"Code language: PHP (php)

Next edit  /etc/postfix/master.cfand add the following to the end of the file:

smtp-amavis unix - - n - 2 smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o smtp_dns_support_level=disabled
    -o max_use=20
127.0.0.1:10025 inet n - n - - smtpd
    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -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 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

Restart postfix and test the configuration by monitoring the mail log file when sending emails.

# systemctl restart postfixCode language: PHP (php)