Sun Java System Messaging Server 6.3 Administration Guide

18.7.4 To Use DNS Lookups Including RBL Checking for SMTP Relay Blocking

In the Messaging Server, there are a number of different ways to ensure that all mail accepted for delivery or forwarding comes from an address with a valid DNS name. The simplest way is to put the mailfromdnsverify channel keyword on the tcp_local channel.

Messaging Server also provides the dns_verify program which allows you to ensure that all mail accepted for delivery or forwarding comes from an address with a valid DNS name using the following rule in ORIG_MAIL_ACCESS:


  TCP|*|*|*|*|SMTP*|MAIL|*|*@*|*|*  \
dns_verify,$7|$$y|$$NInvalid$ host:$ $$7$ -$ %e]

The line breaks in the above example are syntactically significant in such mapping entries. The backslash character is a way of legally continuing on to the next line.

The dns_verify image can also be used to check incoming connections against things like the RBL (Realtime Blackhole List), MAPS (Mail Abuse Prevention System, DUL (Dial-up User List), or ORBS (Open Relay Behavior-modification System) lists as another attempt to protect against UBE. As with the new mailfromdnsverify keyword, there’s also a separate “simpler to configure” approach one can use for such checks rather than doing the dns_verify callout. The simpler approach is to use the DNS_VERIFY_DOMAIN option in the dispatcher.cnf file. For example, in the [SERVICE=SMTP] section, set instances of the option to the various lists you want to check against:

! of normal options...

In this case, messages are rejected at the SMTP level, that is, the messages are rejected during the SMTP dialogue and thus never sent to the MTA. The disadvantage of this simpler approach is that it does the checks for all normal incoming SMTP messages including those from internal users. This is less efficient and potentially problematic if your Internet connectivity goes down. An alternative is to call out to dns_verify from a PORT_ACCESS mapping table or ORIG_MAIL_ACCESS mapping table. In the PORT_ACCESS mapping table, you can have an initial entry or entries that don’t check for local internal IP addresses or message submitters and a later entry that does the desired check for everyone else. Or, in an ORIG_MAIL_ACCESS mapping table, if you only apply the check on messages coming in the tcp_local channel then you’re skipping it for messages coming from your internal systems/clients. Examples using the entry points to dns_verify are shown below.


! Allow internal connections in unconditionally
  *|*|*|*|* $C$|INTERNAL_IP;$3|$Y$E
! Check other connections against RBL list
  TCP|*|25|*|* \
$C$[<msg-svr-base/lib/,dns_verify_domain_port,$1,\,Your$ host$ ($1)$ found$ on$ dnsblock$ list]$E


  TCP|*|25|*|*|SMTP*|*|tcp_local|*@*|*|*  \

For more information see: Performance Tuning Realtime BlockLists (RBL) Lookups.

The PORT_ACCESS table is probed both by the dispatcher, when accepting connections, and by the tcp_smtp_server process under certain circumstances.

tcp_smtp_server processes always check the PORT_ACCESS table for channels marked maysaslserver or mustsaslserver, and they will do it for all channels if bit 4 (value 16) of the LOG_CONNECTION in option.dat is set.

So if either of those are true, the customer needs to be aware that his PORT_ACCESS table is being processed twice for every connection. This may be a trivial overhead except that callouts to things like DNS RBLs or LDAP lookups can be relatively expensive in terms of their impact on SMTP server response time. For this reason, you want to avoid doing them any more than necessary. That is one reason the callout in the example above is coded after the INTERNAL_IP lookup. If the SMTP client is in your INTERNAL_IP table, then you allow the connection without doing the RBL lookup. Reversing that order would mean your local clients would be delayed by RBL lookups. To prevent doing this twice, add a check for one the flags set by dispatcher or tcp_smtp_server so that you only process that table entry when one of those is set or not. For example, add $:Ato the entry:

TCP|*|25|*|*   \
$C$:A$[<msg-svr-base/lib/,dns_verify_domain_port,$1,\,Your$ host$ ($1)$ found$ on$ dnsblock$ list]$E

We added the $:A after the $C so the table processing will continue down the table if this does not match. The $:A specifies that this entry be processed only if it is being done by the dispatcher, that is, not when done by tcp_smtp_server. Alternatively, if you wanted to cause it to be done only in tcp_smtp_server, check for S instead:

TCP|*|25|*|*   \
$C$:S$[<msg-svr-base/lib/,dns_verify_domain_port,$1,\,Your$ host$ ($1)$ found$ on$ dnsblock$ list]$E

The negative check would be $;A to check that A is not set, or $;S to check that S is not set. Support for DNS-based Databases

The dns_verify program supports DNS-based databases used to determine incoming SMTP connections that might send unsolicited bulk mail. Some of the publicly available DNS databases do not contain TXT records that are typically used for this purpose. Instead, they only contain A records.

In a typical setup, the TXT record found in the DNS for a particular IP address contains an error message suitable to return to the SMTP client when refusing a message. But, if a TXT record is not found and an A record is found, then versions of dns_verify prior to Messaging Server 5.2 returned the message “No error text available.

dns_verify now supports an option that specifies a default text that is used in the event that no TXT record is available. For example, the following PORT_ACCESS mapping table shows how to enable this option:


   *|*|*|*|* $C$|INTERNAL_IP;$3|$Y$E  \
   TCP|*|25|*|*   \
$C$[<msg-svr-base/lib/ \
,dns_verify_domain_port,$1,,Your$ host$ ($1)$ \
found$ on$ dnsblock$ list]$E 

In this example, if the remote system is found in a query in the domain, but no TXT record is available, then the following message is returned, “Your host a.b.c.d found on dnsblock list.