On March 3rd, 2003, Internet Security Systems, in cooperation with the Department of Homeland Security, issued a warning regarding a hole found in Sendmail. Sendmail, of course, is responsible for handling over half of the world's e-mail traffic. The warning, echoed by CERT, warned system admins that any version lower than 8.12.8 was vulnerable to a serious root exploit. I heard the warning loud and clear, so I wasted little time upgrading each system on our network.
Sendmail has a long history of security holes, most of which have been thoroughly documented on security sites around the world. Why do people continue to run Sendmail? The majority of my systems used to run Sendmail compared to the minority that ran other MTAs such as Postfix or Qmail. Sendmail isn't easy to configure. It lacks a user-friendly front end. It certainly doesn't come ready to use or with easy-to-understand documentation. Is Sendmail still used because it ships as the default mailer with almost every flavor of Unix? Whatever the reason, many would agree its time to adopt a more user friendly mail transport agent.
Postfix was developed as a replacement for Sendmail and is known to compile on almost every flavor of Unix including Mac O/S X. Wietse Venema, program founder and security specialist, several years developing the application while working as a researcher at IBM's T.J. Research lab. Postfix is the free version of IBM's commercial Mailer, Secure Mailer. It was released in 1998 and dubbed IBM's Christmas present to the Internet. Postfix became especially popular during the Linux revolution by enthusiasts who were looking for open source code that would compile on a free operating system.
Postfix attempts to be fast, easy to administer, and secure, while at the same time being compatible enough with Sendmail so as not to upset existing users. Thus, the outside has a Sendmailish flavor, but the inside is completely different. With this in mind, let's take a closer look at Postfix.
Postfix has a unique internal structure that supports SASLv1/v2, SSL/TLS, DB3, MySQL and LDAP. The application runs in a chrooted environment, and upon execution, chroots (jails) the mail queue and daemons. First time users will benefit from a single, easy to understand configuration file written in plain English, unlike the archaic, cryptic Sendmail counterpart. Most defaults are set to sensible values, allowing you to configure only two or three parameters prior to initial use. Advanced users will benefit from hundreds of additional options including a wide range of add-on software allowing enhanced versatility.
Every mail server, or Mail eXchanger, must have a DNS entry for each domain for which it receives mail. These are called Exchange records or MX entries. They are commonly listed as primary and secondary, each one instructing the domain system to send SMTP traffic destined for some domain to the primary exchanger. In the event delivery to the primary exchanger fails, a secondary exchanger will queue any remaining messages. For more detailed information regarding MX records, please see the DNS manual.
The Postfix receiving cycle consists of seven steps. An in-depth explanation is available through the Postfix website.
Before we begin, we need to remember that Postfix uses several Sendmail-specific filenames such as
newaliases. These are overwritten during installation, so we need
to back these files up prior to installing Postfix. Some operating systems, in
particular the *BSDs, come packaged with MailWrappers that allow you to
wrap a number of mail packages into one, thus providing the luxury of editing
mailer.conf with site-specific paths to existing binaries. For
more information see
% mv /usr/sbin/sendmail /usr/sbin/sendmail.old % mv /usr/bin/mailq /usr/bin/mailq.old % mv /usr/bin/newaliases /usr/bin/newaliases.old
Throughout this article, I'll use examples from the FreeBSD Postfix port installation. Alternately, if you are compiling from source, download Postfix from any number of global mirrors, then uncompress the file to
Next, if Sendmail is running, stop it. Also, remove any Sendmail specific
security or sanity checks from your cron. Save your current Sendmail
configuration files, such as
access for later reference. The FreeBSD port installs the
sendmail binary under
/usr/local/sbin/, where it used
to exist under
/usr/sbin/. To conform with existing scripts, I
suggest making a symlink from
/usr/sbin/sendmail. Most source installations install under
If you are installing via the FreeBSD port,
make will spawn an
ncurses-based GUI where you may add compilation options such as support for
SSL/TLS, SASL, DB3, MySQL, and LDAP. This is especially advantageous for those
planning to include add-ons such as phpMailAdmin or other apps requiring
LDAP/MySQL compiled support. Users requiring only basic functions may bypass
this option and continue with make.
install target is an interactive script that adds other
options such as postfix users, groups, and file locations. The defaults should
suffice for most users.
BSD users should keep in mind that
make world will reinstall
Sendmail binaries, over-writing the Postfix installation. Remember to keep a
current copy of your Postfix binaries and config files in the event you plan to
Configuration is accomplished through a single, easy to understand
configuration file. The default configuration path is usually
/etc/postfix, while the default FreeBSD port installs under
/usr/local/etc/postfix. By editing
main.cf, a few
options need be changed to suit your system prior to running the application:
myhostname = bar.foo.com
mydomain = foo.com
bar.foo.com) or the path of the primary domain (
myorigin = $myhostname # or myorigin = $mydomain
These are later referenced in the sample configuration file.
By default, Postfix looks to
/etc for the
aliases.db file. Depending on where your
aliases.db files are located, you should make a symlink to
/etc. The location of this file may be configured under
main.cf, with the
alias_maps directive. To initiate
your aliases database, run the standard Sendmail command
newaliases. The aliases file uses the standard Sendmail format.
Note that attempting to run Postfix without
aliases.db in the
path will cause an error.
To start Postfix, run:
% postfix start
To stop Postfix, run:
% postfix stop
Anytime you make changes to
main.cf, restart Postfix by
% postfix reload
Next, let's test our server by issuing a telnet connection on port 25, then send some common mail commands (like those sent by an SMTP client) to the server. After each command is issued, the mail server should respond with an acknowledgment.
command: telnet machine1.domain.com 25 response: Trying 184.108.40.206... Connected to machine1.domain.com Escape character is '^]'. 220 machine1.domain.tld ESMTP Postfix (Connected to machine1.domain.tld identified by ESMTP postfix) command: HELO test.com response: 250 remotehost.domain.com
Machine1.domain.tld responds by saying hello back to
remotehost.domain.tld by doing a reverse dns lookup. This helps
prevent host spoofing.
command: MAIL FROM: email@example.com response: ok
The server responds that the email address firstname.lastname@example.org is acceptable and issues an ok.
command: RCPT TO: glenn@localhost response: 250 ok
The server recognizes glenn as a valid system user and issues another ok reply. If the recipient does not exist, the server would issue a user unknown response.
command: DATA: Type in the data of the mail message you wish to send to glenn. End this message with a . after a carriage return on a line by itself command: . response: 250 Ok: queued as EAAD3167
The mail message has been queued for delivery to glenn with the ID: EAAD3167.
command: QUIT (Issue the quit command to end the connection)
Use a simple mail reader, such as
pine, to check the user's
mail on the local system to ensure delivery. In the event mail is not
received, check that
aliases.db resides under
and that a user exists under
/var/mail. Some archaic systems
require the mail drop to be created manually. This is accomplished by doing
% touch /var/mail/user; chown user:postfix /var/mail/user
syslogd logs mail messages to a specific logfile such as
/var/log/maillog, you should tail this file to ensure proper
delivery or to check for errors in configuration.
Next, try sending a test message to a local user on the system from another host on your network, for example, email@example.com. Your message should arrive without error.
If you're running Postfix in a production environment, you'll need to add
some additional configurations such as a Primary MX, Virtual Domains, Host
Relays and a Secondary MX. Some of these options require building a hash style
database. Postfix uses a utility called
postmap, a replacement
makemap with a similar syntax.
If your machine accepts mail for domains outside your network, setting the
primary MX entries correctly is a critical component in the Postfix
configuration. This is accomplished by editing
appending to the end of the file:
relay_domains = $mydestination, /usr/local/etc/postfix/relay-domains
Edit the file
relay-domains according to this format:
another_domain.com second_domain.com third_domain.com
In the event your server is used as a secondary exchanger as defined in the
DNS record (MX), you may define allowable domains by editing
main.cf and adding the line:
relay_domains = $mydestination the.backed-up.domain.com
You may optionally choose to allow the world to MX through your host. Edit
smtpd.cf, then add the line:
smtpd_recipient_restrictions = permit_mx_backup
Remember to reload Postfix after changing
Virtual Hosting is the ability to receive and redirect mail for a user of another domain, not our own, to a local user or a user on a remote system. For example, firstname.lastname@example.org might redirect to joe@localhost, or email@example.com may also redirect to joe@another_domain.com.
Creating a Virtual Domain is accomplished by editing
and appending to the end of the file:
virtual_alias_maps = hash:/usr/local/etc/postfix/virtual
Edit the file
virtual according to this format, the same as of
virtusertable under Sendmail:
firstname.lastname@example.org user@localhost # or email@example.com
Then, hash it to a database.
% postmap /usr/local/etc/postfix/virtual < /usr/local/etc/postfix/virtual
If you allow your host to act as an SMTP relay, you need to configure the
relay options under
main.cf. Under the section
Control, look to
mynetworks for a list of variable options.
In this example, we allow relaying based on two network subnets. This means
that hosts within the class C ranges of 220.127.116.11 and localhost 127 can
mynetworks = 18.104.22.168/24, 127.0.0.0/8
If you run into problems or require additional configuration sets, I suggest consulting the Postfix FAQ.
# Global Postfix configuration file. This file lists only a subset # of all 250+ parameters. See the sample-xxx.cf files for a full list. # NOTE - CHANGE NO MORE THAN 2-3 PARAMETERS AT A TIME, AND TEST IF # POSTFIX STILL WORKS AFTER EVERY CHANGE. queue_directory = /var/spool/postfix command_directory = /usr/local/sbin daemon_directory = /usr/local/libexec/postfix mail_owner = postfix myhostname = bar.foo.com mydomain = foo.com myorigin = $bar.foo.com unknown_local_recipient_reject_code = 450 # Here is the MX (mx) stuff relay_domains = $mydestination, /usr/local/etc/postfix/relay-domains # The aliases alias_maps = hash:/usr/local/etc/postfix/aliases alias_database = hash:/usr/local/etc/postfix/aliases debug_peer_level = 2 debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin \ xxgdb $daemon_directory/$process_name $process_id & sleep 5 sendmail_path = /usr/local/sbin/sendmail newaliases_path = /usr/local/bin/newaliases mailq_path = /usr/local/bin/mailq setgid_group = maildrop manpage_directory = /usr/local/man sample_directory = /usr/local/etc/postfix/samples readme_directory = no # Here is the Virtual User stuff virtual_alias_maps = hash:/usr/local/etc/postfix/virtual # Allow local and remote network to relay through this machine mynetworks = 22.214.171.124/24, 127.0.0.0/8
Postfix uses the same start parameters as Sendmail, so most existing
start-scripts should suffice. In the unlikely event your sendmail-ish scripts
fail or hang, try starting Postfix from
rc.local or, under BSD,
/usr/local/etc/rc.d/postfix.sh. The syntax is:
% /usr/local/sbin/postfix start &
Postfix is a robust, secure MTA. I was impressed with the ease of installation, well-defined documentation, and its ability to receive and relay mail without complex configuration. I've compiled Postfix under Solaris, various flavors of BSD, Slackware, and Red Hat. A wide range of add-on software including phpMailAdmin helps add an additional layer of functionality. Today I see Postfix as a major contender in the race for secure E-mail communications.
Glenn Graham has been working with telecommunications since 1977.
Return to the Linux DevCenter.
Copyright © 2009 O'Reilly Media, Inc.