A mail relay is a system that resends mail that it receives. When mail that should be delivered by some other host arrives at the mail relay host, the system decides whether it should relay the mail. If relaying is allowed, the relay host sends the mail on to the destination address. If relaying is denied, a “Relaying denied” error message is returned to the sender. This chapter contains recipes that control when relaying is allowed or denied and recipes to configure a system to make use of a mail relay.
Relaying is different from forwarding. Mail that is forwarded arrives at the system addressed to the local host; it is forwarded only if the host is instructed to do so by the aliases database or the .forward file. Mail that is relayed arrives at the system addressed to some other host; it is only relayed if sendmail is configured to allow relaying.
In the same way that sendmail must be configured to act as a mail relay, a system must be configured to use a mail relay. Any system running sendmail can directly deliver its own mail; sendmail does not depend on relays by default. However, there are a variety of different sendmail configurations that use relay servers:
A system can be configured to send all of its mail to a relay. This type of configuration is called a null client , not because the sendmail.cf file is empty, but because the system depends on an external host for all email service.
A system can be configured to use a relay for mail that
is normally delivered by the local
mailer, while
delivering all other mail itself. Thus, mail from one user to
another, even when those users are both logged into the same client,
is sent through a relay server.
sendmail can be configured to send all mail bound for
external hosts through a mail relay. Only mail delivered by the
local
mailer is not sent to the relay.
sendmail can be configured to send “non-SMTP” mail to a mail relay host for delivery. Pseudodomains are internal tags used by sendmail to identify mail that is not standard SMTP mail. Special configuration commands exist for sending UUCP, BITNET, DECnet, and FAX mail to a mail relay host when that mail is identified by a pseudodomain.
Mail is sent to the mail relay host via the SMTP relay
mailer. The configuration of the relay
mailer can
be changed with the m4 macros
RELAY_MAILER_ARGS
,
RELAY_MAILER_FLAGS
,
RELAY_MAILER_QGRP
, and
RELAY_MAILER_MAXMSG
. sendmail can even be
configured to use a different mailer for relaying by specifying a
different mailer name with the confRELAY_MAILER
define. However, changing the mailer name or fiddling with the
relay
mailer configuration is generally a bad idea
because it creates an unnecessarily complex configuration that must
be maintained. It is better to configure a mail relay host that is
capable of handling standard SMTP mail than it is to create a custom
mailer for every system that uses the relay host for the simple
reason that there are fewer systems to maintain.
By default, sendmail does not relay mail—thus, a default sendmail system does not consider itself a mail relay. There is a good reason for this: relaying opens a system to the possibility of being abused by spammers. Spammers love to find a system that they can relay through in order to hide the true source of the spam mail. Everything you do to create a relay weakens this security. Therefore, care must be taken to use only those configuration tools that you really need to get the job done.
Several features are available that turn a sendmail system into a mail relay:
This feature tells sendmail to relay mail from any source to any destination. It should not be used on a system that is accessible from the Internet because it creates an open relay that will quickly be found and exploited by spammers.
This causes sendmail to relay any mail in which the envelope sender address contains the name of a host in the local domain. Because the envelope sender address in mail is easily forged, spammers can exploit a relay that uses this feature. For this reason, the relay_local_from feature should be avoided.
This feature tells sendmail to relay mail if the envelope sender
address of that mail contains the name of a host in any domain listed
in the relay-domains file or listed as
RELAY
in the access database.
Because the envelope sender address in mail is easily forged,
spammers can exploit a relay that uses this feature if they can
figure out the entries in the relay-domains file
or the access database. For this reason, the
relay_mail_from feature should be avoided.
This feature enables relaying for any host or domain that lists the local host as its mail exchanger. The disadvantage of this feature is that you lose direct control over which systems can use your system as a relay, and you place that control into the hands of others—the domain administrators. Domain administrators can simply place MX records in their domains to enable relaying through your system.
When this feature is specified, sendmail relays mail for any host in
a domain identified in class $=m
. Class
$=m
contains the name of the local
host’s domain, as determined by sendmail during
startup. Thus, this feature enables relaying for hosts in the local
domain.
By default, values in the relay-domains file or the access database are interpreted as domain names, and relaying is granted to any of the hosts in those domains. This feature changes that. When relay_hosts_only is specified, the values in the relay-domains file and in the access database are interpreted as hostnames, and mail is only relayed for the specific hosts listed in those files.
Other than the relay_hosts_only feature, which works with the relay-domains file and the access database, the features listed above tend to reduce the amount of control the sendmail administrator has over relaying. Generally, a better way to enable relaying is by using the relay-domains file. Using the relay-domains file requires no special m4 configuration because sendmail reads this file by default. To use it, all you need to do is create a text file named relay-domains that contains a list of the domains for which relaying is allowed.
Entries in the relay-domains file enable relaying to or from the domains listed in the file. To have more control over the condition in which relaying is approved, use the access database. The access database is not designed specifically for relaying—it has broader security applications. However, it can be used to control relaying as demonstrated in Recipe 3.10.
For maximum security, use SMTP AUTH or STARTTLS to authenticate the hosts granted relay privileges. Chapter 7 and Chapter 8 cover these security protocols.
Because spammers may abuse a mail relay, special care should be taken to thoroughly test the relay configuration. If your server fails any of the tests, adjust the configuration to close the security hole. No tests are infallible, but they do provide clear indications of possible configuration problems.
You have been asked to create a sendmail configuration that sends all mail through a relay. The identity of the local host is to be hidden so that all mail appears to come from the mail relay host.
Create a minimal sendmail configuration containing only an
OSTYPE
statement to specify the correct operating
system and a FEATURE
command to select the
nullclient feature:
#cd /usr/local/src/sendmail-8.12.9/cf/cf
#cat > sendmail.mc
VERSIONID(`Recipe 3.1 nullclient master configuration file.') dnl Select the correct operating system OSTYPE(`linux') dnl Select the nullclient feature and specify the relay server FEATURE(`nullclient', `smtp.wrotethebook.com')Ctrl-D
Build the new sendmail.cf file, copy it to the correct path, and restart sendmail. An example of building and installing a sendmail.cf file is shown in the last step of Recipe 1.8.
Any Unix system running sendmail, even when the system is used as a single-user workstation, is fully capable of handling its own mail. Some workstations configure sendmail to handle both inbound and outbound mail—just like a mail server. Many Unix workstations, even those that depend on a mail server to collect their inbound mail, have a full sendmail configuration for handling outbound mail. Yet, it is also possible to create a very simple sendmail configuration on a workstation that relies on a mail server for both inbound and outbound mail service. When the nullclient feature is used, a system sends all of its mail through a mail relay host.
Most of the recipes in this book show configuration lines that are
added to a pre-existing sendmail configuration. This recipe does not;
the Solution section shows the complete configuration file. The
nullclient configuration contains only two
essential lines: the
OSTYPE
macro that identifies the
client’s operating system and the
FEATURE
macro that configures the
nullclient feature. The
nullclient feature has two fields. The first is
the feature name: nullclient. The second is the
name of the relay host to which outbound mail is sent. The format of
the second field is
mailer
:host
.,
where mailer
is the name of a mailer
defined in the configuration and host
is
the domain name of the relay host. The basic
nullclient configuration contains only the
local
and prog
mailers, and the
five SMTP mailers: smtp
, esmtp
,
smtp8
, dsmtp
, and
relay
. mailer
defaults
to relay
if no other mailer name is provided. This
default is correct and should only be changed if you add other
mailers to the configuration and have a specific reason for using
another mailer. We allow mailer
to default
to relay
in the sample configuration, and we
recommend that you do the same.
The server value is assigned to the $S
,
$H
, and $M
macros in the
sendmail.cf configuration file. These macros
are, respectively, the smart host, mail hub, and masquerade macros.
sendmail:
Sends all outbound mail to the server identified by the
$S
macro; sends all mail that would normally be
delivered by the local
mailer to the server
identified by the $H
macro.
Changes the hostname in the sender address of outbound mail to the
hostname defined in macro $M
.
A few sendmail
-bv
tests show
the impact of the nullclient
configuration on mail delivery:
#sendmail -bv tyler@example.com
tyler@example.com... deliverable: mailer relay, host smtp.wrotethebook.com, user tyler@example.com #sendmail -bv sara@crab
sara@crab... deliverable: mailer relay, host smtp.wrotethebook.com, user sara@crab.wrotethebook.com #sendmail -bv craig
craig... deliverable: mailer relay, host smtp.wrotethebook.com, user craig@smtp.wrotethebook.com
The host value displayed by the first test shows that mail addressed
to a user on an external host is sent through the mail relay host. In
the generic configuration, mail addressed to an external system is
sent directly to that system or to its MX server, using the
esmtp
mailer. On the
nullclient system, the mail is sent to the relay
host using the relay
mailer. In this example, the
client then relies on smtp.wrotethebook.com to
relay the mail to tyler@example.com.
The second test is very similar to the first. In the second test, mail is addressed to another host within the local wrotethebook.com domain. Again, the mail is sent to the relay server instead of directly to the external host.
Probably the most interesting is the third test, which shows how mail
is delivered to the local username craig.
Normally, mail addressed in this manner would be handled by the
local
mailer and delivered directly to the local
user’s mailbox. Under the
nullclient configuration, this mail is sent to
the relay host for delivery, even though the mail is addressed to a
user who has an account directly on the local system.
Note that the -bv
test is often the best way to
view delivery information. In this particular case, a test using
-bt
could have given a confusing result. For
example, assume you decided to run sendmail
-bt
and use the /parse
command
to examine the mail delivery triple. You would see something like the
following:
#cat > special-test
/parse tyler@science.foo.edu /parse sara@crab /parse craigCTRL-D
#sendmail -bt < special-test | grep '^mailer'
mailer relay, host smtp.wrotethebook.com, user tyler@science.foo.edu mailer relay, host smtp.wrotethebook.com, user sara@crab.wrotethebook.com mailer local, user craig
The first two results obtained by /parse
provide
the correct information. The third result, however, is potentially
misleading. You might look at this and think that, even with the
nullclient configuration in place, mail
addressed to local users is handled by the local
mailer instead of being forwarded to the relay server. The problem
comes from assuming that parsing the delivery address is the end of
the story. In this case, it isn’t. Because the
mailer is the local
mailer, the delivery address
is processed through the aliases database. When
sendmail finishes aliasing, it processes the
localaddr
ruleset (ruleset 5) if the
local
mailer has the F=5
flag
set, which it does by default. It is the localaddr
ruleset that then decides this mail needs to be sent to the mail
relay, as the following -bt
test shows:
#sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >localaddr craig
localaddr input: craig MailerToTriple input: < server . wrotethebook . com > craig < @ smtp . wrotethebook . com > MailerToTriple returns: $# relay $@ smtp . wrotethebook . com $: craig < @ smtp . wrotethebook . com > localaddr returns: $# relay $@ smtp . wrotethebook . com $: craig < @ smtp . wrotethebook . com > >/quit
It can be confusing trying to remember when to call each ruleset. In
general, it is easier to use -bv
when all you want
is information about the mail delivery.
In addition to sending all mail through the relay server, the
nullclient configuration replaces the hostname
of the client with the name of the server in the email sender
address. A sendmail
-bt
test
demonstrates this function of the nullclient
configuration:
#sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >/tryflags HS
>/try relay kathy@giant.wrotethebook.com
Trying header sender address kathy@giant.wrotethebook.com for mailer relay canonify input: kathy @ giant . wrotethebook . com Canonify2 input: kathy < @ giant . wrotethebook . com > Canonify2 returns: kathy < @ giant . wrotethebook . com . > canonify returns: kathy < @ giant . wrotethebook . com . > 1 input: kathy < @ giant . wrotethebook . com . > 1 returns: kathy < @ giant . wrotethebook . com . > HdrFromSMTP input: kathy < @ giant . wrotethebook . com . > PseudoToReal input: kathy < @ giant . wrotethebook . com . > PseudoToReal returns: kathy < @ giant . wrotethebook . com . > MasqSMTP input: kathy < @ giant . wrotethebook . com . > MasqSMTP returns: kathy < @ giant . wrotethebook . com . > MasqHdr input: kathy < @ giant . wrotethebook . com . > MasqHdr returns: kathy < @ smtp . wrotethebook . com . > HdrFromSMTP returns: kathy < @ smtp . wrotethebook . com . > final input: kathy < @ smtp . wrotethebook . com . > final returns: kathy @ smtp . wrotethebook . com Rcode = 0, addr = kathy@smtp.wrotethebook.com >/quit
The /tryflags
command specifies the particular
address we wish to process. In this case, we ask to see the
processing of the header/sender (HS
)
address.[1] The
/try
command specifies the mailer for which the
address should be processed (relay
) and the email
address that is to be processed
(kathy@giant.wrotethebook.com). The result shows
that the sender’s hostname
(giant.wrotethebook.com) is replaced by the mail
relay host’s name
(smtp.wrotethebook.com). This example uses the
sender’s fully qualified domain name, but it could
have used any hostname alias found in class $=w
.
Any of them would be replaced by
smtp.wrotethebook.com in this test.
The two line configuration shown in this recipe sends all mail that originates on the local host to the relay for processing. It also masquerades that mail so that it appears to originate from the mail relay host. The nullclient configuration is intended for systems that depend on the mail server for all email needs. The classic examples of systems that might use such a configuration are diskless clients that depend completely on a server. But the benefits of the nullclient configuration have far wider utility. Centralizing mail services can simplify queue management, mail policy control, security, and logging. Many sites use the nullclient configuration on desktop workstations.
Replacing the hostname in the sender address is called masquerading, and it is covered extensively in Chapter 4. The third edition of sendmail covers the nullclient configuration in 4.8.33. Recipe 3.2, Recipe 3.3, and Recipe 3.4 all provide configurations that use a mail relay host; evaluate those recipes if the nullclient feature does not match your needs.
You have been asked to configure sendmail to send all mail bound for external systems through a mail relay host.
Create a sendmail configuration that uses the
SMART_HOST
define to identify the mail relay host:
dnl Define a relay for all outbound mail define(`SMART_HOST', `smtp.wrotethebook.com')
Build the new sendmail.cf file, copy it to the correct path, and restart sendmail, as described in Recipe 1.8.
The SMART_HOST
define sets a value for the
sendmail.cf
$S
macro. The
$S
macro identifies the smart
host. sendmail uses the smart host to relay mail to
external systems. A few -bv
tests show the impact
of the SMART_HOST
define:
#sendmail -bv sara@crab
sara@crab... deliverable: mailer relay, host smtp.wrotethebook.com, user sara@crab. wrotethebook.com #sendmail -bv tyler@example.com
tyler@example.com... deliverable: mailer relay, host smtp.wrotethebook.com, user tyler@example.com #sendmail -bv craig
craig... deliverable: mailer local, user craig
The first two tests show that all mail addressed to an external host,
whether the host is part of the local
wrotethebook.com domain or part of some other
domain, is sent to the smart host for delivery to the external host.
The third test shows that all mail that can be delivered by the
local
mailer is kept on the local system and
delivered by the local
mailer.
This configuration differs from the nullclient configuration in two ways:
Local mail remains on the local host.
Mail that originates from the local host has the local host’s hostname in the sender address.
This creates a sendmail configuration that can handle its own local mail but must depend on a mail relay host for access to external systems. The concept of a smart host originally developed because many organizations had limited Internet connectivity. In those days, mail was relayed through the smart host because the smart host was the only host that could deliver the mail. These conditions still exist in some locations, but a more common reason that this configuration is popular is because network managers want to route all outbound mail through a single server for increased security, simplified queue management, and centralized logging.
Section 4.3.3.6 in the sendmail book discusses
the SMART_HOST
define.
You have been asked to create a sendmail configuration that sends all local mail to a mail hub, while directly delivering mail addressed to external systems.
Create a sendmail configuration containing the
MAIL_HUB
define
to identify the mail relay host for local mail. Use the
LOCAL_USER
command to
exempt the root user’s mail
from relaying. Here are sample commands:
dnl Define a relay server for local mail define(`MAIL_HUB', `smtp.wrotethebook.com') dnl Users whose mail is not passed to the mail hub LOCAL_USER(root)
Rebuild and reinstall sendmail.cf, and then restart sendmail. Examples of these steps can be found in Recipe Recipe 1.8.
The MAIL_HUB
define sets a value for the
sendmail.cf
$H
macro. The
$H
macro identifies a mail hub that sendmail uses
to deliver local mail. A few -bv
tests show the
impact of the MAIL_HUB
define:
#sendmail -bv tyler@example.com
tyler@example.com... deliverable: mailer esmtp, host example.com, user tyler@example.com #sendmail -bv sara@crab
sara@crab... deliverable: mailer esmtp, host crab.wrotethebook.com., user sara@crab. wrotethebook.com #sendmail -bv craig
craig... deliverable: mailer relay, host smtp.wrotethebook.com, user craig@smtp. wrotethebook.com
The tests demonstrate that sendmail uses the
esmtp
mailer to directly deliver mail bound
for systems in external domains and external systems in the local
domain. Mail that is normally delivered by the
local
mailer, however, is sent to the mail hub
(smtp.wrotethebook.com) via the
relay
mailer.
Notice the user address field of the mail delivery triple displayed by the third test. The address craig has been rewritten to craig@smtp.wrotethebook.com. The address is rewritten even if the delivery address contains the fully qualified name of the local host, for example:
# sendmail -bv craig@jamis.wrotethebook.com
craig@jamis.wrotethebook.com... deliverable: mailer relay, host smtp.wrotethebook.
com, user craig@smtp.wrotethebook.com
Thus, all mail that would be delivered by the
local
mailer, even mail arriving from an external
source, is forwarded to the mail hub. When configuring the mail hub,
be careful not to forward mail back to a system that relays mail to
the hub as this will cause a mail loop.
In this example, the mail hub must be configured with either a craig account or an alias for craig. Often, the mail hub maintains a central mail spool directory and holds the mail for all of its clients. The clients themselves do not have local mail spool directories. They either mount the server’s spool directory via NFS, download the mail to a mail reader using POP or IMAP, or read the mail directly on the server.
Because the mail hub has an account or alias for every user on every client, it is important that the usernames on the clients are unique. If Craig Hunt has an account named craig on crab, and Craig Rider has an account named craig on jamis, and both systems use smtp.wrotethebook.com as a mail hub, then both systems will send mail to the hub using the same delivery address craig@smtp.wrotethebook.com, even though the mail is intended for two different users. Using a mail hub requires coordination among all of the clients.
One username that is obviously duplicated on all clients is
root. Use the LOCAL_USER
macro to ensure that sendmail does not relay mail to the mail hub
when the mail is addressed to root. The
LOCAL_USER
macro adds users to
sendmail.cf class
$=L
. Class
$=L
is a list of local users whose mail is not
relayed to the mail hub.
The following test shows that without the
LOCAL_USER
macro, mail addressed to the
root user is sent to the mail hub:
# sendmail -bv root
root... deliverable: mailer relay, host smtp.wrotethebook.com, user root@smtp.
wrotethebook.com
Clearly, sendmail is attempting to forward mail addressed to root to the mail hub. To prevent this, the following line was added to this recipe’s configuration:
LOCAL_USER(root)
With this command in the configuration, the
sendmail
-bv
test shows the
following results:
# sendmail -bv root
root... deliverable: mailer local, user root
The test shows the effect of the LOCAL_USER
macro.
It keeps root mail local, which is just what we
intended. However, before you use the LOCAL_USER
macro, make sure that keeping root mail local is
correct for your configuration. Often, mail to the
root account is routed via an alias to the
administrator’s real login account. For example, you
might route root to alana
if Alana is the administrator of this system and
alana is the account she uses to login. In that
case, you would use an alias and you would not need the
LOCAL_USER
macro—although adding the macro
would do no harm.
An alternative to MAIL_HUB
is the
LOCAL_RELAY
define. LOCAL_RELAY
provides another way to define
a mail relay host for mail that is normally delivered by the
local
mailer. This alternative was rejected
because the LOCAL_RELAY
define has been deprecated
by the sendmail developers for a number of years. When both
MAIL_HUB
and LOCAL_RELAY
are
included in the same configuration, they interact in a number of
ways. We recommend that you avoid LOCAL_RELAY
and
use only MAIL_HUB
in your
configurations.
Chapter 2 provides extensive examples of using
aliases; in particular, Recipe 2.2 provides
an example of routing root’s mail to another
username. Recipe 3.1 also sets a value for
the mail hub in the $H
macro. The
sendmail book covers MAIL_HUB
in 4.5.7, LOCAL_USER
in 4.5.5, and
LOCAL_RELAY
in 4.5.4.
Apparently local mail is mail that appears to be addressed to local users (i.e., the delivery address does not contain a hostname portion, yet the mail is not really addressed to a local username). Configure sendmail to send this mail to a mail relay server that is configured to properly handle it.
Create a sendmail configuration containing a
LUSER_RELAY
define that identifies the host that can handle apparently local
mail. Here is a sample LUSER_RELAY
command:
dnl Define a relay server for apparently local mail define(`LUSER_RELAY', `smtp.wrotethebook.com')
Rebuild and reinstall sendmail.cf. Restart sendmail to read the new configuration. Recipe 1.8 covers these steps.
A delivery address without a hostname is passed to the
local
mailer for delivery to a local user. If the
user portion of the address does not specify a valid local username
or alias,
the
“User unknown” error is returned.
The following tests show how this works with a generic configuration:
#sendmail -bv fred -Cgeneric-linux.cf
fred... User unknown #sendmail -bv craig -Cgeneric-linux.cf
craig... deliverable: mailer local, user craig
craig is a valid username on this host, so the
mail is delivered by the local
mailer.
fred is not a valid local username, so an error
is returned. After adding the LUSER_RELAY
define
to the configuration, mail to craig is delivered
as before, but mail to fred is now sent to the
mail relay host for delivery:
#sendmail -bv fred
fred... deliverable: mailer relay, host smtp.wrotethebook.com, user fred@smtp. wrotethebook.com #sendmail -bv craig
craig... deliverable: mailer local, user craig
The LUSER_RELAY
define sets the value of the
sendmail.cf
$L
macro and adds
two rules to the localaddr
ruleset (ruleset 5).
Ruleset 5 is invoked after a local address is processed through the
aliases database.[2] The two rewrite rules added by the
LUSER_RELAY
define are only executed if the
recipient address has not already been resolved to a valid delivery
address. The first LUSER_RELAY
rewrite rule checks
to see if the username from the email address is a key in the user
database. If the username is found in the user database, the mail is
delivered according to that database’s instructions.
If the username is not found in the database, the mail is sent to the
relay server identified by the $L
macro. Thus, if
a local delivery address does not resolve to a local username or is
not covered by the aliases database or the user
database, the mail is sent to the LUSER_RELAY
server for delivery.
In the last test above, mail addressed to fred
is forwarded to the LUSER_RELAY
server. The
LUSER_RELAY
configuration assumes that the server
knows how to deliver the mail to fred. Often,
this means that the server has a large aliases
file that defines how mail is routed to the users. Unlike the
MAIL_HUB
configuration described in Recipe 3.3, the LUSER_RELAY
configuration does not assume that the server maintains a central
mail spool directory. The LUSER_RELAY
configuration allows the client to deliver some pieces of local mail
and sends others to the server for delivery.
An alternative to LUSER_RELAY
is to have a large
aliases file on the client. This could be a
local file or a centrally maintained file accessible via NIS or some
other database service. An even more popular alternative is to
require users to add the hostname to the email address when the
hostname is required for delivery—in other words, let the users
see the “User unknown” error until
they understand that they need to address email properly. All of
these are viable
alternatives.
Chapter 2 provides examples of both the
aliases database and the user database. The
sendmail book covers
LUSER_RELAY
in 4.5.6.
You have been asked to configure sendmail to send UUCP mail to a mail relay host that has a direct UUCP connection.
Create a sendmail configuration containing a
UUCP_RELAY
define that identifies the mail relay capable of handling UUCP mail.
Here is an example:
dnl Define a relay server for UUCP mail define(`UUCP_RELAY', `uucp.wrotethebook.com')
Build and reinstall sendmail.cf, and restart sendmail, as described in Recipe 1.8.
The UUCP_RELAY
define sets the value of the
sendmail.cf
$Y
macro, adds
UUCP
to class $=P
,
and adds a rule to
the Parse1
ruleset. The new
Parse1
rewrite rule sends UUCP mail that cannot be
delivered by the local host to the mail relay identified by the
$Y
macro. If $Y
is not defined,
sendmail assumes that the local host can deliver all UUCP mail. Class
$=P
contains a list of pseudodomains (domain names
used internally by sendmail), that sendmail does not attempt to look
up in DNS. The .UUCP
pseudodomain is used by
sendmail to mark mail that should be handled as UUCP mail. When mail
addressed to the .UUCP
pseudodomain hits the new
rule in the Parse1
ruleset, the address is
rewritten as a mail delivery triple that sends the mail to the UUCP
mail relay host defined in macro $Y
. A
sendmail
-bt
test shows all of
this:
#sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >/parse crab!craig
Cracked address = $g Parsing envelope recipient address canonify input: crab ! craig Canonify2 input: craig < @ crab . UUCP > Canonify2 returns: craig < @ crab . UUCP . > canonify returns: craig < @ crab . UUCP . > parse input: craig < @ crab . UUCP . > Parse0 input: craig < @ crab . UUCP . > Parse0 returns: craig < @ crab . UUCP . > Parse1 input: craig < @ crab . UUCP . > MailerToTriple input: < uucp . wrotethebook . com > craig < @ crab . UUCP . > MailerToTriple returns: $# relay $@ uucp . wrotethebook . com $: craig < @ crab . UUCP . > Parse1 returns: $# relay $@ uucp . wrotethebook . com $: craig < @ crab . UUCP . > parse returns: $# relay $@ uucp . wrotethebook . com $: craig < @ crab . UUCP . > 2 input: craig < @ crab . UUCP . > 2 returns: craig < @ crab . UUCP . > MasqSMTP input: craig < @ crab . UUCP . > MasqSMTP returns: craig < @ crab . UUCP . > final input: craig < @ crab . UUCP . > final returns: crab ! craig mailer relay, host uucp.wrotethebook.com, user crab!craig >/quit
This test asks sendmail to parse a delivery address written in the
traditional UUCP bang format,
host
!
user
.
The canonify
ruleset rewrites the address into the
standard Internet address format and adds the
.UUCP
pseudodomain. The address continues
unchanged until the Parse1
ruleset, which rewrites
the address into a mail delivery triple. relay
is
the mailer used in the triple, and the value retrieved from the
$Y
macro is the host used in the triple. However,
the user address remains in the .UUCP
pseudodomain
format until the final
ruleset, which returns the
user address to the UUCP bang format. The effect of all of this is to
send bang formatted delivery addresses to the UUCP relay host and to
count on that host to deliver the mail.
The UUCP_RELAY
is not the only pseudodomain mail
relay that can be configured in sendmail. The following defines are
also available:
BITNET_RELAY
Identifies a mail relay connected to the BITNET network (an outdated network that you probably will not use).
DECNET_RELAY
Identifies a mail relay host connected to a DECnet network. DECnet is an outdated network technology that was once a product of the Digital Equipment Corporation. You probably will not use this network.
FAX_RELAY
All of these relays are defined in the same way as the
UUCP_RELAY
in this recipe. Simply replace the
keyword and the name of the relay host in the recipe with the values
you require and rebuild the sendmail.cf file.
However, none of these defines—UUCP_RELAY
,
BITNET_RELAY
, DECNET_RELAY
, or
FAX_RELAY
—are in widespread use. BITNET and
DECnet are grossly out of date technologies and should not be used.
UUCP carries only a small fraction of global email, and most of that
passes transparently through Internet/UUCP gateways using the
standard Internet address format. FAX_RELAY
is not
flexible enough to easily handle the variety of email to FAX servers.
FAX server vendors cannot limit their market to those sites that have
administrators knowledgeable enough to customize sendmail. For this
reason, the vendors usually provide a technique that allows a user to
send a FAX without any modifications to sendmail. Of the four
defines, UUCP_RELAY
is the only one that gets any
real use, and thus it is the one covered in this book.
See the sendmail book for coverage of
UUCP_RELAY
in 4.5.8, the
FAX_RELAY
in 4.5.3, the
BITNET_RELAY
in 21.9.11, and the
DECNET_RELAY
in 4.5.2.
You have been asked to setup a mail relay host to relay mail for every host within the local domain.
On the mail relay host, create a relay-domains file containing the name of your local domain. For example:
#cat >> /etc/mail/relay-domains
wrotethebook.comCtrl-D
Restart sendmail to ensure that it reads the relay-domains file:
# kill -HUP `head -1 /var/run/sendmail.pid`
No m4 configuration commands are needed to
create this mail relay host. sendmail checks for a file named
/etc/mail/relay-domains and adds the names it
finds there to class $=R
by default. There are two ways to change
the default
pathname of the
/etc/mail/relay-domains file:
confCR_FILE
This define sets the path of the file loaded into class
$=R
. The
confCR_FILE
define is
only used when it is necessary to change the default filename. For
example, to load class $=R
from a file named
/etc/sendmail.cr, add the
following line to the master configuration file:
define(`confCR_FILE', `/etc/sendmail.cr')
RELAY_DOMAIN_FILE
This macro specifies the path to an additional file that provides
data for class $=R
. If the default file, which is
usually named /etc/mail/relay-domains, also
exists, it is added to class $=R
. For example, the
following command adds data from the
/etc/sendmail.cr file to class
$=R
:
RELAY_DOMAIN_FILE(`/etc/sendmail.cr')
Neither of these commands appears in this recipe because it is generally a bad idea to change the default pathname of any file used in the sendmail configuration. Other administrators may need to find information on your system. It is easier for them to do so if the information is stored in the standard location.
Before we created the relay-domains file, sendmail blocked all mail relaying—even relaying from other hosts within the local domain. By default, sendmail does not permit relaying. A test conducted before the relay-domains file is created shows this. Below, telnet is used on rodent.wrotethebook.com to connect directly to the SMTP port on the sendmail server smtp.wrotethebook.com:
$telnet 192.168.0.8 smtp
Trying 192.168.0.8... Connected to 192.168.0.8. Escape character is '^]'. 220 smtp.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 15 Aug 2003 14:25:01 - 0400HELO rodent.wrotethebook.com
250 smtp.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet youMAIL From:<craig@rodent.wrotethebook.com>
250 2.1.0 craig@rodent.wrotethebook.com... Sender okRCPT To:<sara@crab.wrotethebook.com>
550 5.7.1 sara@crab.wrotethebook.com... Relaying deniedQUIT
221 2.0.0 smtp.wrotethebook.com closing connection Connection closed by foreign host.
This test shows that the “Relaying denied” error is returned to the sender, indicating that the default sendmail configuration does not allow hosts in the local domain to relay mail to any third host.
After the domain name wrotethebook.com is written into the /etc/mail/relay-domains file and sendmail is restarted, rerunning the test produces a different result:
$telnet 192.168.0.8 smtp
Trying 192.168.0.8... Connected to 192.168.0.8. Escape character is '^]'. 220 smtp.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 15 Aug 2003 15:12:21 - 0400HELO rodent.wrotethebook.com
250 smtp.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet youMAIL From:<craig@rodent.wrotethebook.com>
250 2.1.0 craig@rodent.wrotethebook.com... Sender okRCPT To:<sara@crab.wrotethebook.com>
250 2.1.5 sara@crab.wrotethebook.com... Recipient okDATA
354 Enter mail, end with "." on a line by itselfSubject: Test
This is a test of wrotethebook.com entry in the relay-domains file.
.
250 2.0.0 g8RJCLXf001550 Message accepted for deliveryQUIT
221 2.0.0 smtp.wrotethebook.com closing connection Connection closed by foreign host.
Now, hosts within the local domain are allowed to relay through smtp.wrotethebook.com—all without any changes to the m4 configuration or any need to rebuild the sendmail.cf file. Mail from or to hosts in the wrotethebook.com domain is relayed. Mail that is neither from nor to a host in the wrotethebook.com domain is still blocked from relaying mail.
There are four alternative solutions: the
RELAY_DOMAIN
macro, the
relay_entire_domain feature, the
promiscuous_relay feature, and the
relay_local_from feature.
The example in the Solution section adds only one domain name to
class $=R
. It is possible to add individual
domains to class $=R
from inside the
m4 configuration by using the
RELAY_DOMAIN
macro. The following lines added to the sendmail configuration would
have the same effect as the relay-domains file
defined above:
dnl RELAY_DOMAIN adds a domain name to class R RELAY_DOMAIN(`wrotethebook.com')
However, the RELAY_DOMAIN
command requires
modifying the m4 configuration and rebuilding
and reinstalling the sendmail.cf file. Using the
relay-domains file does not have these
requirements, which makes the relay-domains file
simpler to use.
There are a few other alternative solutions to this problem. We could have used the relay_entire_domain feature to enable relaying for hosts in the local domain. The following command added to a basic configuration would produce the same result as this recipe:
dnl A feature that relays mail for the local domain FEATURE(`relay_entire_domain')dnl
The relay_entire_domain feature adds a few
rewrite rules that relay mail from any host in a domain listed in
class $=m
. By default, class
$=m
contains the domain name of the server system.
Thus, class $=m
contains
wrotethebook.com on a server named
smtp.wrotethebook.com.
This alternative solution works well, but was rejected for a few reasons. First, this solution is slightly more complex that the one used in this recipe. Using the relay_entire_domain feature requires modifications to the m4 configuration, which means that the sendmail.cf file must be rebuilt and reinstalled before sendmail is restarted. Using the relay-domains file only requires sendmail to be restarted.
Second, the value in class $=m
is determined
internally by sendmail. It is usually correct, so this might be a
minor point, but setting the value in
relay-domains gives the administrator more
control. Third, relay-domains is
self-documenting. Looking in the file quickly tells you which domains
the server is configured to relay mail.
Fourth, the relay-domains file is very flexible. The problem section describes creating a mail relay for other hosts in the local domain, which is the most common relaying example. However, any domain can be listed in the relay-domains file, and mail originating from any host in that domain will be relayed. For example, imagine we wanted to create a mail relay that would relay mail for the wrotethebook.com domain, the ora.com domain, the oreilly.com domain and the sybex.com domain. To do that we would just need the following relay-domains file:
# cat /etc/mail/relay-domains
wrotethebook.com
ora.com
oreilly.com
sybex.com
This recipe is used to permit relaying from any host in a specified domain. These reasons give the relay-domains file a slight advantage over the relay_entire_domain feature for this specific application, which is why relay-domains was chosen for this recipe.
Two other alternative solutions were rejected for security reasons:
This feature turns on relaying for all hosts, which includes the local domain, so it would solve our problem. However, this feature would cause many more problems than it would solve because spammers would quickly find and abuse the relay. Never use the promiscuous_relay feature. Even if your host is protected by a firewall, you need to secure your own system from attack—this is a basic tenet of “defense in depth security.” Creating an open relay is always a bad idea.
This feature sounds like a great solution for the problem. It turns on relaying for mail if the email address in the envelope sender address of the mail contains the name of a host in the local domain. The problem is that this feature depends solely on the email address in the envelope sender address. Unfortunately, spammers can easily rewrite the envelope sender address on the spam to make it appear that it originates from your local domain. For this reason, it was rejected as a possible solution for our problem.
The sendmail book covers the
RELAY_DOMAIN_FILE
macro in 7.4.1.2, the
relay_entire_domain feature in 7.4.5, the
relay_local_from feature in 7.4.7, and the
promiscuous_relay feature in 7.4.3. The
cf/README contains current information about all
of these relay features.
You have been asked to configure a mail relay host to relay mail for specific hosts but not for every host within a domain.
On the mail relay host, create a relay-domains file that contains the name of each host for which mail should be relayed.
Add the relay_hosts_only feature to the sendmail configuration on the mail relay host. Here is the required FEATURE command:
dnl Configure the server to relay mail for specific hosts FEATURE(`relay_hosts_only')
Then build sendmail.cf, copy it to /etc/mail, and restart sendmail, as described in Recipe 1.8.
On our sample mail relay host, we create the following relay-domains file:
#cat > /etc/mail/relay-domains
rodent.wrotethebook.com horseshoe.wrotethebook.com jamis.wrotethebook.com tcp.ora.com chill.sybex.com wrotethebook.comCtrl-D
A sendmail
-bt
test shows the
values stored in class $=R
:
#sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >$=R
tcp.ora.com rodent.wrotethebook.com chill.sybex.com jamis.wrotethebook.com horseshoe.wrotethebook.com wrotethebook.com >/quit
Normally, values in class $=R
are interpreted as
domain names, and any host within a domain listed in class
$=R
is allowed to relay mail through the server.
Recipe 3.6 uses this fact to relay mail for
entire domains. In this case, however, we want
wrotethebook.com interpreted as a hostname, not
a domain name, and we want mail routed for that host.
The
relay_hosts_only
feature changes how the entries in
class $=R
are used. In the default configuration,
pattern matches against class $=R
contain the
string $*$=R
, which matches zero or more tokens
and any value stored in $=R
. Thus
wrotethebook.com,
crab.wrotethebook.com, and
fun.rodent.wrotethebook.com would all pattern
match the wrotethebook.com value found in the
class $=R
array shown above. The
relay_hosts_only feature changes the string in
the pattern match to $=R
, meaning that only exact
matches of values found in class $=R
are valid
matches. When relay_hosts_only is used with our
sample class $=R
values,
rodent.wrotethebook.com matches the pattern
because rodent.wrotethebook.com is included in
$=R
; however,
crab.wrotethebook.com does not match—even
though the value wrotethebook.com appears in the
array. Only a host named wrotethebook.com would
match that specific value when relay_hosts_only
is used.
A couple of tests demonstrate the impact of the relay_hosts_only feature. A telnet test from rodent shows that smtp is configured to allow relaying for rodent:
$telnet smtp.wrotethebook.com smtp
Trying 192.168.0.8... Connected to 192.168.0.8. Escape character is '^]'. 220 smtp.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 15 Aug 2003 15:36:52 - 0400HELO rodent.wrotethebook.com
250 smtp.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet youMAIL From:<craig@rodent.wrotethebook.com>
250 2.1.0 craig@rodent.wrotethebook.com... Sender okRCPT To:<tyler@example.com>
250 2.1.5 tyler@example.com... Recipient okQUIT
221 2.0.0 smtp.wrotethebook.com closing connection Connection closed by foreign host.
The same test run from crab shows that crab is not allowed to relay through smtp:
#telnet smtp.wrotethebook.com smtp
Trying 192.168.0.8... Connected to 192.168.0.8. Escape character is '^]'. 220 smtp.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 15 Aug 2003 20:43:11 - 0400HELO crab.wrotethebook.com
250 smtp.wrotethebook.com Hello crab.wrotethebook.com [192.168.0.15], pleased to meet youMAIL From:<craig@crab.wrotethebook.com>
250 2.1.0 craig@crab.wrotethebook.com... Sender okRCPT To:<tyler@example.com>
550 5.7.1 tyler@example.com... Relaying deniedQUIT
221 2.0.0 smtp.wrotethebook.com closing connection Connection closed by foreign host.
One final test from crab shows the full impact
of class $=R
on relaying:
$telnet smtp.wrotethebook.com smtp
Trying 192.168.0.8... Connected to smtp. Escape character is '^]'. 220 smtp.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 15 Aug 2003 14:20:16 - 0400HELO crab.wrotethebook.com
250 smtp.wrotethebook.com Hello crab.wrotethebook.com [192.168.0.3], pleased to meet youMAIL From:<craig@crab.wrotethebook.com>
250 2.1.0 craig@crab.wrotethebook.com... Sender okRCPT To:<kathy@rodent.wrotethebook.com>
250 2.1.5 kathy@rodent.wrotethebook.com... Recipient okQUIT
221 2.0.0 smtp.wrotethebook.com closing connection Connection closed by foreign host.
In this case, crab successfully relays mail
through smtp. If either the sending host or the
recipient host is listed in class $=R
, the mail is
accepted for relaying. Therefore, mail sent from
crab to rodent is accepted
for relaying, even though crab is not granted
relaying privileges, because rodent is allowed
to relay and rodent is the destination of this
piece of
mail.
Section 7.4.6 in the sendmail book covers the relay_hosts_only feature. Recipe 3.6 and Recipe 3.8 provide solutions to similar problems that may also need to be evaluated.
You are asked to configure sendmail on a mail exchanger to permit relaying for all systems that legitimately use it as their mail exchanger.
Obtain from the domain administrator a listing of the hostnames whose MX records point to the local system as their mail exchanger. Add the list of hostnames to the local-host-names file to handle inbound mail that should be delivered to a mailbox on the mail exchanger or forwarded as directed by the aliases or .forward files. Add the hostnames from the list to the relay-domains file to handle mail that should be relayed.
If you have access to a system that can list the entire domain, you can use the following bit of Unix magic to create a listing of every host in the domain that uses your mail system as its MX server:[3]
#cd /etc/mail
#host -l wrotethebook.com | \
> grep 'mail.*mail\.wrotethebook\.com' | \ > awk '{ print $1 }' > temp-relay-domains
This example writes the list to a file named temp-relay-domains file. Verify the file contents before storing the data in either the relay-domains file or the local-host-names file. Additionally, this example requires the sendmail administrator to have direct access to a system that is entitled to list the entire domain file. Unless you pull double duty as both DNS administrator and sendmail administrator, you might have to rely on the domain administrator for the list of hostnames.
The local-host-names file configures the mail exchanger to accept mail for local delivery or forwarding, as discussed in Chapter 2. The relay-domains file configures the mail exchanger for relaying.
Mail to or from hosts in the relay-domains file will be relayed. Note that the names in the relay-domains file in this example are treated as hostnames, not domain names, because we are using the relay_hosts_only feature.
The relay_based_on_MX feature is an alternative solution to the problem described in the Problem section. When the relay_based_on_MX feature is used, sendmail relays mail for any system that lists the local host on its MX record. The relay_based_on_MX solution is simpler than this recipe, and just as effective, but it was rejected for two reasons:
First, the creation of MX records is not under your control. Any domain administrator, anywhere in the world, could define your mail relay host as a mail exchanger for his domain. After that, any host in that remote domain can use your host as a mail relay. Thus, you are not in control of which hosts use your relay.
Second, the sendmail developers state that it “is
usually better to maintain a list of hosts/domains for which the
server acts as a relay” than it is to use the
relay_based_on_MX feature. In addition to the
lack of control mentioned above, they cite the possibility of
delivery problems when the remote DNS server is slow, and that some
address formats (specifically the %
hack) are not
treated as you might suppose.
Loss of control and the recommendation of the sendmail developers were enough to make us choose the solution in Recipe 3.8. If simplicity is more important to you, the relay_based_on_MX feature also works.
The discussion of the relay_based_on_MX feature in the cf/README file explains the developers’ recommendations. The sendmail book covers relay_based_on_MX in 7.4.4. Recipe 2.1 and Recipe 3.7 provide important material for this recipe.
You have been asked to configure sendmail to read the names of hosts and domains that are granted relaying privileges from an LDAP server.
On the LDAP server, add support for the sendmail schema as described in Recipe 1.3. Note that this only needs to be done once.
On the LDAP server, add to the LDAP database the names of the hosts
and domains that are allowed to relay. Use the
sendmailMTAClass
object class format defined in
the sendmail.schema file. The Discussion section
shows an example doing this on a server that runs OpenLDAP.
On the mail relay host, use the command sendmail
-bt
-d0.1
to check if sendmail
was compiled with LDAP support. The string LDAPMAP
must appear in the “Compiled with:”
list. If sendmail was not compiled with LDAP support, recompile and
reinstall sendmail as shown in Recipe 1.3.
Once sendmail supports LDAP, continue with the next steps.
On the mail relay host, add a
RELAY_DOMAIN_FILE
macro to the sendmail configuration
specifing @LDAP
as the relay domain file path,
which tells sendmail to read class $=R
values from
the LDAP server using the standard sendmail schema. Use the
confLDAP_CLUSTER
define to set the
${sendmailMTACluster}
macro to the same value used
in the sendmailMTACluster
attribute of the LDAP
entry. Here are sample sendmail configuration commands:
dnl Set the LDAP cluster value define(`confLDAP_CLUSTER', `wrotethebook.com') dnl Tell sendmail to load $=R via LDAP RELAY_DOMAIN_FILE(`@LDAP')
Build the configuration file, copy it to /etc/mail/sendmail.cf, and restart sendmail with the new configuration, as described in Recipe 1.8.
This recipes assumes that LDAP is properly installed and running. This is not the place to start experimenting with LDAP. Both LDAP and sendmail are large, complex systems. You should have some experience with LDAP before attempting to use it with sendmail.
The sendmail.schema file that comes with the sendmail distribution must be included in the LDAP configuration in order for LDAP to understand and properly process queries from sendmail.[4] The LDAP administrator must ensure that LDAP is ready to work with sendmail’s standard schema before adding sendmail data to the LDAP database.
The LDAP administrator builds an LDIF file using the sendmail schema to define the list of hosts granted relay privileges and then runs ldapadd to add the contents of the LDIF file to the LDAP database. Here is an example that adds all of the hostnames from the relay-domains file used in Recipe 3.7:
#cat > ldap-relay-domains
dn: sendmailMTAClassName=R, dc=wrotethebook, dc=com objectClass: sendmailMTA objectClass: sendmailMTAClass sendmailMTACluster: wrotethebook.com sendmailMTAClassName: R sendmailMTAClassValue: rodent.wrotethebook.com sendmailMTAClassValue: horseshoe.wrotethebook.com sendmailMTAClassValue: jamis.wrotethebook.com sendmailMTAClassValue: tcp.ora.com sendmailMTAClassValue: chill.sybex.com sendmailMTAClassValue: wrotethebook.comCtrl-D
#ldapadd -x -D "cn=Manager,dc=wrotethebook,dc=com" \
> -W -f ldap-relay-domains
Enter LDAP Password:SecretLDAPpassword
adding new entry "sendmailMTAClassName=R, dc=wrotethebook, dc=com"
An ldapsearch test shows the data in the LDAP database:[5]
# ldapsearch -LLL -x '(sendmailMTAClassName=R)' sendmailMTAClassValue
dn: sendmailMTAClassName=R, dc=wrotethebook, dc=com
sendmailMTAClassValue: rodent.wrotethebook.com
sendmailMTAClassValue: horseshoe.wrotethebook.com
sendmailMTAClassValue: jamis.wrotethebook.com
sendmailMTAClassValue: tcp.ora.com
sendmailMTAClassValue: chill.sybex.com
sendmailMTAClassValue: wrotethebook.com
Once the data is added to the LDAP server, the sendmail system can be configured to read it.
The list of hosts granted relaying privileges are added to the LDAP
database as values in a single sendmailMTAClass
object class record. As the sendmailMTAClassName
attribute makes clear, these values will be stored in class
$=R
. Normally, class $=R
is
loaded from the file /etc/mail/relay-domains.
Use the RELAY_DOMAIN_FILE
macro to add another
source of data for class $=R
. The string
@LDAP
in the path field of the macro tells
sendmail to load class $=R
with values obtained
from the LDAP server. The effect of the @LDAP
string on the RELAY_DOMAINS_FILE
macro can be
easily seen using the sendmail
-bt
command:
#rm -f /etc/mail/relay-domains
#sendmail -bt -Cgeneric-linux.cf
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >$=R
>/quit
#sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >$=R
rodent.wrotethebook.com chill.sybex.com jamis.wrotethebook.com horseshoe.wrotethebook.com wrotethebook.com tcp.ora.com >/quit
The rm command in this test is just to show the
reader that no values are being loaded into class
$=R
from the relay-domains
file. On a real system, you might want to use both the
relay-domains file and LDAP.
The first sendmail
-bt
test
loads the generic-linux.cf configuration
provided with the sendmail distribution. The $=R
command displays the contents of the class $=R
,
which, in this case, is empty. The sendmail
-bt
test is rerun using the sendmail.cf
configuration file created in this recipe. This time the
$=R
command displays the values retrieved from the
LDAP server.
Class $=R
is not the only class that can be loaded
via LDAP. Any class loaded from a file can be loaded via LDAP by
replacing the file pathname on the F
command with
the string @LDAP
, using this syntax:
F{name
}@LDAP
where name
is the class’
name. The same name is then used as the value for the
sendmailMTAClassName
attribute in the LDAP record
that defines the values loaded into the class. Note that this is the
class name without the curly braces.
This recipe uses the
confLDAP_CLUSTER
define because the LDAP record created for this recipe contains the
sendmailMTACluster
attribute. sendmail LDAP
records apply to either a single host or a group of hosts, which
sendmail calls a cluster. A record that applies
to a single host uses the sendmailMTAHost
attribute; a record that applies to a group of hosts uses the
sendmailMTACluster
attribute. If
confLDAP_CLUSTER
is not specified, a cluster name
is not used, and only records with a
sendmailMTAHost
attribute that matches the
hostname of the sendmail host are retrieved. The record added to the
LDAP database in the example above used the
sendmailMTACluster
attribute, and sets that
attribute to wrotethebook.com. Therefore, it is
necessary to define a matching cluster value in the sendmail
configuration. The confLDAP_CLUSTER
define shown
in the Solution section sets the sendmail.cf
macro ${sendmailMTACluster}
, which holds the
cluster name, to wrotethebook.com. If that
define was not used, queries from the local host would not
successfully retrieve the sample class $=R
values
from the LDAP server.
Recipe 3.6 and Recipe 3.7
provide information about class $=R
and how it is
used for relaying. Information about LDAP is available in
Understanding and Deploying LDAP Directory
Services by Howes, Smith, and Good (Macmillan) and in
LDAP System Administration by Gerald Carter
(O’Reilly). The cf/README file
covers this topic in the Using LDAP for Aliases, Maps, and
Classes section. The sendmail book
covers the RELAY_DOMAIN_FILE
macro in Section
7.4.1.2 and the confLDAP_CLUSTER
define in Section
21.9.82.
You have been asked to configure a mail relay host to handle only outbound mail. The host is to relay mail sent from selected hosts without relaying mail addressed to those hosts.
Add support for the
access
database to the sendmail configuration by using the
access_db
feature. Here is the required
FEATURE
macro:
dnl Add support for the access database FEATURE(`access_db')
Build an access database that defines all of the
clients from which this server should accept mail for relaying. The
access database entries should be in the form of
Connect
:address
RELAY
, where address
is
the IP address or DNS name of the source from which mail will be
accepted.
Rebuild and reinstall sendmail.cf, then restart sendmail. These steps are covered in Recipe 1.8.
Mail from, or addressed to, any domain defined in the relay-domains file is relayed. Thus, the relay-domains file creates a relay that handles both inbound and outbound mail, which is generally the configuration used. Occasionally, however, network designers decide to use separate systems for inbound and outbound mail. For example, a mail exchanger for all inbound mail and a mail relay host for all outbound mail might be placed on two physically separate systems. The access database provides the fine-grained control necessary to implement these design decisions. The access_db feature adds support for the access database to the sendmail configuration.
Entries in the access file, from which the access database is built, contain two basic fields:
The conditional test that determines whether an action is taken
The action taken when the condition is met
The conditional test can contain various types of data depending on what the access database entry is being used for. For relaying, the conditional test usually includes an address, which can be a full or partial domain name, hostname, or IP address. It can also be a full email address or just the user portion of an email address. Here is an example of creating an access database entry that relays mail received via a connection from any host in the local wrotethebook.com domain:
#cd /etc/mail
#cat > access
Connect:wrotethebook.com RELAY
Ctrl-D
#makemap hash access < access
The example uses the domain name wrotethebook.com as the data in the conditional test because we want to relay mail for every host in that domain. An alternative would be to use the network address to relay mail for every host on the local network, for example:
Connect:192.168.0 RELAY
The keyword Connect
: that is placed before the
data in the conditional test is called a tag. A
tag is used to limit the scope of the test. Tags are optional.
Normally, the data in the conditional test field of an entry in the
access database are tested against three
different values—the sender and recipient addresses from the
message envelope, and the IP address of the remote system that
connected to the server to transfer the mail. If any one of these
three addresses matches the conditional data in the
access database, the condition is met, and the
action defined in the database is taken. Use a tag to change this
default behavior and limit the conditional test to one of the three
possible addresses. The basic tag values are:
To
:Only the recipient address in the message envelope is matched against the conditional test data.
From
:Only the sender address in the message envelope is matched against the conditional test data.
Connect
:Only the IP address of the remote system that initiated the connection over which the mail was received is matched against the conditional test data.
The example above uses the Connect
: tag to limit
relaying to only those hosts that connect to the relay server from
the wrotethebook.com domain. Mail from any other
source is not relayed.
The action field in the sample access file entry
contains the keyword RELAY
, which simply means
that the server should relay mail that matches the specified
conditional test. RELAY
is the only keyword that
directly relates to relaying. Several other action keywords are
covered in Chapter 7.
The access file must be converted to a hash database before sendmail can use it. The makemap program does the required conversion. It reads ASCII text from stdin and writes out a database of the specified type to the specified file. In our example, note that the input and output names appear the same. They’re not. The input file is named access and the output file is named access.db. However, you do not need to add the .db extension to the output filename. makemap automatically adds the correct extension based on the type of database specified. makemap is provided as part of the sendmail distribution.
After building the access database, building sendmail.cf, and restarting sendmail, the system relays mail from clients in the local domain but will not relay mail to those clients if the mail originates in some other domain.[6] Two tests show this. The first test is mail sent from a host in the local domain to a remote host:
$telnet smtp.wrotethebook.com smtp
Trying 192.168.0.8... Connected to smtp. Escape character is '^]'. 220 smtp.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 15 Aug 2003 16:47:57 - 0400HELO rodent.wrotethebook.com
250 smtp.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet youMAIL From:<craig@rodent.wrotethebook.com>
250 2.1.0 craig@rodent.wrotethebook.com... Sender okRCPT To:<tyler@example.com>
250 2.1.5 tyler@example.com... Recipient okQUIT
221 2.0.0 smtp.wrotethebook.com closing connection Connection closed by foreign host.
The second test is mail sent from a remote host to a host in the local domain. If the local domain was specified in the relay-domain file, this mail would be accepted. This test shows that with the access database from this recipe, the mail is rejected:
$telnet smtp.wrotethebopok.com smtp
Trying 192.168.0.8... Connected to smtp. Escape character is '^]'. 220 smtp.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 15 Aug 2003 16:52:07 - 0400HELO example.com
250 smtp.wrotethebook.com Hello example.com {10.20.3.3], pleased to meet youMAIL From:<tyler@example.com>
250 2.1.0 tyler@example.com... Sender okRCPT To:<craig@rodent.wrotethebook.com>
550 5.7.1 craig@rodent.wrotethebook.com... Relaying deniedQUIT
221 2.0.0 smtp.wrotethebook.com closing connection Connection closed by foreign host.
Chapter 6 provides more information about the access database. The Finer control by using tags for the LHS of the access map section of the cf/README file provides additional information about tags. The sendmail book covers the access database in Section 7.5.
[1] Set /tryflags
to
ES
and rerun this test to verify that the
envelope/sender address is also rewritten.
[2] Ruleset 5 is
invoked only when the F=5
flag is set for the
selected mailer. By default, this flag is set for the
local
mailer, which is the mailer used in our
examples.
[3] In the example, we list a domain named
wrotethebook.com and grep
for
mail.wrotethebook.com. Replace these values with
the correct values for your domain and mail system hostname.
[4] You can, of course, design your own schema. But that is not a topic for a sendmail book.
[5] If ldapsearch requires
-h
and -b
arguments, matching
values will also be required by sendmail. See Recipe 5.9 for an example of setting
-h
and -b
for sendmail.
[6] sendmail does not need to be restarted when a database changes. The only reason a restart was needed for this recipe was because the sendmail.cf file changed.