Chapter 11. E-Mail services (211)

This topic has a weight of 8 points and contains the following objectives:

Objective 211.1; Using e-mail servers (4 points)

Candidates should be able to manage an e-mail server, including the configuration of e-mail aliases, e-mail quotas and virtual e-mail domains. This objective includes configuring internal e-mail relays and monitoring e-mail servers.

Objective 211.2; Managing local e-mail delivery (2 points)

Candidates should be able to implement client e-mail management software to filter, sort and monitor incoming user e-mail.

Objective 211.3 Managing remote e-mail delivery (2 points)

Candidates should be able to install and configure POP and IMAP daemons.

Using e-mail servers (211.1)

Candidates should be able to manage an e-mail server, including the configuration of e-mail aliases, e-mail quotas and virtual e-mail domains. This objective includes configuring internal e-mail relays and monitoring e-mail servers.

Key Knowledge Areas

Configuration files for postfix

Basic knowledge of the SMTP protocol

Awareness of sendmail and exim

Terms and Utilities

  • Configuration files and commands for postfix

  • /etc/aliases

  • /etc/postfix/

  • /var/spool/postfix/

  • sendmail emulation layer commands

  • mail-related logs in /var/log

Resources: PostfixTLSreadme, PostfixTFSreadme, SMTPauthHowto, RFC2487, raymii.org, PostfixGuide, the man pages for the various commands.

Basic knowledge of the SMTP protocol

Since October 2008, RFC 5321 is in use for describing the SMTP protocol.

When an SMTP client has a message to transmit, it establishes a two-way transmission channel to an SMTP server. The responsibility of the SMTP client is to transfer it to one or more SMTP servers, or to report the failure to do so.

The means by which an e-mail message is presented to an SMTP client, and how the domain name to transfer the message to is determined, is a local matter that will not be addressed here.

Detailed information can be found at: RFC5321.

For demonstration and testing purposes a plain text SMTP session can be initiated with telnet, nc or ncat:

	telnet mx1.unix.nl 25
	Connected to mx1.unix.nl (213.154.248.146).
	Escape character is '^]'.
	220 mx1.unix.nl ESMTP Exim 4.63 Thu, 12 Aug 2010 08:50:30 +0200
	ehlo snow.nl
	250-mx1.unix.nl Hello mx1.unix.nl [81.23.226.83]
	250-SIZE 52428800
	250-PIPELINING
	250-AUTH PLAIN LOGIN
	250-STARTTLS
	250 HELP
		

When using nc or ncat when performing the commands above, an additional Enter keystroke may be necessary. This is due to the differences in return characters that may exist between telnet and other, similar tools.

Using telnet <smtp servername> 25 initial contact with the SMTP server is established. In the example above mx1.unix.nl was used as the server. The server responds with the maximum message size, the pipelining, and the authentication capabilities of the server, in this case AUTH PLAIN LOGIN. The server is also able to use STARTTLS, and HELP.

  • SIZE: when the size of the message the client wishes to send exceeds the set limit, the SMTP transaction will be aborted with an ERROR code pipelining. Also, when enabled, an SMTP client can transmit a group of SMTP commands (e.g., RSET, MAIL FROM:, RCPT TO:) without waiting for a response from the server.

  • AUTH PLAIN LOGIN: the SMTP server is capable of handling a plain password/username authentication. This can be handy for mobile devices using the SMTP server while originating from different IP addresses.

  • STARTTLS: The SMTP protocol itself doesn't include any form of encryption. With STARTTLS the communciation can be encrypted using certificates. This is fully described in RFC 3207.

Since we have established the initial connection we can now proceed:

	mail from: nonexistent@snow.nl
	250 OK
	rcpt to: nonexistent@unix.nl
	250 Accepted
			

The server responds with 250 OK but when, for example, the MAIL FROM: command is followed by a misformatted or incomplete email address the server responds with 501: sender address must contain domain or a similar error. With RCPT TO: <email address> the destination of the message is given. If the recipient's address is accepted the server responds with: 250 Accepted.

Now the mailserver knows who we are and to whom we wish to transmit a message. The email client also knows what the SMTP server is capable of. We then proceed with the transmission:

	data
	354 Enter message, ending with "." on a line by itself
	mail from: Aiu <nonexistent@snow.nl>
	From: <nonexistent@snow.nl>
	To: Info <nonexistent@unix.nl>
	Subject: Demo messages
	Date: 12-02-2010 08:53:00
	MesssageID: 31231233@snow.nl
	This is a demonstration mesage.
	.
	250 OK id=1OjReS-0005kT-Jj
	quit
		

With the DATA command we proceed with the contents of the message. The server responds with: 354 Enter message, ending with "." on a line by itself.

Then the message contents is entered, starting with the message-headers. These headers are used by the email client. In this example the commands Mail From:, To:, Subject:, Date: and Message-ID: are used. Message-ID: is an unique identifier generated by the SMTP client. These headers are required as described in RFC 5322.

After the headers have been entered, a blank line indicates that the actual text of the message commences. The message ends, as the DATA command response has already indicated, with a . (without the quotes) on a line by itself. The server responds with: 250 OK id=1OjReS-0005kT-Jj. The id is a unique SMTP server identifier and can be used for troubleshooting.

Note

When fighting spam, some SMTP servers can check whether a message is RFC 5322 compliant. Regular SMTP clients are RFC 5322 compliant, but spammers often use a not so regular SMTP client and thus can send malformed messages.

Sendmail

Basic sendmail configuration steps are:

  1. Download Sendmail

  2. Set up Sendmail

  3. Configure Sendmail

  4. Build the Sendmail User Table

  5. Add your domain names to Sendmail

  6. Test your configuration file

Basic configuration of sendmail is described at: Sendmail basic installation.

An installation and operation guide for sendmail 8.12 can be found at: Sendmail installation and operation guide.

Sendmail can either be built from source or installed as sendmail binaries. With sendmail you must build a run-time configuration file. This is a file that sendmail reads when it starts up and it describes the mailers it knows about, how to parse addresses, how to rewrite the message header, and the settings of various options. Although the configuration file can be quite complex, a configuration can usually be built using an m4-based configuration language (m4 is a macro processing language). Assuming you have the standard sendmail distribution, see cf/README for further information.

The sendmail configuration files are processed by m4 to facilitate local customization; the directory cf of the sendmail distribution directory contains the source files. This directory contains several subdirectories:

cf

Both site-dependent and site-independent descriptions of hosts. These can be literal host names (e.g., ucbvax.mc) when the hosts are gateways or with more general descriptions (such as generic-solaris2.mc) as a general description of an SMTP-connected host running Solaris 2.x. File names ending with .mc (M4 Configuration) are the input descriptions; the output is in the corresponding .cf file. The general structure of these files is described below.

domain

Site-dependent subdomain descriptions. These are tied to the way your organization wants to do addressing. For example, domain/CS.Berkeley.EDU.m4 is our description for hosts in the CS.Berkeley.EDU subdomain. These are referenced using the DOMAIN m4 macro in the .mc file.

feature

Definitions of specific features that some particular host in your site might want. These are referenced using the FEATURE m4 macro. An example feature is use_cw_file that tells sendmail to read an /etc/mail/local-host-names file on startup to find the set of local names.

hack

Local hacks, referenced using the HACK m4 macro. Try to avoid these. The point of having them here is to make it clear that they smell.

m4

Site-independent m4(1) include files that have information common to all configuration files. This can be thought of as an #include directory.

mailer

Definitions of mailers, referenced using the MAILER m4 macro. The mailer types that are known in this distribution are fax, local, smtp, uucp, and usenet. For example, to include support for the UUCP-based mailers, use MAILER(uucp).

ostype

Definitions describing various operating system environments (such as the location of support files). These are referenced using the OSTYPE m4 macro.

sh

Shell files used by the m4 build process. You probably don't have to change these.

siteconfig

Local UUCP connectivity information. This directory has been replaced by the mailertable feature; any new configurations should use that feature to do UUCP (and other) routing. The use of the siteconfig directory is deprecated.

Make sure the m4 utility is available at the server. With the m4 utility the .mc macro files can be converted to a sendmail.cf file. The recommended method to configure sendmail is to edit the macro files. And not the sendmail.cf file itself.

Details of sendmail installation files can be seen at: Sendmail installation and operation guide.

Important sendmail files

/etc/mail/sendmail.cf - Main sendmail configuration file.

/etc/mail/access - The sendmail access database file can be created to accept or reject mail from selected domains, systems and users. Since /etc/mail/access is a database, after creating the text file, use makemap to create the database map.

To create a new access map:

	# makemap hash /etc/mail/access.db < /etc/mail/access
			

In the access file different actions can be defined:

OK

Accept mail even if other rules in the running ruleset would reject it, for example, if the domain name is unresolvable. "Accept" does not mean "relay", but at most acceptance for local recipients. Thus, OK allows less than RELAY.

RELAY

Accept mail addressed to the indicated domain or received from the indicated domain for relaying through your SMTP server. RELAY also serves as an implicit OK for the other checks.

REJECT

Reject the sender or recipient with a general purpose message.

DISCARD

Discard the message completely using the $#discard mailer. If it is used in check_compat, it affects only the designated recipient, not the whole message as it does in all other cases. This should only be used if really necessary.

SKIP

This can only be used for host/domain names and IP addresses/nets. It will abort the current search for this entry without accepting or rejecting it but causing the default action.

/etc/mail/local-host-names - Local host names can be defined in the local-host-names file. Add each domain that is to be considered a local account into /etc/mail/local-host-names.

/etc/mail/virtusertable - Used to map incoming email to a local account. With virtusertable, messages sent to one account can be distributed to two users. Also a "catch all" email address can be set up to route all mistyped email to one particular user to create a new virtusertable.

To generate the virtusertable database map:

	$ makemap hash /etc/mail/virtusertable < sourcefile
			

/etc/mail/genericstable - Used for outbound mail. Can be used to rewrite local usernames so they appear to have originated from a different host or domain.

/etc/mail/genericsdomain - Populate this file with the hostname --long command.

	# hostname --long > genericsdomain
			

/etc/mail/mailertable - Used to route email from remote systems.

/etc/mail/domaintable - Can be used to make a transition from an old domain name to a new one.

/etc/mail/aliases - Used to redirect mail for local recepients. Each line of /etc/aliases has the format of alias: user. Two system aliases must always be present: mailer_daemon: postmaster and postmaster: root. You can use aliases for all kind of daemons, for example use ntp: root. Now you can add a line to redirect all mail to root to a specific user of group of administrators, for example root: marc. newaliases needs to be run after any change in this file.

	# newaliases
			

If any update is made in one the of the configuration files sendmail needs to reload the files:

	# killall -HUP sendmail
			

Antirelaying

Starting with sendmail version 8.9, sendmail does not relay by default. When using an older sendmail version, make changes in the sendmail.cf or access file to make sure that sendmail does not relay. Antirelaying tips are described at: Controlling SMTP relaying tips - Sendmail.org.

Sendmail test option

Sendmail can be run in test mode. Use the -b and -t options to do this. You need to run this as root.

	# sendmail -bt
			

Sendmail and DNS

Make sure that the MX records for the MTA's are available in DNS. This can be checked with:

	$ dig MX somedomain.com
			

Manual entries in sendmail.cf

As mentioned before this is not the recommended way. Change the m4 files instead and use m4 to generate sendmail.cf.

Exim

Exim is a message transfer agent (MTA) developed at the University of Cambridge for use on Unix systems connected to the Internet. Exim can be installed in place of Sendmail, although the configuration of Exim is quite different. Also see exim.org for more detailed information.

The exim4-config_files man page contains descriptions for each of these files. Exim comes with an exim.conf template. Just edit this config file for your environment. The Exim Wiki on GitHub provides additional configuration help, FAQ, etc.

Postfix

Postfix is another, widely adopted, MTA. Postfix focusses on speed, ease of administration and security. The author of the software, Wietse Venema, was dependant on long computer calculations during his study. It was during that time that he developed a habit of creating software that would be as fault-free and fault-resistent as possible. Only if he could trust the software to run for two weeks straight without errors, there would be no necessity to sleep on the floor for those two weeks while babysitting the software. This coding habit stuck with the author for the years to come. When the Postfix program was first written, it was written with the same habit as those earlier study assignments. This habit then became a coding philosophy. By writing the code in a structured manner, only adding neccessary bits and making sure the execution flows as efficiently as possible, the resulting software became fast, easy to administrate and secure. Today, Postfix is still under active development. Many people have contributed to it, and many still do. Despite this common effort, the original author still assures that only necessary code gets added. And that it is added in a way that does not interfere with the philosophy that has been part of Postfix from the very start. This approach, plus the way that Postfix consists of various small programs working together instead of one big program, makes Postfix a very attractive alternative to other MTA solutions.

At the time of this writing Postfix version 3.1 is the latest stable version. Postfix version 3.2 is (still) considered an experimental release. Experimental Postfix releases can be recognized by their names. These will carry a date in them. An example of an experimental release is the following tarball: postfix-3.2-20161204.tar.gz. Stable Postfix versions will only show (major and minor) version numbers without the numerical date at the end. Due to the wide adoption of Postfix, most Linux distributions offering software packages also offer Postfix packages to be installed. There is a wide variety in Postfix versions being deployed with Linux distributions though. According to the Postfix website http://www.postfix.org, versions prior to Postfix 2.10 are End-Of-Support (EOS). CentOS 6.8 still ships with Postfix 2.6 though. Debian 7 did not get beyond Postfix 2.9. More recent Linux distribution versions like CentOS 7 and Debian 8 ship with Postfix >2.10, while some bleeding edge Linux distribution versions offer Postfix >3.1. There is absolutely no certainty that more recent versions of Postfix will have fewer bugs than older versions of Postfix. It is regarded as a 'best practice' to be aware of which version of Postfix you are exposing to the Internet, while at the same time keeping up to date about known Postfix vulnerabilities. There is no reason to restrict this best practice to Postfix alone though.

To address the Postfix subjects that are defined for the LPIC-2 exam, the following chapter will provide some examples. These examples asume you are using Postfix installed from packages on either a Debian-based or a Red Hat based Linux distribution. There may still be circumstances that require Postfix to be installed from source. This is beyond the scope of this chapter but LPIC-2 objective 206.1 covers the installation of software from source.

Postfix main.cf file format

The default location for the postfix configuration files is /etc/postfix. Amongst other configuration files there are two main configuration files that determine the behavior of Postfix: main.cf and master.cf. By default, the Postfix main.cf configuration file specifies a subset of all the parameters that control the operation of the Postfix mail system. Parameters not explicitly specified are left at their default values. Refer to the postconf(5) manpage for a full listing of all parameters. The main.cf file contains useful comments as well as references to other documentation sources at the top. On Debian-based systems, the /etc/postfix/main.cf file you encounter may be a stripped-down version. The /usr/share/postfix directory should then contain a main.cf.dist file which is more elaborate. The following line count operation gives an estimate about the differences between the different main.cf files on a Debian-based system:

	user@debian:/usr/share/postfix$ wc -l /etc/postfix/main.cf 
	43  /etc/postfix/main.cf
	user@debian:/usr/share/postfix$ wc -l /usr/share/postfix/main.cf*
	18  /usr/share/postfix/main.cf.debian
	665 /usr/share/postfix/main.cf.dist
	 11 /usr/share/postfix/main.cf.tls
				

The example above shows that the /usr/share/postfix/main.cf.dist file holds more than 600 lines, whereas the default /etc/postfix/main.cf file only holds 43 lines. Keeping the main.cf file clean and tidy is a good habit. But it is also a good habit to use a pager to read through the more elaborate main.cf.dist file on Debian-based systems. Red Hat based systems keep well documented configuration files within the /etc/postfix directory.

By default, postfix will only read configuration files from the /etc/postfix directory. Other configuration directories may be specified by defining the alternate_config_directories directive in /etc/postfix/main.cf. Red Hat based distributions may have /etc/postfix/dynamicmaps.cf.d and /etc/postfix/postfix-files.d directories. These directories exist to ease the life of the Postfix package creators and should be left alone unless you are really sure about what you are doing.

Note

The postfix configuration directory value /etc/postfix is hard-coded during compile time. Chapter 4.6 of the following document explains how to change this value when installing Postfix from source: Postfix Installation From Source Code

The general format of the main.cf file is as follows:

  • Each logical line is in the form parameter = value. Whitespace around the = is ignored, as is whitespace at the end of a logical line.

  • Empty lines and whitespace-only lines are ignored, as are lines whose first non-whitespace character is a #.

  • A logical line starts with non-whitespace text. A line that starts with whitespace continues a logical line.

  • A parameter value may refer to other parameters.

  • When the same parameter is defined multiple times, only the last instance is remembered.

  • Otherwise, the order of main.cf parameter definitions does not matter.

Also see Postfix Configuration Parameters as an alternative to the postconf man page. The remainder of that document is a description of all Postfix configuration parameters. Default values are shown after the parameter name in parentheses. These default values can also be looked up with the sudo /usr/sbin/postconf -d command. Beware though, since this command will produce 877 lines of output on a Postfix 3.1 instance. Because it is an administrative command and usually located within /usr/sbin, sudo or a shell with root privileges should be used to invoke this command.

One best practice to perform when using Postfix is to disable the SMTP VRFY command on a publicly accessible mail server. This VeRiFY command can be abused by an attacker to enumerate valid user accounts or email adddresses as follows:

	user@mailserver:~$ telnet mailserver 25
	Trying ::1...
	Connected to mailserver.
	Escape character is '^]'.
	220 localhost ESMTP Postfix (Linux/GNU)
	EHLO localhost
	250-localhost
	250-PIPELINING
	250-SIZE 10240000
	250-VRFY
	250-ETRN
	250-STARTTLS
	250-ENHANCEDSTATUSCODES
	250-8BITMIME
	250 DSN
	VRFY root
	252 2.0.0 root
	VRFY wodan
	550 5.1.1 <wodan>: Recipient address rejected: User unknown in local recipient table
	VRFY postfix
	252 2.0.0 postfix
				

The 200-category response codes expose valid recipients. Just like HTTP servers do, a SMTP server can respond with status codes. It is recommended to be familiar with the most common response codes. This will aid when debugging system performance or issues. It is usually not necessary to know the difference between 220 and 250 at first sight. But the difference between 2xx and 5xx status codes should be noticable and familiar. The VRFY command is enabled on Postfix by default. By enabling or adding the following line to main.cf the VRFY feature is disabled:

	disable_vrfy_command = yes
				

Let's try the VRFY root command from above again after both having disabled the VRFY command and having reloaded Postfix:

	user@mailserver:~$ telnet mailserver 25
	Trying ::1...
	Connected to localhost.
	Escape character is '^]'.
	220 localhost ESMTP Postfix (Linux/GNU)
	EHLO localhost
	250-localhost
	250-PIPELINING
	250-SIZE 10240000
	250-ETRN
	250-STARTTLS
	250-ENHANCEDSTATUSCODES
	250-8BITMIME
	250 DSN
	VRFY root
	502 5.5.1 VRFY command is disabled
	VRFY wodan
	502 5.5.1 VRFY command is disabled
	VRFY postfix
	502 5.5.1 VRFY command is disabled
				

By disabling the possibility to distinguish between valid (2xx) and invalid (5xx) email recipients, the Internet has become a safer place.

The Postfix developers recommend to change no more than 2-3 parameters at a time, and test if Postfix still works after every change. After making changes to main.cf you need to reload postfix. Depending on the Linux distribution used, this can be accomplished using one of the following commands using sudo or a shell with root privileges: postfix reload or systemctl restart postfix or even /etc/init.d/postfix reload.

Postfix master.cf file format

The Postfix mail system follows a modular approach by implementing a small number of (mostly) client commands that are invoked by users, and by a larger number of services that run in the background. Postfix services are implemented by daemon processes. These run in the background and are controlled by the master process. The master.cf configuration file defines how a client program connects to a service, and what daemon program runs when a service is requested.

The general format of the master.cf file is as follows:

  • Empty lines and whitespace-only lines are ignored, as are lines whose first non-whitespace character is a #.

  • A logical line starts with non-whitespace text. A line that starts with whitespace continues a logical line.

  • Each logical line defines a single Postfix service. Each service is identified by its name and type as described below. When multiple lines specify the same service name and type, only the last one is remembered. Otherwise, the order of master.cf service definitions does not matter.

Each logical line consists of eight fields separated by whitespace. These are described below in the order as they appear in the master.cf file. Where applicable a field of - requests that the built-in default value be used. For boolean fields specify y or n to override the default value.

Chroot option (default: Postfix >= 3.0: n, Postfix <3.0: y) - Whether or not the service runs chrooted to the mail queue directory (pathname is controlled by the queue_directory configuration variable in de main.cf file).

Postfix preparations

Before postfix can be used, it needs to know:

myorigin

The myorigin parameter specifies the domain that appears as the From: domain in outgoing email. The myorigin option is subject to other options, which define whether the From: domain gets appended or replaced by the myorigin value. Refer to the main.cf file or postconf man page for details. By default, the myorigin value is defined as $myhostname. Changing the myorigin value to the configured domain name can be done as follows:

	myorigin = $mydomain
						

The $myhostname or $mydomain are replaced by postfix with the hostname or domain of the server it is running on.

mydestination

Postfix needs to know for which domain(s) it will receive mail. The parameter mydestination is used for this. More than one domain may be specified. The domain names can be separated using whitespace or a comma. Also, a pattern can be used to point to a lookup table (hash, btree, nis, ldap or mysql).

	mydestination = $mydomain, localhost.$mydomain, hash:/etc/postfix/moredomains
				

Note

You have to include $mydomain when the server is used as a mail server for the entire domain.

relay_domains

The default configuration of postfix will try to deliver incoming mail to authorized destinations only. The relay_domains parameter controls for which domains postfix will accept and forward emails.

	relay_domains = 	(safe: never forward mail from strangers)
					

	relay_domains = $mydomain (forward mail to my domain and subdomains)
					

relayhost

By default postfix tries to deliver directly to the internet depending on the domain name of the destination address in the mail message. Using the relayhost parameter we can specify to use another SMTP server as relay:

	relayhost = 
					

This is the default, direct delivery to the internet, or using another ISP SMTP server:

	relayhost = mail.example.com
					

Logging

Postfix uses the syslog daemon for its logging. When /etc/syslog.conf is configured like in the example below, Postfix log events are written to /var/log/maillog. Error messages are, in this example, redirected to the console.

	mail.err    /dev/console
	mail.debug  /var/log/maillog
			

Tip

Using egrep '<reject|warning|error|fatal|panic>' /var/log/maillog will help you to find any problems postfix encountered. There are also third party utilities like pflogsumm that can generate statistics out of Postfix logging.

virtual domains

Generally a postfix server is the final destination for a limited number of domains. But postfix can also be configured to handle mail for additional domains which are different from, for example, the domain in which the postfix server is located. These destinations are called virtual hosts. Using the virtual_alias_domains parameter we can specify for which virtual hosts we wish to receive mail. The format of the parameters is the same as in the samples above. Separate multiple virtual hosts using a space or a comma. Also a link to a (hashed) file on disk is possible:

	virtual_alias_domains = example.com, snow.nl, unix.nl
				

or when using a hashed file (using the postmap utility):

	virtual_alias_domains = hash:/etc/postfix/virtual
				

The content of /etc/postfix/virtual can be:

	postmaster@example.com	peter
	info@snow.nl		gerda
	sales@example.com	petra
	@example.com		jim
				

In the above example peter receives the postmaster@example.com email. Gerda receives the info@snow.nl email and the sales@example.com goes to petra. The last line is a catch all rule, all email for example.com without a valid destination goes to jim.

Note

Use postmap /etc/postfix/virtual to create the hashed file and issue a postfix reload after updating the virtual file.

Sendmail emulation layer commands

Since Sendmail has been the de facto mail delivery standard on Unix like systems for years, replacement systems like Postfix have felt compelled to implement sendmail emulation layer commands in order to maintain compatibility with outside programs. That is to say that certain commands that were originally included with the sendmail package are available with alternatives like Postfix as well.

Mailq

mailq is available on most systems to check the mail queue. It is equivalent to sendmail -bp, which works with Postfix too. Its native alternative is postqueue -p.

Newaliases

newaliases is required to generate a binary aliases file with both sendmail and postfix. Both employ /etc/aliases as the default input file.

On Postfix systems man sendmail will provide more details on the Postfix to Sendmail compatibility interface.

/var/spool/mail

Specifies the default mail drop directory. By default, all mail is delivered to the /var/spool/mail/<username> file.

Postfix TLS

Chapter 8 of this book deals with HTTP over SSL/TLS. The SMTP protocol is similar to the HTTP protocol in that both protocols use plain text network commands. This comes in handy when debugging, because it enables for command execution through telnet- or netcat-like software. But it does not come in handy when transferring sensitive information across a range of systems. Due to the nature of the SMTP protocol, multiple machines may be involved to transfer an e-mail message from the soure to the final destination. And there is no way of excluding the possibility that a message has been altered during transfer. This is where encryption comes in. By using encrypted communication, at least some form of confidentiality and authenticity can be added to SMTP transactions. Just like Apache needs to be set up properly for HTTPS transactions, Postfix needs to be configured for use with TLS as well. Unlike Apache, we leave out the SSL acronym and only refer to TLS for Postfix. The following paragraphs will explain more about TLS-specific Postfix directives and about configuring Postfix for use with TLS.

At the time of this writing, TLSv1.2 is the latest TLS version. TLSv1.3 has reached DRAFT status, and it will be a matter of time before it hits the streets. There will be some noteworthy changes between TLSv1.2 and TLSv1.3. Up to TLSv1.2, a ciphersuite consisted of an authentication algorithm, an encryption algorithm, a message digest algorithm and a key exchange algorithm. These four algorithms work together and are defined by their acronyms. From TLSv1.3 onward, the ciphersuite will consist of only the encryption and message authentication algorithm.

The following paragraphs are ment to assist you in getting Postfix with TLS up and running. Encryption is an ever expanding subject, and it is recommended to take the time to read and understand the available documentation in regards to Postfix and the (proper) use of TLS. Postfix comes with extensive documentation that can be found within the /usr/share/doc/postfix directory (on Debian-based systems, you might have to install the postfix-doc package for completeness as is explained on the bottom of this page). The TLS_README document is definitely worth reading. It can be viewed using a pager like less or first expanded using a utility like zcat if the file is compressed. The TLS_README.txt document is also available on the Postix website http://www.postfix.org.

When creating a keypair for use with Apache, it may be preferred to use an encrypted private key. An encrypted key needs to be decrypted using a password before it can be used. OpenSSL will encrypt the private key during creation by default, unless specified otherwise. Postfix requires the private key used for TLS encrypted communication to be unencrypted, in other words without a password. A private key may be stripped from its password by reading, importing and exporting the key using OpenSSL. In the following example though, the -nodes option is used with OpenSSL during creation time of the key. This will prevent OpenSSL from encrypting the private key in the first place.

	sudo openssl req -nodes -x509 -newkey rsa:2048 \
	-keyout postfixkey.pem -out postfixcert.pem \
	-days 356
			

The self-signed certificate and private key created with the one-liner above can be used for postfix. Postfix demands the private key file is owned by, and only readable by root. The certificate file may be world-readable. Because the example above uses the RSA algorithm, the following directives are used to refer to these files:

	smtpd_tls_cert_file=postfixcert.pem
	smtpd_tls_key_file=postfixkey.pem
			

Note

When declaring these directives, take special care to differiantate between smtpd_tls_ directives and smtp_tls directives. smtp_tls directives are used for client authentication.

The certificate file must have the PEM-format. This is the OpenSSL standard export format, so no additional flags should be required. In the example above, the RSA algorithm is used. Instead of RSA, DSA could also be used as the encryption algorithm. When using the DSA algorithm, the key needs to be generated using the -t dsa option and the directives for the certificate file and key slightly differ from their RSA counterparts:

	smtpd_tls_dcert_file=postfixcert.pem
	smtpd_tls_dkey_file=postfixkey.pem
			

ECDSA is another valid encryption algorithm for use with Postfix. But because many mailservers still use OpenSSL 0.9.8 versions that lack proper ECDSA implementation, the use of ECDSA for Postfix with TLS is currently not recommended. Currently RSA is the recommended encryption algorithm to use with TLS for Postfix. However if you do want to use ECDSA keys, the key must be generated using the -t ecdsa option and the certificate and key files have to be specified using the following directives:

	smtpd_tls_eccert_file=postfixcert.pem
	smtpd_tls_eckey_file=postfixkey.pem
			

The OpenSSL example above creates a self-signed certificate. This is a way of getting the Postfix STARTTLS functionality working quick and dirty. But in terms of authenticity, self-signed certificates may not be validated by many public SMTP servers. Another option is to create a key and CSR, and sign the CSR using your own CA. This is shown by examples in the Apache chapter. By using certificates issued by your own CA, you could configure to have your own mailservers validate each other. Yet another option is to create a key and CSR, and have the CSR signed by a public CA. That way, public SMTP servers should be able to validate the certificate offered by your Postfix server. When going this route, it may be necessary to add additional root CA references to complete the certificate chain. Additional root CA files may be configured by using either the smtpd_tls_CAfile or smtpd_tls_CApath directives. The file directive should point to a (you guessed it) file holding the necessary root CA information. When concattenating several certificates in to one file, be aware that the files are read bottom to top. The smtpd_tls_CApath directive should point to a directory holding the necessary file(s).

Postfix uses opportunistic encryption by default. This means that a connecting system will try to create an encrypted connection at first. However, if this fails for any reason (say, due to an invalid certificate) then the system will continue to perform all SMTP commands without encryption. This behavior is determined by the value of the smtpd_tls_security_level directive. By changing the value of this directive from may to encrypt, unencrypted sessions are prevented. Be aware though! Since this directive may prevent the Postfix server from performing any SMTP transactions anymore, if TLS sessions may not be initiated for any reason.

Note

Despite all the good intentions from various public Certificate Authorities, the Certificate Authority system is kind of flawed by design. After all, ANY Certificate Authority may issue certificates for ANY service on ANY host. The chapter on DNS mentions DANE TLSA records to combat this issue. When DNSSEC has been properly configured and TLSA records are supported, it is recommended to create 301 or 311 TLSA records for a given TLS-capable Postfix server. By shifting the trust from the CA trust store with over 1300 CA root certificates to the authenticity and integrity of DNSSEC, it becomes less of a problem to depend on self-signed certificates. If multiple domains are served on the same Postfix server, it is recommended to publish a digest for every seperate domain (and therefore certificate) in DNS. The smtpd_tls_security_level value can be set to either dane or dane-only to handle TLSA records. Refer to the TLS_README file for details.

Directives and options Postfix has been written with many what if... fall-back scenarios in mind. The result is a very resilient piece of software. Being a result of good coding practices, Postfix uses a number of mechanisms to determine if circumstances are favourable or not. If system resources become scarse, the Postfix system will adapt as is deemed suitable regarding the circumstances. When configuring Postfix to use TLS encryption, there are some directives that deserve additional attention. When configured correctly, directives should compliment each others functionality. When configured inconsistently or incorrectly, directives may conflict with each others functionality. It is advised to pay additional attention to directives that are involved when configuring the allowed protocols and cipher suites. This is comparable to chapter 8 of this book regarding Apache. Modern Postfix versions exclude the use of SSLv2. Because version upgrades may change the default protocols and allowed cipher suites, there is no harm in configuring these yourself. By declaring the following directives from main.cf, these options will stay constant despite Postfix version upgrades over time.

	smtpd_tls_protocols
	smtpd_tls_mandatory_protocols
	smtpd_tls_ciphers
	smtpd_tls_mandatory_ciphers
	smtpd_tls_exclude_ciphers
			

By disabling the aNULL ciphers, use of anonymous ciphers is prevented. The use of anonymous ciphers is one of the fall-back scenarios that helps Postfix in providing availability, to the expense of accountability.

As mentioned before, the TLS functionality for Postfix can be configured using the smtpd_tls_security_level directive. According to RFC 2487, this directive should be set to the value may. This will result in Postfix announcing the availability of STARTTLS to connecting clients, without demanding its use. If you want to enforce the use of STARTTLS, the value of smtpd_tls_security_level should be set to encrypt instead. Again, be aware that this may result in degraded server compatibility towards other systems. By setting the directive value to none, the Postfix server will refrain from announcing the STARTTLS method at all. When a connecting system tries to initiate STARTTLS, the Postfix server will reply with a 502 5.5.1 Error: command not implemented message.

When enabling TLS for Postfix, various additional configuration directives become active. Most directives starting with smtpd_tls_ or smtp_tls_ are not significant for the working of Postfix unless TLS is enabled. One of these directives is the smtpd_tls_loglevel directive. This directive may be configured by setting a value from 0-4. It is not recommended to use a setting above 2, except for debugging purposes. A value of 0 will disable logging of TLS events. A value of 1 will log a summary message on TLS handshake completion. A value of 2 will also log levels during TLS negotiation. A value of 3 will log all of the above plus hex and text dumps of the TLS transaction. A value of 4 eventually will log all of the above but will not stop dumping after the TLS transaction has been processed. It will continue to dump the entire SMTP transmission after the STARTTLS command. Use with caution!

On most Linux distributions, additional documentation regarding Postfix can be found within the /usr/share/doc/postfix directory. On Debian-based systems, this requires installing the postfix-doc package. Without the addition from this package, the contents of that directory will be very shallow.

Note

Postfix 3.x makes TLS easier by incorperating the postfix-tls. While reading up, you might also want to check out what tlsmgr and tlsproxy do.

Copyright Snow B.V. The Netherlands