Postfix server setup

From Smith family

Jump to: navigation, search
Server setup
← Previous Next →
SSL certificates MDA (Dovecot)

Configuring email is the most involved part of setting up a server. My setup is organised with

  • Postfix as a mail transfer agent, using virtual users with maildir-style mailboxes, and TLS transport
  • SpamAssassin for spam filtering
  • ClamAV for virus filtering
  • Amavis to wrap SpamAssassin and ClamAV for easy use with Postfix
  • Dovecot as a mail delivery agent, providing IMAP services
  • Dovecot's Deliver local delivery agent, to do server-side filtering with Sieve
  • Squirrelmail to provide a webmail, running over a secure web connection

A lot to do, and split between several pages on this site. Postfix, TLS, and Amavis + SpamAssassin + ClamAV are here. Dovecot, Deliver, and Sieve setup are on the Dovecot server setup page. Squirrelmail setup is described in the Web server setup page, along with the HTTPS configuration.

The basic sources for setting up Postfix and Dovecot are the basic Postfix howto and the Postfix virtual user howto on the Ubuntu wiki.

Contents

Basic Postfix with virtual users

Here we get Postfix running, by sending mail to other sites, and receiving mail and putting it in virtual users' mailboxes. I use virtual users because I handle mail for many users in many domains, and want the flexibility that virtual users allows. Information about the virtual users is held in plain text files, as that's all I need for the small number of users I have.

The virtual user mailboxes are in the directory structure

/home/vmail/domain1.com/user1/
                       /user2/
           /domain2.com/user1/
                       /user2/
           /domain3.com/user1/

...and so on. The vmail user will be the one used for email transport into and out of these virtual mailboxes.

  • Install postfix
root@server:~# apt-get install postfix mailx 
  • Create the vmail user and group
 root@server:~# groupadd -g 5000 vmail
 root@server:~# useradd -m -u 5000 -g 5000 -s /bin/bash vmail
  • Update /etc/postfix/main.cf
mydomain = domain1.com   # Change this line for your domain
myorigin = $mydomain
myhostname = mail.$mydomain  # Change this for your mailserver's name

mydestination = $myhostname localhost.$mydomain localhost
relaydomains = $mydomain
relayhost =
mynetworks = 127.0.0.0/8 192.168.1.0/24
smtpd_recipient_restrictions = permit_mynetworks reject_unauth_destination

## Anti-spammer measures
# Don't talk to mail systems that don't know their own hostname.
smtpd_helo_restrictions = reject_unknown_helo_hostname

# Don't accept mail from domains that don't exist.
smtpd_sender_restrictions = reject_unknown_sender_domain

# Block clients that speak too early.
smtpd_data_restrictions = reject_unauth_pipelining

proxy_interfaces = 1.2.3.4  # My external IP
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
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

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

mailbox_size_limit = 0
recipient_delimiter = .  # Make sure you change this from a '+'
inet_interfaces = all

home_mailbox = Maildir/

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

virtual_alias_maps = hash:/etc/postfix/valiases
  • Tell Postfix about the domains it should service by creating /etc/postfix/vhosts
domain1.com
domain2.com
  • Tell Postfix about the users in those domains by creating /etc/postfix/vmaps
user1@domain1.com  domain1.com/user1/
user2@domain1.com  domain1.com/user2/
user1@domain2.com  domain2.com/user1/
user3@domain2.com  domain2.com/user3/
Then create the hash file:
root@server:~# postmap /etc/postfix/vmaps
(this command needs to be repeated every time /etc/postfix/vmaps is changed)
  • Create aliases for the users in /etc/postfix/valiases
postmaster@domain1.com   user1@domain1.com
postmaster@domain2.com   user1@domain1.com
user2@domain1.com        user2@domain2.com
Then create the hash file:
root@server:~# postmap /etc/postfix/valiases
(this command needs to be repeated every time /etc/postfix/valiases is changed)
  • Create /etc/aliases
root:   user1
clamav: root
amavis: root
postmaster:     root
and then create the database
root@server:~# newaliases
  • The virtual mailbox directory structure should be created for each user when they receive their first email.
  • Get Postfix to reload the updated configuration files
root@server:~#postfix reload
  • Test that Postfix is running properly. First, use telnet to connect to postfix
root@server:~# telnet localhost 25
Postfix will respond
Trying 127.0.0.1...
Connected to mail.server.org.
Escape character is '^]'.
220 localhost.localdomain ESMTP Postfix (Ubuntu)
then type the following
ehlo localhost
mail from: root@localhost
rcpt to: user1@domain1.com
data
Subject: My first mail on Postfix

Hi,
Are you there?
regards,
Admin
. (Type the .[dot] in a new Line and press Enter )
quit
then check that the message is delivered properly into the correct mailbox
root@server:~# ls /home/vmail/domain1/user1
  • Then test that all the mail transport is working, using the mail command line utility
root@server:~# mail user2@domain1.com
and again, check that the mail appears in the filesystem.

Adding TLS

Now to enable TLS, which encrypts communication between MTAs, preventing eavesdropping. We'll use the certificates generated previously. All that's needed is to modify the /etc/postfix/main.cf file to point to the certificates.

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/domain/certs/mail-cert.pem
smtpd_tls_key_file=/etc/ssl/domain/private/mail-key.pem
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${queue_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${queue_directory}/smtp_scache

and then reload Postfix

root@server:~# postfix reload

Check it's working by telnetting into Postfix

root@server:~# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.domain.tld ESMTP Postfix (Ubuntu)
ehlo localhost

and check that the line

250-STARTTLS

appears in the output. Use quit to end the session.

Clients should connect on port 25, using TLS security.

Allowing off-site users with SASL

As it stands, the server will only forward mail sent from the LAN. That's fine, but if you want to send mail from other devices via this SMTP server, you need to put some authentication on it. SASL is the general term for authentication on mail servers.

Assuming you have Dovecot set up with some users (up to the 'Testing Dovecot' stage, you can use Dovecot's authentication engine for authenticating users of the SMTP server.

First, extend the Dovecot configuration file /etc/dovecot/dovecot.conf with the client section below so that it accepts authentication requests from Postfix.

auth default {
  mechanisms = plain
  userdb passwd-file {
     args = /etc/dovecot/users
  }
  passdb passwd-file {
    args = /etc/dovecot/passwd
  }
  socket listen {
    master {
       path = /var/run/dovecot-auth-master
       mode = 0600
       user = vmail
       group = mail
       }

  client {
     path = /var/spool/postfix/private/auth-client
     mode = 0660
     user = postfix
     group = postfix
     }

  }
}

Next, make Postfix authenticate users. Modify /etc/postfix/main.cf to include the lines

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth-client
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated permit_mynetworks permit_mx_backup reject_unauth_destination

Restart both Dovecot and Postfix:

root@server:~# /etc/init.d/dovecot restart
root@server:~# postfix reload

Mail clients can now post messages through the SMTP server, so long as they give a valid username/password combination that's recognised by Dovecot.

Amavis + ClamAV + SpamAssassin

Both ClamAV and SpamAssassin need to be introduced into Postfix's message-handlng queue to do their things with messages. The idea is that Postfix will take the message out of it's queue and hand it over the filter program (listening on the loopback interface), who will return it the same way after doing its thing. The trouble is, Postfix can only have one such filter, so Amavis is needed to act as a wrapper around them both. Here is how to do it. For instructions, I basically followed the ones on the Ubuntu wiki.

  • Create the file /etc/mailname containing
mydomain.com
  • Install the packages:
root@server:~# apt-get install amavis-new spamassassin clamav-daemon
root@server:~# apt-get install libnet-dns-perl libmail-spf-query-perl pyzor razor
root@server:~# apt-get install arj bzip2 cabextract cpio file gzip lha nomarch pax rar unrar unzip zip

ClamAV

  • Add the ClamAV user to the Amavis group, and vice versa
root@server:~# adduser clamav amavis
root@server:~# adduser amavis clamav

The remainder of ClamAV's default settings are adequate

SpamAssassin

  • Edit /etc/default/spamassassin to activate the Spamassassin daemon. Change ENABLED=0 to:
ENABLED=1
and, to allow automatic rule updates, change CRON=1
CRON=1
then start SpamAssassin

Now start Spamassassin:

root@server:~# /etc/init.d/spamassassin start

Amavis

  • Edit /etc/amavis/conf.d/15-content_filter_mode to enable spam filtering
#
# Default SPAM checking mode
# Uncomment the two lines below to enable it back
# 

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
(don't enable virus checking yet, as ClamAV 0.90, as included in Ubuntu 7.04, doesn't seem to work very well)
  • Edit /etc/amavis/conf.d/20-debian-defaults to determine the fate of spam and virus-laden mails
$final_virus_destiny      = D_PASS;
$final_banned_destiny     = D_PASS;
$final_spam_destiny       = D_PASS;
$final_bad_header_destiny = D_PASS;
(in other words, don't discard any mail for the moment)
  • Restart Amavis
root@server:~# /etc/init.d/amavis restart

Postfix

  • Now, include Amavis in Postfix's message queue. Modify /etc/postfix/main.cf to use Amavis
# Spam and virus filtering
content_filter=smtp-amavis:[127.0.0.1]:10024
  • Modify /etc/postfix/master.cf to handle the return from Amavis
# 
# Amavis spam and virus filtering
#

# Sending to Amavis
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

# Returning from Amavis
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 
  • Restart Postfix
root@server:~# postfix reload

Block addresses that are known to spammers

The recipient_delimiter option on Postfix is rather neat. Given a recipient_delimiter of '.', messages to user.ext1@domain1.com are handled in an interesting way. If user.ext1@domain1.com is a valid user, the message is put in their mailbox. If user.ext1@domain1.com isn't a valid user, Postfix will drop everything in the username after the delimiter and retry the delivery to user@domain1.com. This means that you can create specialised-use email addresses and have them all come to the same mailbox. It also means you can create 'disposable' email addresses. That also requires some method of disposing of those addresses when the time comes.

The disposal is done by checking the headers of incoming emails and discarding or rejecting those that are to a disposable address.

  • Add the following to /etc/postfix/main.cf
# block addresses that are known to spammers
header_checks = regexp:/etc/postfix/header_checks
  • Create the file /etc/postfix/header_checks
if /^To:/
/^To:.*(user1\.ext1@domain1\.com)/
  reject Recipient address rejected: User unknown in virtual mailbox table
/^To:.*(user1\.ext2@domain1\.com)/
  reject Recipient address rejected: User unknown in virtual mailbox table
endif
  • Reload the configuration
root@server:~# postfix reload

Configure Postfix as a backup MX server for other domains

Having backup mail servers is always good, so it's only fair to offer the same service to others in exchange. This is how you do it.

  • Modify /etc/postfix/main.cf
smtpd_recipient_restrictions = permit_mynetworks permit_mx_backup reject_unauth_destination

permit_mx_backup_networks = otherdomain1.com otherdomain2.com
  • Reload the configuration
root@server:~# postfix reload

However, there is a problem with queue lifetimes. With this setup, messages held in the backup role will only be stored on this server for the standard three days. If you're acting as backup for a privately-run mail server, this may not be long enough (the other site's owner could be away on holiday, for example, and may not get back within three days). Simply increasing the queue lifetime means that undeliverable messages to third parties are not reported back for a long time, which isn't that great.

The way to fix is, apparently, is to have two Postfix instances. One instance handles the normal traffic, with a short queue time, while the other handles traffic for the backed-up mail host; the latter Postfix instance has a long queue time and so can keep the mail for a while. I've not attempted to do this yet, as the above settings work OK for me.

Open submission port (587)

Some ISPs prevent access to port 25, the normal mail transfer port. To allow clients on these networks to still connext to this server, we open port 587 for SMTP mail submission.

Modify /etc/postfix/master.cf to include:

submission inet n       -       -       -       -       smtpd
  -o smtpd_enforce_tls=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,permit_mx_backup,reject
(i.e. uncomment the lines)

You may also need to modify /etc/postfix/main.cf to include

data_directory = /var/lib/postfix
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
tls_random_exchange_name = ${data_directory}/prng_exch

And don't forget to open the port in the firewall and on the router.

See also

Here are a few pages that are useful guides or provide background and context.

Personal tools