ProblemYou have been asked to configure sendmail to route mail for entire virtual domains, not just individual hosts . SolutionThe domain administrator must register each virtual mail domain with an official DNS registrar. The DNS administrator must also create a minimal zone file for each virtual mail domain. In addition to the basic records required to create a zone file, the file must contain MX records that point to the mail exchanger that you are configuring. See DNS and BIND , by Paul Albitz and Cricket Liu (O'Reilly), for more information on DNS configuration. On the mail server, create a /etc/mail/ virtuser -domains file that lists each virtual mail domain for which service will be provided. Create an /etc/mail/virtusertable text file that defines the routing for each virtual mail domain. Use makemap to build a hash type database from the text file. Next , create a sendmail configuration that enables the virtusertable feature, loads class $={VirtHost} from the /etc/mail/virtuser-domains file, and enables the virtuser_entire_domain feature. Here are examples of the lines that need to be added to the sendmail configuration: dnl Use the virtusertable for mail routing FEATURE(`virtusertable') dnl Load $={VirtHost} from a file VIRTUSER_DOMAIN_FILE(`/etc/mail/virtuser-domains') dnl Interpret the values in $={VirtHost} as domain names FEATURE(`virtuser_entire_domain') As shown in Recipe 1.8, rebuild and install the sendmail.cf file, and restart sendmail. DiscussionAssume that the zone files created for the shop.wrotethebook.org , school.ora.com, and hotel.example.com domains all contain MX records that route email to mail.wrotethebook.com . The mail.wrotethebook.com host will reject that mail unless the destination hostname is listed in class $=w or class $={VirtHost} . The configuration described in the Solution section loads the $={VirtHost} class from the /etc/mail/virtuser-domains file specified by the VIRTUSER_DOMAIN_FILE macro. Here is a sample virtuser-domains file containing the names of three virtual mail domains: # cat /etc/mail/virtuser-domains shop.wrotethebook.org school.ora.com hotel.example.com Values stored in class $={VirtHost} are replicated in class $=R , as this simple test shows: # sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > $={VirtHost} shop.wrotethebook.org school.ora.com hotel.example.com > $=R shop.wrotethebook.org school.ora.com hotel.example.com > /quit By default, values in class $=w and class $={VirtHost} are interpreted as hostnames. Values in class $=R , on the other hand, are interpreted as domain names. Use the virtuser_entire_domain feature to cause the values in class $={VirtHost} to also be interpreted as domain names. The virtuser_entire_domain feature tells sendmail to evaluate class $=R and class $={VirtHost} in an equivalent manner ”every host in every domain listed in class $=R is accepted for processing by the local host, and every host in every domain in class $={VirtHost} is matched against the virtusertable . Here is a sample virtusertable we'll use to illustrate this: # cat > /etc/mail/virtusertable @mainst.shop.wrotethebook.org logan @mall.shop.wrotethebook.org pat @retro.shop.wrotethebook.org reba @school.ora.com %1@b2341.isp.wrotethebook.net @sales.school.ora.com jeff+sales@b2341.isp.wrotethebook.net @info.school.ora.com jeff+info@b2341.isp.wrotethebook.net @motel.hotel.example.com reservations@b0021.isp.wrotethebook.net @lodge.hotel.example.com reservations@b0531.isp.wrotethebook.net @hotel.hotel.example.com reservations@b1088.isp.wrotethebook.net Ctrl-D # makemap hash /etc/mail/virtusertable < /etc/mail/virtusertable The first three entries route mail addressed to anyone on the three hosts in the shop.wrotethebook.org domain to the local user accounts where the mail addressed to these virtual hosts is read. school.ora.com and hotel.example.com both run their own servers, but the servers are literally part of the isp.wrotethebook.net domain. school.ora.com has only one server. hotel.example.com has three servers ”one at the motel, one at the lodge, and one at the hotel. Notice that school.ora.com uses + detail syntax to identify the specific mailbox in the jeff account where the mail should be stored. For this to work, the jeff account on b2341.isp.wrotethebook.net must have a mail filter that processes the + detail syntax. A few tests of this recipe's configuration show the impact of the virtuser_entire_domain feature and the virtusertable entries: # sendmail -bv info@mall.shop.wrotethebook.org info@mall.shop.wrotethebook.org... deliverable: mailer local, user pat # sendmail -bv cranks@sales.school.ora.com cranks@sales.school.ora.com... deliverable: mailer esmtp, host b2341.isp. wrotethebook.net., user jeff+sales@b2341.isp.wrotethebook.net # sendmail -bv reservations@lodge.hotel.example.com reservations@lodge.hotel.example.com... deliverable: mailer esmtp, host b0531.isp. wrotethebook.net., user reservations@b0531.isp.wrotethebook.net None of the hostnames in the three test addresses shown above are listed in either class $=w or $={VirtHost} . Yet all three addresses are clearly rewritten by the virtusertable . This is the effect of the virtuser_entire_domain feature ”these hostnames are processed through the virtusertable because they belong to domains listed in the $={VirtHost} class. Potential conflicts and solutionsHowever, the virtuser_entire_domain feature does not change the way that the keys in the virtusertable are interpreted. There is no domain wildcard for the virtusertable . Each hostname in the test above is rewritten because it exactly matches a key in the database. A common mistake is to think that an entry like @school.ora.com applies to every host in the school.ora.com domain because the virtuser_entire_domain feature is used. A test shows this is not the case: # sendmail -bv dave@school.ora.com dave@school.ora.com... deliverable: mailer esmtp, host b2341.isp.wrotethebook.net., user dave@b2341.isp.wrotethebook.net # sendmail -bv dave@hs.school.ora.com dave@hs.school.ora.com... deliverable: mailer esmtp, host hs.school.ora.com., user dave@hs.school.ora.com Both of the recipient addresses shown above are in a domain listed in $={VirtHost} and the virtuser_entire_domain feature is enabled. For these reasons, both of these addresses are matched against the virtusertable . But only the first address matches a key found in the database and is rerouted. The other address goes through the normal delivery process, and therein lies a possible conflict with the domain administrator. Some domain administrators use wildcard MX records that match any hostname within a given domain. The wildcard MX makes things easy for the domain administrator but has the potential to cause problems for the sendmail administrator. The sendmail -bv test of dave@hs.school.ora.com shows the problem. Mail addressed to hs.school.ora.com is accepted by the local host for processing because the school.ora.com domain is listed in class $=R , which means that the local host will relay mail for this domain. The hs.school.ora.com address is not modified by the virtusertable process, so the local host attempts to deliver the mail via the esmtp mailer directly to a host named hs.school.ora.com . When the local host does a DNS lookup of hs.school.ora.com , the lookup succeeds because this host is covered by the MX wildcard. The MX record returned by the lookup points the local host right back to the local host. Problem! This problem can be avoided in a few different ways. All three solutions work, and all have different advantages and disadvantages. While the first solution is preferred, the solution you choose depends on your personal situation. The three solutions are:
The catchall solutionBelow, we define catchall entries in the mailertable to avoid the possible delivery problems that would be caused if the domain administrator used wildcard MX records in our sample virtual mail domains. First, add mailertable support to the basic Recipe 5.7 configuration: dnl Use the virtusertable for mail routing FEATURE(`virtusertable') dnl Load $={VirtHost} from a file VIRTUSER_DOMAIN_FILE(`/etc/mail/virtuser-domains') dnl Interpret the values in $={VirtHost} as domain names FEATURE(`virtuser_entire_domain') dnl Use the mailertable to invoke special mailers FEATURE(`mailertable') Create the virtusertable database and the virtuser-domains file as described above. Create a mailertable with a catchall entry for each of the virtual mail domains: # cat > /etc/mail/mailertable .school.ora.com error:5.3.0:553 Invalid hostname shop.wrotethebook.org error:5.3.0:553 Invalid hostname .shop.wrotethebook.org error:5.3.0:553 Invalid hostname hotel.example.com error:5.3.0:553 Invalid hostname .hotel.example.com error:5.3.0:553 Invalid hostname Ctrl-D # makemap hash /etc/mail/mailertable < /etc/mail/mailertable The first entry addresses the specific problem described in the example above. The next two entries provide similar error control for the shop.wrotethebook.org virtual mail domain, and the last two entries provide the protection for the hotel.example.com virtual mail domain. The additional entries for the shop.wrotethebook.org and hotel.example.com domains are necessary because, unlike the school.ora.com domain, neither of these other domains has a virtusertable entry that routes mail addressed to user @ domain , as this test of this recipe's basic configuration shows: # sendmail -bv jane@shop.wrotethebook.org jane@shop.wrotethebook.org... deliverable: mailer esmtp, host shop.wrotethebook.org., user jane@shop.wrotethebook.org # sendmail -bv kathy@hotel.example.com kathy@hotel.example.com... deliverable: mailer esmtp, host hotel.example.com., user kathy@hotel.example.com # sendmail -bv sara@school.ora.com sara@school.ora.com... deliverable: mailer esmtp, host b2341.isp.wrotethebook.net., user sara@b2341.isp.wrotethebook.net mailertable entries that begin with a dot are partial domain names that match any address that ends with the specified domain name. For example, a mailertable entry beginning with .wrotethebook.com would match addresses of the form user @ host .wrotethebook.com . Full domain names (those that do not start with a dot) match mail addressed in the form of user @ domain . Therefore, a mailertable entry starting with ora.com would match craig @ora.com but not craig@tcp.ora.com . These catchall mailertable entries are only applicable to virtual mail domains and are only useful if the zone files for those domains use wildcard MX records. If these were real domains, the virtusertable entry might route mail from one host in the domain to another in the same domain. The rewritten address would then be caught by the mailertable catchall entry, and the "invalid hostname" error would be returned. Because these are virtual mail domains with no physical existence, the virtusertable never routes mail to a host in these nonexistent domains. Thus, addresses rewritten by the virtusertable do not match the catchall entries and are allowed to continue on their way as directed by the virtusertable . These catchall entries are useful, but only for the specific problem described here. Run some tests with the new configuration to see the impact of these mailertable entries: # sendmail -bv -C recipe5-7a.cf dave@hs.school.ora.com dave@hs.school.ora.com... Invalid hostname # sendmail -bv -C recipe5-7a.cf dave@school.ora.com dave@school.ora.com... deliverable: mailer esmtp, host b2341.isp.wrotethebook.net., user dave@ b2341.isp.wrotethebook.net # sendmail -bv -C recipe5-7a.cf jane@mall.shop.wrotethebook.org jane@mall.shop.wrotethebook.org... deliverable: mailer local, user pat # sendmail -bv -C recipe5-7a.cf jane@shop.wrotethebook.org jane@shop.wrotethebook.org... Invalid hostname These tests show that addresses that match keys in the virtusertable are still being properly rewritten, while addresses in the virtual mail domain that do not have entries in the virtusertable are now being properly identified as addressing errors. Catchall entries are useful, but they should be used with caution and be thoroughly tested to ensure that they don't catch things that they shouldn't. All of this work could, of course, be avoided if the domain administrator did not use wildcard MX records. The best solution to this potential problem is to avoid wildcards and use individual MX records. See AlsoRecipe 5.6 defines individual virtual hosts, as opposed to virtual mail domains, and should be evaluated as an alternative before implementing this recipe. Recipe 5.1 through Recipe 5.4 and this chapter's Introduction provide additional information about the mailertable . The sendmail book covers the virtusertable in Section 4.8.51. MX records and DNS are covered in DNS and BIND , by Paul Albitz and Cricket Liu (O'Reilly), and in TCP/IP Network Administration , by Craig Hunt (O'Reilly). |