home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Previous Section Next Section

7.4 Relaying

Promiscuous relaying is the process of accepting email from outside your site and then transmitting it to another host also outside your site. Hosts that relay are quickly discovered by spam programs, and used to mask the identity of the originating spam site. Prior to V8.9, promiscuous relaying was allowed by default. Beginning with V8.9, promiscuous relaying is turned off by default.

In place of default relaying, V8.9 and above sendmail provides a variety of features, macros, and databases that allow you to relay in a variety of manners. The access database (Section 7.5) provides a way to relay on a host-by-host, or network basis. Adding domains to the class $=R ($=R) is another method. In this section we describe features that allow you to tune relaying to your taste. Table 7-2 lists the features available as of V8.12.

Table 7-2. Relay features

Feature

§

Description

access_db

Section 7.5

Screen addresses and set policy

loose_relay_check

Section 7.4.2

Allow %-hack relaying

promiscuous_relay

Section 7.4.3

Allow all relaying

relay_based_on_MX

Section 7.4.4

Relay for any site for which you are an MX server

relay_entire_domain

Section 7.4.5

Relay based on $=m

relay_hosts_only

Section 7.4.6

Interpret domains in relay-domains, and access database, as hosts

relay_local_from

Section 7.4.7

Relay if SMTP MAIL domain is in $=w

relay_mail_from

Section 7.4.8

Relay if SMTP MAIL address is RELAY in access database, and provided the entry is properly tagged.

In addition to the features we discuss here, you should also see Chapter 10 for a discussion of how relaying can be controlled with AUTH= and STARTTLS.

Before you turn on relaying of any sort, be sure you understand the potential risks of your decision. A mistake that loosens relaying restrictions too much can open your site to abuse as a spam relay from anywhere in the world.

The following features are presented in alphabetical order, not in order of recommendation or safety. In fact, the first is more fraught with risk than the others. Take care to read about all these relaying features so that you fully understand them before choosing any.

7.4.1 Macros to Allow Relaying

Hosts and domains to which mail can be relayed are listed either in a special sendmail class, or in the access database. You add hosts and domains to the special class with either the RELAY_DOMAIN mc macro, or the RELAY_DOMAIN_FILE mc macro.

7.4.1.1 The RELAY_DOMAIN mc macro

A special class (currently $=R)[14] holds as its list of values host and domain names to which sendmail should allow mail to be relayed. Relaying is discussed in general in the sections that follow.

[14] Do not use this class directly. Instead, use the macros we present here. If you use it directly, you risk breaking your configuration file if sendmail changes in the future.

You add domain names to this class like this:

RELAY_DOMAIN(`list of hosts and domains')

Here, the list is one or more hosts or domains separated from each other by spaces:

RELAY_DOMAIN(`our.internal.domain our.company.domain')

If you find it more convenient to list them on separate lines you can do so like this:

RELAY_DOMAIN(`our.internal.domain')
RELAY_DOMAIN(`our.company.domain')

The list can be host or domain names, or IP numbers, or network numbers. IPv6 addresses can be specified by prefixing each with the literal text IPv6:, as for example:

host.another.domain       a hostname
your.domain               a domain name
123.45                    a network (leftmost numbers)
123.45.67.89              a host IP address
IPv6:2002:c0a8:02c7       an IPv6 network
IPv6:2002:c0a8:51d2::23f4 an IPv6 host address
7.4.1.2 The RELAY_DOMAIN_FILE mc macro

You can also maintain a list of hosts, domains, and addresses that can be relayed to in an external file. That file is declared with the following macro:

define(confCR_FILE, `path')  deprecated 
RELAY_DOMAIN_FILE(`path')

The recommended value for path is /etc/mail/relay-domains:

RELAY_DOMAIN_FILE(`/etc/mail/relay-domains')

This declaration causes a list of relay hosts, domains, or addresses to be read from the file /etc/mail/relay-domains. Because RELAY_DOMAIN_FILE is implemented with an F configuration command (Section 22.1.2), you can add whatever F command arguments you desire. For example:

RELAY_DOMAIN_FILE(`-o /etc/mail/relay-domains')

Here, the -o switch makes the presence of the /etc/mail/relay-domains file optional.[15]

[15] This is not recommended, but serves as an example of one way to modify the underlying F command.

If you are currently reading relaying information from a file declared directly with the F configuration command, you are encouraged to convert to this new macro. Use of it will insulate you from change in the future if a different class name is ever used.

7.4.2 FEATURE(loose_relay_check)

The percent-hack is a form of address that uses the % character to route mail through one host to another. For example, the following address uses the percent-hack to relay mail through hostA for delivery to hostB:

user%hostB@hostA

The intention here is to cause sendmail to connect to the hostA host and send the message by specifying user@hostB as the envelope-recipient, meaning that hostA will relay the message to hostB.

V8 sendmail no longer allows the percent-hack form of relaying without first performing two checks. First, the connected-to host, the one following the @ (hostA), is looked up in the class macro defined by the RELAY_DOMAIN mc macro, and in the access database. If the connected-to host is neither in that class nor OK'd by the access database, the message is rejected with:[16]

[16] Beginning with V8.12, you can customize this rejection message using the confRELAY_MSG mc configuration macro. To use it, include the leading 550, but exclude the 5.7.1, and replace the old text with the new (see cf/README).

550 5.7.1 Relaying denied.

If the connected-to host is OK, sendmail looks up the destination host hostB, also in the class macro defined by the RELAY_DOMAIN mc macro (Section 7.4.1.1), and in the access database. If the destination host is neither in that class nor OK'd by the access database, the message is rejected; otherwise it is accepted for delivery.

In brief, for the percent-hack to work, both hosts must be listed in the class macro defined by the RELAY_DOMAIN mc macro, or OK'd by the access database, or both.

One way to list them might look like this in your mc configuration file:

RELAY_DOMAIN(`hostA.domain hostB.domain')      V8.9 and above

If it is not possible for you to know ahead of time which hosts should be listed in that class, you might want to loosen this check. But be forewarned, if you think you need to loosen this check, you probably do not need to.

To loosen these checks, you can use the loose_relay_check feature, which is declared in your mc configuration file like this:

FEATURE(loose_relay_check)        CAUTION!

Use this feature with caution! It risks allowing spammers to relay through your server because it skips the check for the destination host—that is, the host following the % (hostA in our example). Consider, for example, a spam site sending a spam message with the following envelope-recipient:

user%site.to.spam@your.mail.server

If your mail server is listed with RELAY_DOMAIN (as it would be if it relays mail inward to your internal network), and if your mail server uses this loose_relay_check feature, there is nothing to prevent this spam message from being relayed to any arbitrary site on the Internet, or for your site to be abused as a spam relay.

Note that this feature can be of benefit in an internal network protected by a well-configured mail gateway and a firewall because it allows testing of internal mail hubs as potential MX servers for internal-only email.

7.4.3 FEATURE(promiscuous_relay)

Sometimes it is beneficial to set up a mail server that will relay mail from any host that connects to it. Consider a main mail-sending machine that exists behind a firewall. In this example, the mail-sending machine is separate from the mail-receiving machine. The mail-sending machine has inbound port 25 blocked at the firewall so that it cannot receive mail from anywhere but the internal network. In such an arrangement, it is simpler to allow any internal host to relay mail than to specify individual hosts or domains in the access database, or with the class $=R, or with authentication.

If this simpler approach is applicable to your site, and if your network is totally secure around port 25, you can enable unfettered or "promiscuous" relaying with this promiscuous_relay feature. You declare it like this:

FEATURE(`promiscuous_relay')

To underscore the risk associated with this feature, the following warning will be printed each time you build with your mc configuration file:

*** WARNING: FEATURE(`promiscuous_relay') configures your system as open
        relay.  Do NOT use it on a server that is connected to the Internet!

By declaring this feature, you tell sendmail to allow mail received by the local machine from anywhere in the world to be relayed outward to any machine in the world. This opens up the local machine to be used by spam engines worldwide, and almost guarantees that the local machine will eventually become listed by one or more DNSBL sites.

You should use this feature only if the affected machine is secured by other means. If you don't have an effective firewall, or don't have knowledgeable network administrators, you should avoid using this promiscuous_relay feature.

7.4.4 FEATURE(relay_based_on_MX)

When sendmail receives a message bound for another host, it might be doing so because the local machine is listed as an MX record for that other host (Section 9.2) and the other host is temporarily down. When that other host comes back up, sendmail will deliver all such queued messages to it. You allow relaying for hosts for which your site serves as an MX record, by listing the names of those sites in your relay-domains file ($=R).

There might be times, however, when your site must be an MX server for an unknown number of sites, or an unknown variety of domains. One such example might occur when your machine is behind a firewall on a private network. You might be the central MX site for all internal domains that are created or renamed often. For such sites, sendmail offers the relay_based_on_MX feature, which looks like this:

FEATURE(`relay_based_on_MX')

When you declare this feature, you allow sendmail to relay mail to any host for which your site is listed as an MX record. Fortunately you don't have to keep track of which hosts do list your site because this feature makes the process automatic.

This feature should be used only in an environment where you administer or trust the DNS records. You should not use it if your DNS lookups come from the Internet at large because, in that instance, anyone in the world would be able to use your machine as an MX server without your knowledge or permission.

Note that you should not use this relay_based_on_MX feature if you also use the -z switch with the bestmx database map (bestmx).

Also note that relaying for MX purposes is different from relaying for the % hack (see Section 7.4.2).

7.4.5 FEATURE(relay_entire_domain)

By default, only hosts listed in the access database (Section 7.5) with the righthand side keyword RELAY, or hosts that are listed with the RELAY_DOMAIN macro (Section 7.4.1.1), are allowed to relay mail through the local host. You can allow all the hosts in your domain to relay mail through the mail server by listing them there, but it is much easier to use the shorthand method provided by the relay_entire_domain feature:

FEATURE(`relay_entire_domain')

When you define this feature, you enable any host listed in the class $=m ($=m), your domain, to relay mail through the local host. Note, however, that if your host is named something such as bob.gov, your host and domain will be the same. Whatever you do, never put a top-level domain such as gov, or com, or de into $=m, or you will find your site relaying mail for any host in that top-level domain.

Note that $=m should not be used to have mail accepted as local under a variety of domains. Instead use the domaintable feature (FEATURE(domaintable)).

7.4.6 FEATURE(relay_hosts_only)

Normally, relaying is based on the domains listed with the RELAY_DOMAIN mc macro (Section 7.4.1.1) or in the file specified by the RELAY_DOMAIN_FILE mc macro (Section 7.4.1.2), or on the domains allowed to relay in the access database. When sendmail checks to see if a domain should be allowed to relay, it interprets each domain as a top-level domain. For example, if RELAY_DOMAIN listed the following entry, or if the RELAY_DOMAIN_FILE file contained the following entry:

your.domain

all the following domains would also match that single domain entry:

sub.your.domain
a.very.deep.sub.your.domain

As an alternative, you can have sendmail interpret each name as the literal name of a host. If you prefer this second method, you can enable it by declaring the relay_hosts_only feature like this:

FEATURE(relay_hosts_only)

With this feature declared, sendmail will compare the sending host to the list of hosts, and to hosts looked up in the access database, on a host-by-host basis. For example, if the RELAY_DOMAIN defined the following:

sub.domain

only a host named sub.domain would be allowed to relay. Another host—say, hostB.sub.domain, would not be allowed to relay unless it too was listed, or OK'd by the access database.

Clearly this feature gives you more control over who can and cannot relay. It can be of value at a site that is populated by some network printers and some Unix machines. The file specified by RELAY_DOMAIN_FILE could be set up to allow the Unix machines to relay, but not the printers.

7.4.7 FEATURE(relay_local_from)

During an SMTP conversation the sending host specifies the address of the envelope-sender by issuing a MAIL SMTP command. RFC2822 commentary and DSN extensions are then discarded from that specified address, and the result is stored in the $f macro ($f).

If you wish, you can use the value in the $f macro to determine if a message should be relayed to any outside or inside host. Although such a method is fraught with risk, it is still made available with the relay_local_from feature, which is declared like this:

FEATURE(`relay_local_from')

Because this feature poses risk, the following warning will be printed each time you build with your mc configuration file:

*** WARNING: FEATURE(`relay_local_from') may cause your system to act as open
        relay.  Use SMTP AUTH or STARTTLS instead. If you cannot use those,
        try FEATURE(`relay_mail_from').

When you declare this feature you cause the domain part of the address in $f (the portion of the address to the right of the @ character) to be compared to the list of hosts in the $=w class macro ($=w). Recall that the class $=w contains all the names by which the local host can be known. If the domain in $f is found in that class, relaying is allowed.

The risk should be obvious. Because $f is given its value as a part of the SMTP MAIL command, that address can be forged to appear local by anyone on the Internet. That is, by declaring this feature, you are opening up your host to abuse by the entire world.

So why does sendmail offer this relay_local_from feature? If you administer a site that is behind a firewall and an Internet mail hub, and if your internal machines cannot be contacted on any port from the outside world, you might find this a simple way to allow global relaying within that network.

We suggest, however, that SMTP AUTH (Section 10.9) or STARTTLS (Section 10.10) will provide a safer way to authenticate local origination addresses upon which to base the permission to relay. A safer way to relay based on connection domains is the Connect: keyword in the access database. If you prefer a simpler solution, the relay_mail_from feature, described next, might be just what you are looking for, although it, too, is risky.

7.4.8 FEATURE(relay_mail_from)

During an SMTP conversation the sending host specifies the address of the envelope-sender by issuing a MAIL SMTP command. RFC2822 commentary and DSN extensions are then discarded from that address, and the result is stored in the $f sendmail macro ($f).

If you wish, you can use the value in the $f sendmail macro to determine if a message should be relayed to any outside or inside host. Although such a method is fraught with risk, it is still made available with the relay_mail_from feature, which is declared like this:

FEATURE(`relay_mail_from')

Because this feature poses risk, the following warning will be printed each time you build your cf file from your mc file:

*** WARNING: FEATURE(`relay_mail_from') may cause your system to act as open
        relay.  Use SMTP AUTH or STARTTLS instead.

By declaring this feature, you cause the address in the $f sendmail macro to be prefixed with a literal From: and looked up in the access database (Section 7.5). If it is found in that database, and the value returned is a literal RELAY, that address is allowed to be relayed:

From:bob@your.domain    RELAY    this sender can relay

If you want to base the decision to relay on a domain instead of on an individual's address, you can declare this feature with an additional argument that is a literal domain:

FEATURE(`relay_mail_from', `domain')

With this extra argument in place, the domain part of the address in $f (the portion of the address to the right of the @ character) will be prefixed with a literal From: and looked up in the access database. If it is found, and if the value returned is a literal RELAY, that domain will be allowed to be relayed:

From:your.domain    RELAY    this domain can relay

This feature is fraught with risk. By defining it, you allow anyone on the Internet to spoof allowed addresses as part of any SMTP MAIL command. If you want to allow local hosts to relay mail from the local network to the world, you can either authenticate with SMTP AUTH (Section 10.9) or STARTTLS (Section 10.10), or you can relay based on connections using the Connect: keyword in the access database.

7.4.9 Risk with FEATURE(nouucp)

UUCP addresses are those that use a ! character to separate address components. For example, the following address says to send the message first to the host hostA, and then hostA will relay that message to user@hostB:

hostB!user@hostA

If you have tuned your site to prevent unintended relaying, misuse of the nouucp features can open your site to an unexpected form of relaying.

Consider a workstation on your network that forwards all its mail to the central mail hub using LOCAL_RELAY (Section 4.5.4) or LUSER_RELAY ($L). If that workstation also defines:

FEATURE(`nouucp', `nospecial')

addresses containing the ! character will not be recognized as special and will be forwarded to the mail hub as is.

If, on the mail hub, you forget to declare the nouucp feature, the as-is address forwarded to it will be recognized as special. Because the address was received from an internal workstation, relaying is allowed. The ! address will have the hostA part stripped and the result will be relayed to user@hostB.

Thus, it is a good idea to define nouucp on the mail hub if you define it on any of your workstations.

7.4.10 FEATURE(accept_unresolvable_domains)

Beginning with V8.9, sendmail will refuse a mail message if the address specified as part of the SMTP MAIL FROM: has a domain part that cannot be looked up. For example, if the domain foo.bar does not exist, the following error will be logged with syslog and the message will be rejected with the same error message:

553 5.1.8 <user@your.domain>... Domain of sender address other@foo.bar does not 
exist

If the domain cannot be looked up, the result is a temporary error:

451 4.1.8 <user@your.domain>... Domain of sender address other@foo.bar does not 
resolve

We recommend rejecting such addresses, but there might be circumstances where you cannot. If, for example, you are behind a firewall and lack access to full DNS lookups, you might want to accept everything. But if that is the case, you will need a sending mail hub with good DNS access so that you can reply to such messages.

You can accept such addresses by defining the accept_unresolvable_domains feature:

FEATURE(`accept_unresolvable_domains')

This tells sendmail to accept all envelope-sender addresses, even if the domain part following the @ cannot be looked up with DNS.

7.4.11 FEATURE(accept_unqualified_senders)

The sendmail program refuses to accept a message if the address specified as part of an SMTP MAIL command lacks a domain. That is, if the address has a user part but lacks the @ followed by a domain, the message will be rejected:

MAIL FROM:<bob@foo.com>       good, has a domain part
MAIL FROM:<bob>               bad, lacks a domain part

Some mail submission programs will submit mail without including a domain part. Improperly configured PCs are one example, as are poorly configured Unix hosts. Generally, such problems will appear on your local network. If you lack the authority to fix such a problem, you can tweak sendmail to accept such addresses by including the accept_unqualified_senders feature like this:

FEATURE(`accept_unqualified_senders')

Note that this feature accepts unqualified addresses regardless of the port on which they are received. Such a broad solution might be acceptable on an internal network, but is discouraged on machines that service the Internet. For those hosts, we recommend you tune acceptance or rejection of unqualified addresses on a port-by-port basis.

The DaemonPortOptions option u modifier (See this section), when set, has the same effect as declaring this feature for the given single port. That is, unqualified addresses are accepted on a port-by-port basis, without the need to declare this feature.

The DaemonPortOptions option f modifier (See this section), when set, tells sendmail to reject unqualified addresses received on this port, even if this feature is declared. That is, you accept unqualified addresses on all ports by declaring this feature, then reject them on a port-by-port basis with this f key word.

    Previous Section Next Section