Thursday, May 8, 2014

Postfix dovecot sasl amavisd-new clamav spamassassin postgrey opendkim vitual domains on Debian 7 (Wheezy)

Introduction
In this setup is for a small to medium sized email server with Postfix virtual mailboxes which can be used for multiple domains and non-Linux accounts. If you are new to Postfix please read PostfixBasicSetupHowto to understand the basics before proceeding with this Howto. Also, information is presented about integration with ClamSMTP (an SMTP filter for Postfix) and other mail servers that check for viruses (using the ClamAV anti-virus software).

Example Setup
In this example emails are hosted for two separate domains, domain1.com and domain2.com. (Replace these with your own domain names.

Install Postfix
Install the postfix package.
For convenience in testing mail delivery, also install mailx package for use as command line mail utility program. (mailx is a dummy package for one of three mail programs, the most widely used of which is bsd-mailx.)
$ sudo apt-get install postfix bsd-mailx

Set Postfix Support for Maildir style Mailboxes
Maildir is an e-mail spool format that does not require file-locking to maintain message integrity because the messages are kept in separate files with unique names. A Maildir is a directory (often named Maildir) with three subdirectories named tmp, new, and cur. The subdirectories should all reside on the same filesystem.
Please find out more about Maildir here.
sudo nano /etc/postfix/main.cf

Add the following code segment:
home_mailbox = Maildir/

Restart Postfix to effect the changes.
sudo /etc/init.d/postfix restart

Postfix virtual Mailboxes for separate domains and Non-Linux accounts
As a system hosts more and more domains and users, it becomes less desirable to give every user their own Linux system account.

With the Postfix virtual mailbox delivery agent, every recipient address can have its own virtual mailbox. Unlike virtual alias domains, virtual mailbox domains do not need the translation from each recipient addresses into a different address, and owners of a virtual mailbox address do not need to have a Linux system account.

The Postfix virtual mailbox delivery agent looks up the user mailbox pathname, uid and gid via separate tables that are searched with the recipient's mail address. Maildir style delivery is designated by terminating the mailbox pathname with a "/".

The following figure shows a directory structure for mailboxes.

It is best to transfer all domains into virtual mailboxes. Even if you have setup postfix with one domain, make that domain a virtual domain. You aren't required to do this, but doing it this will give you a well organized mail system from the outset. Having Postfix host one real domain and the rest virtual means that you will always need to configure Postfix twice: once for each type of domain. 

Create a virtual Mailbox owner
In our setup all virtual mailboxes are owned by a fixed uid and gid 5000. (If this is not what you want, specify lookup tables that are searched by the recipient's mail address.)
To create a virtual mailbox group:
sudo groupadd -g 5000 vmail

To create a virtual mailbox owner:
sudo useradd -m -u 5000 -g 5000 -s /bin/bash vmail

Edit main.cf
sudo vi /etc/postfix/main.cf

Set up Postfix to use virtual mailboxes
Add the following code segment to main.cf
virtual_mailbox_domains = /etc/postfix/vhosts
virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = hash:/etc/postfix/vmaps
virtual_minimum_uid = 1000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

In the first line is used a text file called vhosts. (You can name this anything you want.) Inside this text file will be a simple one-column list of all the domains you are hosting. Add your domains there.
sudo nano /etc/postfix/vhosts

Obviously, use your own domain names instead of the domain examples:
domain1.com
domain2.com

The next line virtual_mailbox_base specifies the base directory where the mail will be stored. (Again, you can choose anything you want.) In our case it will be the '''vmail''' subdirectory of the owner's home directory /home/vmail

The third line points to a text file named '''vmaps'''. This is a two column text file. The first column specifies a virtual email address. The second column specifies the person's mailbox location. Just like with real domain hosting, if you specify a / at the end of the location, it designates a Maildir format. (If not, it is mbox.) In this Howto we are using the Maildir format.

Setup this file:
sudo nano /etc/postfix/vmaps

The format should look like:
info@domain1.com  domain1.com/info/
alias@domain1.com  domain1.com/info/
sales@domain1.com  domain1.com/sales/
info@domain2.com  domain2.com/info/
sales@domain2.com  domain2.com/sales/

Note: To make an alias, map to same folder as another user.
Convert vmaps into a hash file by running:
sudo postmap /etc/postfix/vmaps

Remember to execute the above command every time when you add a new map.
Restart Postfix to make the changes take effect.
sudo  /etc/init.d/postfix restart

My example config now looks like:
# See /usr/share/postfix/main.cf.dist for a commented, more complete version

# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = mail.abc.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = mail.domain1.com, localhost.domain1.com, , localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.16.0.0/16
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

# Maildir style Mailboxes
home_mailbox = Maildir/

# Virtual mailboxes
virtual_mailbox_domains = /etc/postfix/vhosts
virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = hash:/etc/postfix/vmaps
virtual_minimum_uid = 1000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

Test virtual mailbox setup
The directory structure for a particular user is created when he gets his first mail.
Send a mail to info@domain1.com
In a terminal you can type:
mail info@domain1.com

Check the mailbox
cd /home/vmail/domain1/info/new
$ ls

You should see a mail file there. If so, you've done it! 

Set up non-Linux accounts
There are several popular techniques to do this using services such as OpenLDAP or MySQL and mixing them with Courier IMAP. We won't be using those. Instead, we're going to use something simpler: plain text files.

We'll accomplish this with Dovecot. Dovecot is lightweight, flexible, and secure. 
The following command installs Dovecot but removes Courier IMAP (if you have already have them installed).

Install Dovecot IMAP
Install the packages: dovecot-imapd
sudo apt-get install dovecot-imapd

Configure Dovecot
You need to set up Dovecot to work with our setup. It is best to backup your original dovecot config file and create a new one (based on a copy of the file here).
Backup the original config file:
sudo mv /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig

Create a new config file and copy the new config file into it:
sudo vi /etc/dovecot/dovecot.conf

My output of dovecot -n:
# 2.1.7: /etc/dovecot/dovecot.conf
# OS: Linux 3.2.0-4-amd64 x86_64 Debian 7.5 ext4
auth_mechanisms = plain cram-md5
auth_verbose = yes
base_dir = /var/run/dovecot/
info_log_path = /var/log/dovecot.info
log_path = /var/log/dovecot
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/home/vmail/%d/%n
namespace inbox {
  inbox = yes
  location =
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox Junk {
    special_use = \Junk
  }
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
  mailbox Trash {
    special_use = \Trash
  }
  prefix =
}
passdb {
  args = /etc/dovecot/passwd
  driver = passwd-file
}
plugin {
  sieve = ~/.dovecot.sieve
  sieve_dir = ~/sieve
}
protocols = " imap"
service auth {
  executable = /usr/lib/dovecot/auth
  #unix_listener /var/spool/postfix/private/auth {
    #group = postfix
    #mode = 0666
    #user = postfix
  #}
  user = root
}
service imap-login {
  chroot = login
  executable = /usr/lib/dovecot/imap-login
  user = dovecot
}
service imap {
  executable = /usr/lib/dovecot/imap
}
service pop3-login {
  chroot = login
  executable = /usr/lib/dovecot/pop3-login
  user = dovecot
}
service pop3 {
  executable = /usr/lib/dovecot/pop3
}
ssl = no
userdb {
  args = /etc/dovecot/users
  driver = passwd-file
}
valid_chroot_dirs = /var/spool/vmail

In Debian 7, you may need to edit many file located in /etc/dovecot/conf.d/
10-auth.conf      10-tcpwrapper.conf  90-quota.conf                auth-passwdfile.conf.ext
10-director.conf  15-lda.conf         90-sieve.conf                auth-sql.conf.ext
10-logging.conf   15-mailboxes.conf   auth-checkpassword.conf.ext  auth-static.conf.ext
10-mail.conf      20-imap.conf        auth-deny.conf.ext           auth-system.conf.ext
10-master.conf    90-acl.conf         auth-ldap.conf.ext           auth-vpopmail.conf.ext
10-ssl.conf       90-plugin.conf      auth-master.conf.ext

Several of the config lines require explanation.
The line "mail_location = maildir:/home/vmail/%d/%n" is particularly important. In our virtual hosting set up, the way we distinguish one user from another is to have them log in with their full email address. For example, when the email account is "info@domain1.com", Dovecot does some guessing on its end about your user name. If it just sees something like "info", it sets a variable called "%n"to "info". If it sees "info@domain1.com", it will split it up and set "%d" to domain1.com and "%n" to "info". Using that paradigm, if we replace the variables in this line , we get something like: maildir:/home/vmail/domain1.com/info
The lines "args = /etc/dovecot/passwd" and "args = /etc/dovecot/users" are similar to the /etc/passwd and /etc/shadow system files. 

The format of these files is similar to this:
/etc/dovecot/users:
info@domain1.com::5000:5000::/home/vmail/domain1.com/:/bin/false::

/etc/dovecot/passwd:
info@domain1.com:$1$G/FqlOG5$Vj0xmc9fKY.UVr8OWr/7C1

The 5000:5000 corresponds to the uid and gid of the "virtual" called vmail (which owns all the mailboxes in the system). The home directory includes everything but the word before the @ in the email address. 

Note: It is possible to use a single file for the user/passwd with the following format:
/etc/dovecot/passwd:
info@domain1.com:$1$G/FqlOG5$Vj0xmc9fKY.UVr8OWr/7C1:5000:5000::/home/vmail/domain1.com/:/bin/false::

Create Dovecot Users
There are no commands like useradd and passwd to add users and passwords for our mail system. A bash script provides a small and quick solution.

Files:
/etc/dovecot/users - Similar to /etc/passwd
/etc/dovecot/passwd - Similar to /etc/shadow
/etc/postfix/vmaps - Map virtual users to mail directory (for postfix). If changes are made, use postmap /etc/postfix/vmaps && service postfix reload.

Scripts to Add and Delete Users
Create file:
sudo nano /usr/local/sbin/adddovecotuser 

Add the following code segment and save the file:
#!/bin/sh
if [ ! $# = 1 ]
 then
  echo "Usage: $0 username@domain"
  exit 1
else
  user=`echo "$1" | cut -f1 -d "@"`
  domain=`echo "$1" | cut -s -f2 -d "@"`
  if [ -x $domain ]
   then
    echo "No domain given\nUsage: $0 username@domain"
    exit 2
  fi
  echo "Adding user $user@$domain to /etc/dovecot/users"
  echo "$user@$domain::5000:5000::/home/vmail/$domain/$user/:/bin/false::" >> /etc/dovecot/users

  # Create the needed Maildir directories
  echo "Creating user directory /home/vmail/$domain/$user"
  # maildirmake.dovecot does only chown on user directory, we'll create domain directory instead
  if [ ! -x /home/vmail/$domain ]
   then
    mkdir /home/vmail/$domain
    chown 5000:5000 /home/vmail/$domain
    chmod 700 /home/vmail/$domain
  fi
  /usr/bin/maildirmake.dovecot /home/vmail/$domain/$user 5000:5000
  # Also make folders for Drafts, Sent, Junk and Trash
  /usr/bin/maildirmake.dovecot /home/vmail/$domain/$user/.Drafts 5000:5000
  /usr/bin/maildirmake.dovecot /home/vmail/$domain/$user/.Sent 5000:5000
  /usr/bin/maildirmake.dovecot /home/vmail/$domain/$user/.Junk 5000:5000
  /usr/bin/maildirmake.dovecot /home/vmail/$domain/$user/.Trash 5000:5000
# To add user to Postfix virtual map file and reload Postfix
  echo "Adding user to /etc/postfix/vmaps"
  echo $1  $domain/$user/ >> /etc/postfix/vmaps
  postmap /etc/postfix/vmaps
  postfix reload
fi
echo "\nCreate a password for the new email user"
#SWAP THE FOLLOWING passwd LINES IF USING A UBUNTU VERSION PRIOR TO 12.04
#passwd=`dovecotpw`
passwd=`doveadm pw -u $user`
echo "Adding password for $user@$domain to /etc/dovecot/passwd"
if [ ! -x /etc/dovecot/passwd ]
 then
  touch /etc/dovecot/passwd
  chmod 640 /etc/dovecot/passwd
fi
echo  "$user@$domain:$passwd" >> /etc/dovecot/passwd

exit 0

Make the file executable:
$ sudo chmod +x /usr/local/sbin/adddovecotuser 
 
Add a user like this:
$ sudo adddovecotuser info@domain1.com

We'll create one for deleting users too:
sudo vi /usr/local/sbin/deldovecotuser

Add the following code segment and save the file:
#!/bin/bash
#
# deldovecotuser - for deleting virtual dovecot users
#
if [ ! $# = 1 ]
 then
  echo -e "Usage: $0 username@domain"
  exit 1
 else
  user=`echo "$1" | cut -f1 -d "@"`
  domain=`echo "$1" | cut -s -f2 -d "@"`
  if [ -x $domain ]
   then
    echo -e "No domain given\nUsage: $0 username@domain: "
    exit 2
  fi
fi
read -n 1 -p "Delete user $user@$domain from dovecot? [Y/N]? "
echo
case $REPLY in
 y | Y)
  new_users=`grep -v $user@$domain /etc/dovecot/users`
  new_passwd=`grep -v $user@$domain /etc/dovecot/passwd`
  new_vmaps=`grep -v $user@$domain /etc/postfix/vmaps`
  echo "Deleting $user@$domain from /etc/dovecot/users"
  echo "$new_users" > /etc/dovecot/users
  echo "Deleting $user@$domain from /etc/dovecot/passwd"
  echo "$new_passwd" > /etc/dovecot/passwd
  echo "Deleting $user@$domain from /etc/postfix/vmaps"
  echo "$new_vmaps" > /etc/postfix/vmaps
  postmap /etc/postfix/vmaps
  postfix reload
  read -n1 -p "Delete all files in /home/vmail/$domain/$user? [Y/N]? " DELETE
  echo
  case $DELETE in
   y | Y)
    echo "Deleting files in /home/vmail/$domain/$user"
    rm -fr /home/vmail/$domain/$user
   ;;
   * )
    echo "Not deleting files in /home/vmail/$domain/$user"
   ;;
  esac
 ;;
 * )
  echo "Aborting..."
 ;;
esac

Make the file executable:
sudo chmod +x /usr/local/sbin/deldovecotuser

Delete a user like this:
sudo deldovecotuser info@domain1.com

To start Devecot for the first time
sudo /etc/init.d/dovecot start

C#/Mono Application to Add Users
An alternative to the scripts below for adding users and creating passwords, there is an Open Source tool written in C# and compiles in Mono to do this same task. It offers a few more error checks and prompts. It incorporates the scripts into one tool for Postfix and Dovecot. You can find it here

Postfix SASL
If you would like your mail users to authenticate to Postfix too, we need to configure Postfix for SASL. In that way, the mail server can relay email from users not in local network.

Make Dovecot listen for authentication requests
In /etc/dovecot/dovecot.conf edit the auth section to:
service auth {
  executable = /usr/lib/dovecot/auth
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0666
    user = postfix
  }
  user = root
}

Note: Code above needs an update for versions 12.04 and after. Dovecot packed with those systems does'nt work with these settings anymore.
Restart dovecot.
sudo /etc/init.d/dovecot start

Configure Postfix SASL.
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noplaintext,noanonymous
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
sudo echo "mech_list: cram-md5" > /etc/postfix/sasl/smtpd.conf

Restart Postfix.
sudo /etc/init.d/postfix start

Test the Setup
With mutt
Type in a terminal:
mutt -f  pop://mail.domain1.com

or:
mutt -f  imap://mail.domain1.com

Input your user name and password as requested. When logged in, shortcuts are displayed in top of window. Press q to quit.

Tip1: If your DNS lookup doesn't work yet, you can use mutt -f pop://localhost when on server.

Tip2: You can use auth_default_realm = domain1.com in dovecot.conf and omit @domain1.com in your user name when logging in.

With telnet
Telnet is more verbose. Type in a terminal:
telnet localhost 110

Note: This only works when traffic is local, since we have set disable_plaintext_auth = yes.

Type the following code segment in the prompt provided by the Dovecot POP3 server
user info@domain1.com
pass password
quit

Final output should be something like this
Trying 127.0.0.1...
Connected to mail.domain1.com.
Escape character is '^]'.
+OK dovecot ready.
user info@domain1.com
+OK
pass password
+OK Logged in.
quit
+OK Logging out.

Mail Filtering
One of the largest issues with email today is the problem of Unsolicited Bulk Email (UBE). Also known as SPAM, such messages may also carry viruses and other forms of malware. According to some reports these messages make up the bulk of all email traffic on the Internet.

This section will cover integrating Amavisd-new, Spamassassin, and ClamAV with the Postfix Mail Transport Agent (MTA). Postfix can also check email validity by passing it through external content filters. These filters can sometimes determine if a message is spam without needing to process it with more resource intensive applications. Two common filters are opendkim and python-policyd-spf.

Amavisd-new is a wrapper program that can call any number of content filtering programs for spam detection, antivirus, etc.

Spamassassin uses a variety of mechanisms to filter email based on the message content.
ClamAV is an open source antivirus application.

opendkim implements a Sendmail Mail Filter (Milter) for the DomainKeys Identified Mail (DKIM) standard.

python-policyd-spf enables Sender Policy Framework (SPF) checking with Postfix.

This is how the pieces fit together:
An email message is accepted by Postfix. The message is passed through any external filters opendkim and python-policyd-spf in this case. Amavisd-new then processes the message. ClamAV is used to scan the message. If the message contains a virus Postfix will reject the message.

Clean messages will then be analyzed by Spamassassin to find out if the message is spam. Spamassassin will then add X-Header lines allowing Amavisd-new to further manipulate the message.

For example, if a message has a Spam score of over fifty the message could be automatically dropped from the queue without the recipient ever having to be bothered. Another, way to handle flagged messages is to deliver them to the Mail User Agent (MUA) allowing the user to deal with the message as they see fit.

Installation
To install the rest of the applications enter the following from a terminal prompt:
telnet localhost 110

sudo apt-get install amavisd-new spamassassin clamav-daemon
sudo apt-get install opendkim postfix-policyd-spf-python
There are some optional packages that integrate with Spamassassin for better spam detection:

sudo apt-get install pyzor razor

Along with the main filtering applications compression utilities are needed to process some email attachments:
sudo apt-get install arj cabextract cpio lhasa nomarch pax rar unrar unzip zip

If some packages are not found, check that the multiverse repository is enabled in /etc/apt/sources.list

If you make changes to the file, be sure to run sudo apt-get update before trying to install again.

Configuration
Now configure everything to work together and filter email.

ClamAV
The default behaviour of ClamAV will fit our needs. For more ClamAV configuration options, check the configuration files in /etc/clamav.

Add the clamav user to the amavis group in order for Amavisd-new to have the appropriate access to scan files:
sudo adduser clamav amavis
sudo adduser amavis clamav

Spamassassin
Spamassassin automatically detects optional components and will use them if they are present. This means that there is no need to configurepyzor and razor.

Edit /etc/default/spamassassin to activate the Spamassassin daemon. Change ENABLED=0 to:
ENABLED=1

Now start the daemon:
sudo service spamassassin start

Amavisd-new
First activate spam and antivirus detection in Amavisd-new by editing /etc/amavis/conf.d/15-content_filter_mode:
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 return

Bouncing spam can be a bad idea as the return address is often faked. Consider editing /etc/amavis/conf.d/20-debian_defaults to set $final_spam_destiny to D_DISCARD rather than D_BOUNCE, as follows:
$final_spam_destiny       = D_DISCARD;

Additionally, you may want to adjust the following options to flag more messages as spam:
$sa_tag_level_deflt = -999; # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 6.0; # add 'spam detected' headers at that level
$sa_kill_level_deflt = 21.0; # triggers spam evasive actions
$sa_dsn_cutoff_level = 4; # spam level beyond which a DSN is not sent

If the server's hostname is different from the domain's MX record you may need to manually set the $myhostname option. Also, if the server receives mail for multiple domains the @local_domains_acl option will need to be customized. Edit the /etc/amavis/conf.d/50-user file:
$myhostname = 'mail.example.com';
@local_domains_acl = ( "example.com", "example.org" );

If you want to cover multiple domains you can use the following in the/etc/amavis/conf.d/50-user
@local_domains_acl = qw(.);

After configuration Amavisd-new needs to be restarted:
sudo service amavis restart

DKIM Whitelist
Amavisd-new can be configured to automatically Whitelist addresses from domains with valid Domain Keys. There are some pre-configured domains in the /etc/amavis/conf.d/40-policy_banks.

There are multiple ways to configure the Whitelist for a domain:
  • 'example.com' => 'WHITELIST',: will whitelist any address from the "example.com" domain.
  • '.example.com' => 'WHITELIST',: will whitelist any address from any subdomains of "example.com" that have a valid signature.
  • '.example.com/@example.com' => 'WHITELIST',: will whitelist subdomains of "example.com" that use the signature of example.comthe parent domain.
  • './@example.com' => 'WHITELIST',: adds addresses that have a valid signature from "example.com". This is usually used for discussion groups that sign their messages.
A domain can also have multiple Whitelist configurations. After editing the file, restart amavisd-new:
sudo service amavis restart

In this context, once a domain has been added to the Whitelist the message will not receive any anti-virus or spam filtering. This may or may not be the intended behavior you wish for a domain.

Postfix
For Postfix integration, enter the following from a terminal prompt:
$ sudo postconf -e 'content_filter = smtp-amavis:[127.0.0.1]:10024'

Next edit /etc/postfix/master.cf and add the following to the end of the file:
smtp-amavis     unix    -       -       -       -       2       smtp
        -o smtp_data_done_timeout=1200
        -o smtp_send_xforward_command=yes
        -o disable_dns_lookups=yes
        -o max_use=20

127.0.0.1:10025 inet    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,no_milters
Also add the following two lines immediately below the "pickup" transport service:
         -o content_filter=
         -o receive_override_options=no_header_body_checks

This will prevent messages that are generated to report on spam from being classified as spam.

Now restart Postfix:
sudo service postfix restart

Content filtering with spam and virus detection is now enabled.

Amavisd-new and Spamassassin
When integrating Amavisd-new with Spamassassin, if you choose to disable the bayes filtering by editing /etc/spamassassin/local.cfand use cron to update the nightly rules, the result can cause a situation where a large amount of error messages are sent to the amavis user via the amavisd-new cron job.

There are several ways to handle this situation:
Configure your MDA to filter messages you do not wish to see.
Change /usr/sbin/amavisd-new-cronjob to check for use_bayes 0. For example, edit /usr/sbin/amavisd-new-cronjob and add the following to the top before the test statements:
egrep -q "^[ \t]*use_bayes[ \t]*0" /etc/spamassassin/local.cf && exit 0

Testing
First, test that the Amavisd-new SMTP is listening:
$ telnet localhost 10024
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready
^]
In the Header of messages that go through the content filter you should see:
X-Spam-Level: 
X-Virus-Scanned: Debian amavisd-new at example.com
X-Spam-Status: No, hits=-2.3 tagged_above=-1000.0 required=5.0 tests=AWL, BAYES_00
X-Spam-Level: 


Your output will vary, but the important thing is that there are X-Virus-Scanned and X-Spam-Status entries.

Troubleshooting
The best way to figure out why something is going wrong is to check the log files.
For instructions on Postfix logging see the Troubleshooting section.

Amavisd-new uses Syslog to send messages to /var/log/mail.log. The amount of detail can be increased by adding the $log_leveloption to /etc/amavis/conf.d/50-user, and setting the value from 1 to 5.
$log_level = 2;

When the Amavisd-new log output is increased Spamassassin log output is also increased.
The ClamAV log level can be increased by editing /etc/clamav/clamd.conf and setting the following option:
LogVerbose true

By default ClamAV will send log messages to /var/log/clamav/clamav.log.

PostfixGreylisting
Introduction
Greylisting is a spam-reduction technique which can be very effective. It works by delaying mail from untrusted senders. If the sending mail server is standards-compliant, it will re-send the e-mail, and the server will accept it. Most spam mailers, however, don't re-send the mail, and so the spam is blocked. Servers that re-send the mail will be added to a white list, and will not be delayed in future. This means that the first e-mail from a given sender will be delayed, but subsequent ones will not be.

Installation
Simply install the postgrey package and any dependencies. Note that it is in the universe repository. See the InstallingSoftware page for more information on installing packages.

Configuration
You need to instruct postfix to use postgrey. You can either manually edit /etc/postfix/main.cf and on parameter smtpd_recipient_restrictionsadd check_policy_service inet:127.0.0.1:10023 or run the following command to configure Postfix to use Postgrey:
sudo postconf -e 'smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination,check_policy_service inet:127.0.0.1:10023'

Note: the port number seems to vary depending on the version of the package. On 8.04LTS, it is 60000, while on jaunty it is 10023. Fortunately Postgrey prints the ports it is listening on when it starts. Have a look at /var/log/mail.info if you are unsure.

Then run the following to reload the Postfix configuration:
sudo /etc/init.d/postfix reload

You may need to modify the whitelisting of certain domains or users. To do so, use the files in /etc/postgrey/.
The default delay is 300 seconds (5 minutes), to change this value edit /etc/default/postgrey. Add --delay=N to the POSTGREY_OPTS:
POSTGREY_OPTS="--inet=127.0.0.1:60000 --delay=60"

In Use
Once Postgrey is running, entries will start to appear in /var/log/mail.log. To see them, run 
sudo grep -i greylisted /var/log/mail.log

Entries will look something like:
Sep 14 10:44:57 mailserver postfix/smtpd[17049]: NOQUEUE: reject: RCPT from mail.server.com[1.2.3.4]: 450 <someone@somedomain.com>: Recipient address rejected: Greylisted for 300 seconds (see http://isg.ee.ethz.ch/tools/postgrey/help/somedomain.com.html); from=<someone.else@anotherdomain.com> to=<someone@somedomain.com> proto=ESMTP helo=<mail.server.com>

In addition, e-mails that have been greylisted will have an X-Greylist header, eg:
X-Greylist: delayed 1201 seconds by postgrey-1.24 at mail.server.com; Fri, 14 Sep 2007 11:04:58 BST

My postfix and dovecot configure file:
$ cat /etc/postfix/main.cf

# See /usr/share/postfix/main.cf.dist for a commented, more complete version

# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/mailcert.pem
smtpd_tls_key_file=/etc/ssl/private/mail.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_security_level=may
smtpd_tls_protocols = !SSLv2, !SSLv3

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = mail.abc.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = mail.abc.com, localhost.abc.com, , localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.16.0.0/16
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

# Maildir style Mailboxes
home_mailbox = Maildir/

# Virtual mailboxes
virtual_mailbox_domains = /etc/postfix/vhosts
virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = hash:/etc/postfix/vmaps
virtual_minimum_uid = 1000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

# SASL
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noplaintext,noanonymous
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth

# Amavis antivirus + anti spam
content_filter = smtp-amavis:[127.0.0.1]:10024

# ... + Postgrey
smtpd_recipient_restrictions =
        reject_non_fqdn_sender,
        reject_non_fqdn_recipient,
        reject_unknown_sender_domain,
        reject_unknown_recipient_domain,
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_unauth_destination,
        check_policy_service inet:127.0.0.1:10023

# Prevent non-correct configurations
smtpd_helo_required = yes
smtpd_sender_restrictions =
        reject_unknown_address
        permit_sasl_authenticated,
        permit_mynetworks

local_recipient_maps = proxy:unix:passwd.byname $alias_maps
/etc/postfix/master.cf
smtp      inet  n       -       -       -       -       smtpd
submission inet n       -       -       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_wrappermode=no
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
pickup    fifo  n       -       -       60      1       pickup
        -o content_filter=
        -o receive_override_options=no_header_body_checks
cleanup   unix  n       -       -       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       -       1000?   1       tlsmgr
rewrite   unix  -       -       -       -       -       trivial-rewrite
bounce    unix  -       -       -       -       0       bounce
defer     unix  -       -       -       -       0       bounce
trace     unix  -       -       -       -       0       bounce
verify    unix  -       -       -       -       1       verify
flush     unix  n       -       -       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       -       -       -       smtp
relay     unix  -       -       -       -       -       smtp
showq     unix  n       -       -       -       -       showq
error     unix  -       -       -       -       -       error
retry     unix  -       -       -       -       -       error
discard   unix  -       -       -       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       -       -       -       lmtp
anvil     unix  -       -       -       -       1       anvil
scache    unix  -       -       -       -       1       scache
maildrop  unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix  -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
  ${nexthop} ${user}
smtp-amavis     unix    -       -       -       -       2       smtp
        -o smtp_data_done_timeout=1200
        -o smtp_send_xforward_command=yes
        -o disable_dns_lookups=yes
        -o max_use=20
127.0.0.1:10025 inet    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,no_milters

$ dovecot -n
/etc/dovecot/dovecot.conf
# 2.1.7: /etc/dovecot/dovecot.conf
# OS: Linux 3.2.0-4-amd64 x86_64 Debian 7.5 ext4
auth_mechanisms = plain cram-md5
auth_verbose = yes
base_dir = /var/run/dovecot/
info_log_path = /var/log/dovecot.info
log_path = /var/log/dovecot
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/home/vmail/%d/%n
namespace inbox {
  inbox = yes
  location =
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox Junk {
    special_use = \Junk
  }
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
  mailbox Trash {
    special_use = \Trash
  }
  prefix =
}
passdb {
  args = /etc/dovecot/passwd
  driver = passwd-file
}
plugin {
  sieve = ~/.dovecot.sieve
  sieve_dir = ~/sieve
}
protocols = " imap"
service auth {
  executable = /usr/lib/dovecot/auth
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0666
    user = postfix
  }
  user = root
}
service imap-login {
  chroot = login
  executable = /usr/lib/dovecot/imap-login
  user = dovecot
}
service imap {
  executable = /usr/lib/dovecot/imap
}
service pop3-login {
  chroot = login
  executable = /usr/lib/dovecot/pop3-login
  user = dovecot
}
service pop3 {
  executable = /usr/lib/dovecot/pop3
}
ssl = required
ssl_cert = </etc/ssl/certs/mailcert.pem
ssl_key = </etc/ssl/private/mail.key
userdb {
  args = /etc/dovecot/users
  driver = passwd-file
}
valid_chroot_dirs = /var/spool/vmail

Links
https://help.ubuntu.com/community/PostfixVirtualMailBoxClamSmtpHowto
https://help.ubuntu.com/14.04/serverguide/mail-filtering.html
https://help.ubuntu.com/community/PostfixGreylisting
https://www.digitalocean.com/community/articles/how-to-set-up-a-postfix-e-mail-server-with-dovecot
http://linuxaria.com/howto/using-opendkim-to-sign-postfix-mails-on-debian

No comments:

Post a Comment