Postfix server setup
From Smith family
| 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/mailnamecontaining
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/spamassassinto activate the Spamassassin daemon. ChangeENABLED=0to:
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_modeto 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.
- Secure Virtual Mailserver HOWTO: Postfix + OpenLDAP + Dovecot + Jamm + SASL + SquirrelMail
- Virtual Domains, Postfix, Dovecot LDA, and LDAP
- Postfix and Dovecot on Ubuntu Dapper Drake
- How To Install Postfix, Amavis, ClamAV, and Spamassassin on Debian Linux
- Single-user SpamAssassin installation
- Setting Up Email: A Postfix/Dovecot HOWTO
