Build your own email server with Postfix
Whether you work for a small organisation or just use email to keep in touch, tailoring an open source email server to your needs is a great way to regain control over your mail. Using any of the big, free providers makes having an email account easy, but leaves you little that can be centrally monitored, configured or enforced.
If you work for a small organisation you may also have concerns about privacy or want more control over your account options. You could buy a domain name and get dedicated email hosting from a specialised provider, but even that doesn’t give you as much flexibility as it could. Thanks to free software, however, even a small group can get more bandwidth or disk space and make use of full custom filtering, privacy protection and many other features – all with the smallest possible costs and maintenance effort.
Hardware-wise, the only requirement is that the computer hosting the server has a fixed, public IP address (see Is Your DNS Clean, page 101, for more on this) and we’ve found the easiest and most reliable solution is to rent a Linux virtual private server (VPS) for a few pounds a month in a data centre. As far as software goes, the good news is that you can do everything without being a programmer. The only prerequisites are a basic familiarity with the command line and the text-based software installation tool of your distribution. You’ll also need a little time to read documentation and tweak configuration files.
This tutorial only covers the basics of MTA management. Since we can’t give you a really complete server in just four pages, you’ll get the next two best things: enough information to start handling email and an explanation of all the documentation listed in the Resources box. You’ll learn how to receive email for users in two different domains, myfamily.net and mybusiness.com, how to relay messages for authorised users and how to reject as much spam as possible before it even enters your server.
The big picture
A complete email system requires at least a few basic components. First, there’s the Mail Transport Agent (MTA). This is the server which, using the Simple Mail Transport Protocol (SMTP), relays the email you send from your desktop client to the MTAs of other users, or receives your incoming messages. It can also talk with other daemons and scripts to block spam, viruses or unwanted connections.
Any outgoing messages from external clients are accepted and relayed only after authentication has taken place. Legitimate incoming email is passed to a local delivery agent (LDA), which places it into one or more mailboxes. The single messages are then passed to webmail or desktop clients by an IMAP (Internet Mail Access Protocol) or POP3 server.
A complete email system is composed of many pieces. Here we deal with the heart of the system – the MTA server.
Less is more
The majority of tutorials on MTA servers fall into two categories: the ‘ultimate single-user email server’ or the ‘perfect Unix email platform for Fortune-500 corporations’. The first is unhelpful for small groups, but the second often involves studying, installing and maintaining a bunch of servers for a small user base. In such cases, it’s safer and more efficient to stick to plain text configuration files, and limit the number of third party components. Files are much simpler to handle than relational databases and perfectly manageable when you have less than 20 users, so we’ll follow this approach here. The MTA we’ll use is Postfix (www.postfix.org). It’s not the only FOSS server of this kind, but it’s an excellent combination of features, documentation, great online support and ease of installation. Most of the concepts are valid for other servers, too.
Main Postfix concepts
Postfix is actually a suite of programs – some interact with user processes and some run as daemons – that are controlled by a master daemon. Usage of all the daemons is specified, one logical line per daemon, in a file called master.cf. Logical lines can extend on more lines of the file. Here’s the format of the master.cf file:
# ================================================= # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (yes) (never) (100) # ==================================================== smtp inet n - n - - smtpd -v
Each line starts with the daemon’s name (service) and the way in which it communicates with Postfix (internet/Unix sockets, or FIFOs). The next two parameters dictate whether the daemon is private or not to the mail system and if it runs with privileges into a chroot (a restricted file system). Wakeup and maxproc define the wake up interval and the maximum number of processes that may execute this service simultaneously. The line ends with the specific command that invokes the daemon, with all its options displayed. Here, a dash (–) represents when the default value for that field is used.
Next is maps, where Postfix stores strings or filtering expressions used to deal with clients, senders or single messages. Maps can be indexed or linear. The first ones are binary databases built from regular text files. External relational databases could also be used as indexed maps. Linear Maps are regular text files read from top to bottom until a matching record is found! Remember that you’ll need to run the command postmap
A Postfix main.cf file consists of five basic elements, which we’ll discuss one at a time later. Otherwise, the main variables of the main.cf file are:
myhostname = mx.mybusiness.com mydomain = $myhostname myorigin = $mydomain unknown_local_recipient_reject_code = 550 mydestination = $myhostname, localhost mynetworksw = 127.0.0.0/8 # other constant trusted IP addresses here relay_domains = relayhost =
myhostname contains the full name of the VPS box. The first rule of each SMTP server is: never become a spambot by relaying messages of unknown origin or bounce notifications to the internet. This is the purpose of the last three variables. As they are shown, only messages originated on the server will be sent outside. We’ll deal with authorised users on remote computers in a moment. All the other variables define where the program accepts mail from, for which destinations and what to do with messages for unknown users.
How to get help with PostfixOne of the best features of Postfix is the postfix-users mailing list (www.postfix.org/lists.html#lists), where help requests receive quick and thorough answers. However, this only happens if you ask your question in the right way. Follow all the suggestions published at www.postfix.org/DEBUG_README.html#mail before posting, to give subscribers what they need to know in order to help you. Doing so will only take a few minutes and it’s worth it not to be left in the dark.
By default, Postfix only accepts email for canonical domains – in other words, the IP addresses and hostnames of the machine where Postfix is running and, possibly, the parent domains of those hostnames. Virtual mailboxes make it possible to set up and manage fully independent email domains and addresses without giving a Unix account to each user. This diminishes both your administrator’s load and the number of possible security holes. The part of the main.cf configuration file that defines when to accept and where to deliver email for virtual domains is:
virtual_mailbox_domains = /etc/postfix/vhosts.map virtual_mailbox_maps = hash:/etc/postfix/vmailboxes.map virtual_alias_maps = hash:/etc/postfix/valias.map virtual_mailbox_base = /var/mail/mymail_storage virtual_uid_maps = static:5000 virtual_gid_maps = static:5000
virtual_mailbox_domains points to the map of the only domains for which Postfix will accept inbound email:
# cat /etc/postfix/vhosts.map myfamily.net mybusiness.com
Even in those domains, we only accept messages for the users in the virtual_mailbox_maps – those inside the /etc/postfix/vmailbox map:
# cat /etc/postfix/vmailboxes.map firstname.lastname@example.org business/info/ email@example.com business/sales/ firstname.lastname@example.org business/boss/ email@example.com family/dad/ firstname.lastname@example.org family/mom/
Only the email addresses listed in the first column of the map are valid ones: anything else, such as email@example.com, will be rejected. The second column is the location (relative to virtual_mailbox_base) of the mailbox associated to each address: all messages for firstname.lastname@example.org must go to $virtual_mailbox_base/business/info/. A trailing slash in this field defines a Maildir mailbox, otherwise the traditional mbox format is used. As far as email filtering is concerned, MTAs stop at distinguishing one user from another: they won’t sort incoming email in different sub-folders.
Should you need, even temporarily, aliases for your virtual domains to redirect some email to other local or virtual accounts, list them in the file specified by virtual_alias_maps:
# cat /etc/postfix/valias.map email@example.com firstname.lastname@example.org email@example.com postmaster
The last three variables define the base directory of the mailboxes, the user IDs and the group IDs of their owners respectively. We’re using the simplest possible configuration – all the virtual mailboxes belong to the same user, the one with fixed UID and GID 5000. To avoid security problems, this must be a user created just for this purpose, which does nothing else in the system and cannot affect anything except the mailboxes.
With proper SMTP filtering rules, an MTA can recognise and refuse lots of spam during the initial phases of the SMTP transaction. It’s useful to set this up from the beginning because it saves a lot of bandwidth and CPU time, and obviously those both cost money. We’ll now shortly describe the tools Postfix offers to perform this particular task. The ultimate reference is, besides the mailing list, the Postfix anti-UCE cheat sheet.
You can define restrictions on acceptable messages for every stage of the SMTP transaction. They will always be applied, regardless of the order you list the corresponding Postfix variables in the main.cf file, in the order in which those phases happen: smtpd_client, smtpd_helo, smtpd_sender, smtpd_recipient and smtpd_data. Each restriction stage can contain as many checks as you wish and will perform them in the order in which you write them.
The result of each check can be REJECT, OK or DUNNO. In the first case the message is discarded, period. If a message gets an OK it bypasses all the restrictions of that stage, but must still go through all the checks of any successive stage. DUNNO, instead, means no definitive verdict, so the next check in the current restriction stage should be performed. In practice, unless you specifically tell Postfix otherwise, rejection only happens after the RCPT TO phase of the SMTP transaction.
Most Postfix administrators use this feature to list all their checks in the variable (smtpd_recipient_restrictions) that correspond to the last stage, in order to get a more predictable and self-documenting behaviour. The one exception is the rejection of data pipelining, which spammers may use for brute force attacks, but can only happen in the smtpd_data_ restrictions stage.
By all means follow suit, but remember that order is important and, since there are no more controls or restrictions after that stage, one OK is all Postfix needs to throw a message at the internet. Placing checks of this kind before permit mynetworks and reject_unauth_destination is all you need to make your server a world-class spammer!
Postfix and SMTP micro-glossary
- smtp_ Postfix has many variables whose names start with this prefix. They control some feature of the SMTP process, the one that sends mail to other MTAs.
- smtpd_ Postfix variables starting with this prefix control the Postfix smtpd daemon, the one that accepts any email for your users incoming from the internet.
- HELO/EHLO This is a phase of the SMTP transaction where the client and the server greet each other. Postfix checks with helo or hostname in their names specify what behaviour is acceptable in this phase.
- Envelope-sender and Enveloperecipient addresses In SMTP, email messages travel wrapped inside packets called envelopes, whose format includes a sender and a recipient, which may or may not be those of the real end users exchanging email. Postfix has several ways to check the reputation of envelope addresses.
- SMTP Client This is the IP address or host name of the computer that is sending you email.
Letting spam out of the door
Here’s a basic, incomplete example of the anti-spam checks Postfix can perform via smtpd restrictions:
smtpd_recipient_restrictions = reject_invalid_hostname, # 1 reject_non_fqdn_STUFF, # 2 reject_unknown_STUFF, # 3 permit_mynetworks, # 4 permit_sasl_authenticated, # 5 reject_unauth_destination, # 6 check_client_access pcre:client_checks.pcre, # 7 reject_rbl_client someblacklist.org # 8
The standard procedure is to first make sure that the calling party is real software that properly applies the SMTP protocol, not some half-baked spambot. This is done in lines one to three. The steps also block any virus which may have infested the computers of your real users. After this, you can safely relay (lines four to five) everything coming from your internal network or authenticated users.
Check six dumps any message where your server isn’t the final destination, or an authorised forwarder. The last two lines introduce two other Postfix features – conditions expressed with Perl Compatible Regular Expressions (PCRE) and online blacklists. Check seven accepts or rejects messages according to the restrictions on their client IP address, hostname or parent domains written inside the client_checks. pcre file. For example, a line like this:
...discards anything coming from IP addresses in the range 10.9.8.0-10.9.9.255. Regular expressions like these are applied, in the order in which they are listed, to all email headers, in the order in which these are written inside the message. Check 8 tells Postfix to reject clients that are in the block list published at someblacklist.org. Block lists (bl) can be of two types: DNS (DNSbl) or Right-Hand Side (RHSbl).
The first type only works for IP addresses. RHSbl verifies the host and domain names instead, or the ‘right-hand side’ of sender email addresses. Using block lists to discard incoming email outright translates as ‘I won’t accept your email because some guy I don’t know says you’re bad’, so it’s best to use them in this way as little as possible. Postfix can also perform PCRE-based checks on the body of email messages (content checks) or delegate, after a whole message has been downloaded, spam detection to specialised external programs like SpamAssassin, but lack of space forces us to refer you to the Postfix website at www.postfix.org for more details on this.
SMTP authorisation (SMTP AUTH) restricts to known and authorised email users the right to relay their outbound messages through your server. All other relay requests are rejected. Besides increasing security, with SMTP AUTH legitimate users can relay messages from everywhere in the world using always the same server, no matter which desktop client or ISP they happen to use at that moment.
Another scenario where SMTP AUTH is pretty useful is wherever there are users who can send and receive email, but only inside the local network: children on a family or school server or temporary workers inside a company are the two most common examples. When an SMTP AUTH-capable email client connects to its MTA, the latter answers by listing the available authentication methods.
The client sends authentication data (for example, a user name and password) and the server forwards them to some external authentication service. This service in turns tells the MTA if the user making the request is an authorised one or not. If it is, the server relays the client message to its destination, otherwise the connection is closed. The standard Linux tools to add SMTP AUTH to Postfix are the SASL (Simple Authentication and Security Layer) libraries or the authentication capabilities of the Dovecot IMAP server.
The second option only works with Postfix 2.3 or later, if built with Dovecot SASL support. The minimal settings to enable SASL authorisation are shown below. Don’t add them to main.cf until the testsaslauthd tool, run as the system user that ultimately will be used to run Postfix, works without problems.
broken_sasl_auth_clients = yes smtpd_sasl_auth_enable = yes smtpd_sasl_security_options = noanonymous smtpd_sasl_application_name = smtpd smtpd_sender_login_maps = hash:/etc/postfix/mymaps/ sasl_senders smtpd_sasl_local_domain =
Is your DNS clean?
The first step towards the perfect MTA is often overlooked by novice email administrators, with frustrating consequences. The reason for this is that it has nothing to do with SMTP and is relatively undocumented. Receiving email from the internet and dealing with it is a relatively easy process, because, with the one exception mentioned in the list below, it is a well localised activity: you simply install some software on your server and then configure by yourself that same software and nothing more.
Sending email, instead, means first of all making sure that all the other MTAs on the internet trust yours and are willing to accept its messages. To make this happen you must give the server a permanent and reliable public identity on the internet. This is to distinguish the server from the spambots constantly moving from one infected desktop to another.
Your server, instead, must have a fixed IP address to prove, in a way, that it’s always the same computer: this is not a problem – fixed addresses are included in almost all VPS packages available. That IP address, however, must be officially mapped as follows in the global Domain Name Service (DNS) as the authorised mail exchanger (MX) of your domain. Don’t worry though, it’s easier than it first seems.
Let’s assume that your domain is www. mybusiness.com and its MX is a VPS with the (fake) IP address 192.168.1.1. To receive your email and, above all, make the email you send not look like spam, you must give a real name to your MX, such as mx.mybusiness.com and declare in the DNS that: All email for any @mybusiness.com address must be routed to mx.mybusiness.com (MX record). mx.mybusiness.com can be found at the constant IP address 192.168.1.1. The IP address 192.168.1.1 does indeed correspond to mx.mybusiness.com (this is called reverse DNS). Email from @mybusiness.com which doesn’t come from mx.mybusiness.com is therefore very likely to be spam.
The last piece is what is called an SPF record. The Sender Policy Framework (http://spf.pobox.com) is a protocol introduced to prevent bogus computers from impersonating your MTA. Debates on the effectiveness of SPF resemble the Vi vs Emacs wars, but one thing is sure: right or wrong, email from domains without an SPF record are silently discarded from hotmail.com, so you can do without it only if you’re really sure you’ll never need to send email to anybody using their servers.
All good VPS providers help their customers to configure DNS correctly and the details vary from provider to provider, so we won’t cover them here: what is important is that you know what you must ask, to whom and why. Some guides recommend also defining in DNS a secondary MX, that is another MTA, usually on a separate network, which accepts your email when the primary MX is down for any reason.
When things are back to normal, the secondary MX hands over all the messages it collected to the primary one. Some providers make their own MTAs available for this purpose. In practice, unless the secondary MX has the same anti-spam configuration of the first, it may do more harm than good. Modern SMTP servers can wait up to three or five days before they give up a delivery. This means that no email is lost even if your primary MX goes down for some hours, but during those same hours a secondary MX with weaker anti-spam rules may let in spam you’d have never seen otherwise.
Encrypted server communications
Before authentication, set up Transport Layer Security (TLS) to encrypt communications between your users and your server. TLS on Linux is normally provided with the OpenSSL libraries. The simplest way is to generate a self-signed certificate and the associated pair of private and public encryption keys which will be used to communicate with clients. Since TLS is not specific to email, we have to point you to the Resources box below for the detail of certificate generation.
Following the procedure explained there, you’ll eventually obtain a self-signed certificate and its private key in the mycert.pem file. Copy it to /etc/postfix/myssl/ (making it readable only by root, because it’s not encrypted!) and then add to main.cf the mostly self-explanatory smtpd_tls settings:
smtpd_tls_security_level = may smtpd_tls_auth_only = yes smtpd_tls_key_file = /etc/postfix/ssl/mycert.pem smtpd_tls_cert_file = /etc/postfix/ssl/mycert.pem smtpd_tls_loglevel = 1
This will give you a level of security suitable to keep your newly customised email server safe and reliable.
First published in Linux Format magazine