Just
Can't Get Enough Sendmail
Hal Pomeranz
In the June issue of Sys Admin, I discussed the concept
of shutting down the standard Sendmail daemon on most Unix machines
(http://www.sysadminmag.com/documents/s=8228/sam0306a/0306a.htm).
To recap, this daemon is responsible for two things:
1. Listening on port 25/tcp for incoming messages from
outside of the machine.
2. Flushing the local queue of unsent messages on a periodic basis.
If the machine is not a mail server, then there is no need for
your system to be listening on port 25/tcp for incoming email (flushing
the queue of outgoing messages can be handled by running Sendmail
from cron on a periodic basis). Disabling the Sendmail daemon on
most of your machines is a huge security win, since it prevents
external attackers from using Sendmail as a mechanism for breaking
into your site.
That article resulted in an enormous amount of feedback, but there
were a small number of specific issues that came up repeatedly.
Clearly, many sites are grappling with similar circumstances, so
in this follow-up article, I will cover some of these common problems
in more detail.
Black Holes, Bounced Email, and Replies
After implementing my suggested configurations on their systems,
several people noticed that they were no longer receiving email
that was sent to root or other users by the cron daemon or
other processes running on the local machine. Other readers noted
that mail bounces and error messages, and even normal replies to
messages sent from the reconfigured machine were not making it back
to the original sender. What's happening here is "normal behavior"
for Sendmail, but obviously not desirable behavior for these sites.
Given a "bare" address like "root" or "mary", Sendmail will automatically
add the fully qualified hostname of the local machine on the right-hand
side of the address. So, mail to root will end up being sent to
root@somehost.yourdomain.com. Now, per the configuration
guidance in my previous article, this email will get forwarded to
a central relay server elsewhere on your network for final delivery.
Unfortunately, this relay server is going to attempt to send the
email right back to the machine that generated it, because the delivery
address is the machine somehost.yourdomain.com. But that
machine is no longer running a Sendmail daemon to receive this incoming
email! So, the message will sit in the outgoing mail queue on the
relay server until it times out and is expunged. It will never get
delivered.
Note that Sendmail also qualifies the sender address in the same
way. Thus, outgoing messages leave the machine as being from user@somehost.yourdomain.com.
If somebody tries to reply to this message, the response will sit
in a mail queue someplace trying to be delivered to somehost.yourdomain.com
again and ultimately never be delivered. The same thing happens
to bounced messages and other errors.
This is clearly not what we want. Most sites deal with this problem
by "hiding" their host names, or masquerading in Sendmail
lingo. In other words, bare addresses get qualified with just yourdomain.com,
rather than the full hostname of the machine where the email message
was generated. Now all messages, replies, and bounces will simply
go to user@yourdomain.com, and this traffic can easily be
handled by your central mail servers.
To fully enable masquerading, simply add a few following configuration
directives to your Sendmail macro configuration file. These directives
can be included in either the nullclient.mc or submit.mc
file discussed in the previous article:
MASQUERADE_AS(`yourdomain.com')
FEATURE('allmasquerade')
FEATURE('masquerade_envelope')
FEATURE('always_add_domain')
The MASQUERADE_AS directive specifies the domain that should
be used to qualify bare addresses instead of the fully qualified hostname
of the local machine. Usually this would be your local domain name,
but it could be any domain name you want to specify, even a domain
that is foreign to the local site. By default Sendmail masquerading
only applies to the outgoing sender address. The allmasquerade
feature tells Sendmail to use the masqueraded domain on recipient
addresses as well. Furthermore, it's necessary to use masquerade_envelope
so that the "envelope sender" address is also masqueraded, because
this is the address to which bounces and replies will be sent.
The always_add_domain feature is not strictly related to
masquerading. This directive tells Sendmail to always qualify both
bare recipient addresses (e.g., mail sent to root from the cron
daemon) as well as the outgoing envelope sender address. If MASQUERADE_AS
has been used to specify a domain name then that name will be used;
otherwise, Sendmail just uses the fully qualified hostname of the
machine. Qualifying all addresses in outgoing mail (whether you're
using masquerading or not) is generally thought to be "good practice".
The Old "Bind to Loopback" Trick
A number of the responses to the original article described a
configuration in which the site leaves the Sendmail daemon running
on their machines, but instead of configuring the daemon to listen
on port 25/tcp on all of the network interfaces on the system, it's
configured to only listen to 25/tcp on the internal software "loopback"
interface of the machine. This is the interface with IP address
127.0.0.1 on your system, which is only accessible to processes
running on the local machine. Several of the emails I received noted
that this is the default configuration for Red Hat and possibly
other Linux distributions.
This configuration certainly accomplishes our primary security
goal, because the Sendmail daemon is no longer available to an external
attacker. On the other hand, this configuration still allows a local
user -- or an attacker with access to a local machine as an unprivileged
user -- to use the local Sendmail daemon as a potential privilege
escalation path to "break root" on the system. Perhaps this is not
a huge issue in the home/hobby environment, but it could be a significant
problem for large enterprises and high-security environments.
The "bind to loopback" configuration does make things easier for
sites upgrading to Sendmail v8.12, because the default Message Submission
Process (MSP) wants to deliver outgoing email to a Mail Transfer
Agent (MTA) listening on 25/tcp at the loopback interface. Perhaps
that's why Red Hat chose this as their default configuration.
The way to configure Sendmail to listen on a specific address
and port number is with the DaemonPortOptions in the sendmail.cf
file:
# SMTP daemon options
o DaemonPortOptions=Addr=127.0.0.1,Port=smtp,Name=MTA
The configuration line shown here forces Sendmail to listen on the
smtp port (usually 25/tcp as defined in /etc/services) on the loopback
interface (address 127.0.0.1).
If you prefer, you may also set this option in the m4 macro configuration
file. If you are using Sendmail v8.11 or later, then use the following
configuration directive:
DAEMON_OPTIONS(`Addr=127.0.0.1,Port=smtp,Name=MTA')
For versions prior to v8.11, use:
define('confDAEMON_OPTIONS',`Addr=127.0.0.1,Port=smtp,Name=MTA')
In either case, the sendmail.cf file you generate should have
DaemonPortOptions set appropriately.
Local Alias Expansion
A number of people wrote to say that my configuration suggestions
had "broken" aliases they had set up on their local systems. For
example, several sites had a local alias set up for root so that
this email would go to the specific admin for that machine. Once
the system was reconfigured per my instructions, the alias was no
longer being resolved and email was going to unexpected places.
Again, this is "expected" behavior, though maybe not desirable.
Alias expansion is handled by Sendmail's "local delivery" mailer.
However, the configuration in the previous article turned the local
machine into a simple mail relay, completely bypassing any attempt
at local delivery on the system. This means that alias expansion
will never happen.
I would argue strongly that relying on specific aliases configured
on individual client systems scattered throughout your organization
is poor configuration practice. You are administratively much better
off centralizing your aliases on your primary mail servers wherever
possible.
Still, perhaps you don't control the central mail servers or have
some other good reason for needing to use the local aliases file.
In this case, you must run a mail server on the local machine to
handle "local delivery" -- at least as far as expanding an address
from the local aliases file and then delivering the email to its
final destination on some other host. This is probably another good
use for the "bind to loopback" configuration described in the previous
section, since there's usually no reason for the system to ever
accept incoming email from outside the machine.
Conclusions
Masquerading is clearly a useful addition to the concepts I covered
in my original article. Note that you will typically use masquerading
on your mail servers as well, since you would like hostnames to
be hidden on all email originating at your site.
I admit to being highly ambivalent about running the Sendmail
daemon bound to the loopback interface only. This configuration
may make sense in SOHO situation where you might not have an external
mail server that you can use as a relay, or in the case where you
need to do local alias expansion on the machine. In an enterprise-type
environment, however, I prefer to simplify things by disabling the
Sendmail daemon on all but my central mail servers.
Hal Pomeranz (hal@deer-run.com) is the founder and technical
lead for Deer Run Associates, a consulting company in the San Francisco
Bay Area. He has been a Sendmail wrangler for more than 15 years.
|