The ucspi-tcp package contains a set of tools to accept, reject, or conditionally accept mail using rules that key on the IP address or rDNS of the remote site.[2] Some rules are locally defined and used only on a single host, while others are shared among multiple hosts. The standard way to handle shared rules is via DNS blacklists or blocklists (DNSBLs, either way). Local IP and rDNS rules are handled by tcpserver, using a rule file created by tcprules. This is the same rule file we set up in Chapter 8 to distinguish between local injection hosts and remote relay hosts. DNSBLs are handled by rblsmtpd, which runs between tcpserver and qmail-smtpd.
9.4.1 Using Local Filtering RulesLocal filtering rules go into the file that is used to build the CDB file used by tcpserver. If you set up your qmail system as suggested in Chapter 4, the CDB file is called /var/qmail/rules/smtprules.cdb, and the source from which it's built is /var/qmail/rules/smtprules.txt. To refuse mail connections from hosts that you never want to accept any mail from, use a deny line: 10.1.2.3:deny 10.20.96-127.:deny These rules reject connections from the single address 10.1.2.3 and the range 10.20.96.0 through 10.20.127.255. (Omitted components are considered to be wildcards and match any value.) You can also match on the rDNS name of a host. To reject connections from mail.imaspammer.com and any host whose rDNS ends with .dialup.badlyrunisp.net, use these lines: =mail.imaspammer.com:deny =.dialup.badlyrunisp.net:deny Each time tcpserver gets an incoming connection. It looks first for a rule with a name in the form IDENT@IP and IDENT@=rDNS, if it's retrieved IDENT data for the connection, it looks for IP, then =rDNS, then wildcard IPs, then wildcard rDNS, then just an equals sign if there's any rDNS, and finally, an empty catch-all rule. For example, if the host IP is 10.1.2.3, its rDNS is mail.myvirt.com, and the IDENT info is fred, it looks for these rules in this order: fred@10.1.2.3 fred@=mail.myvirt.com 10.1.2.3 =mail.myvirt.com 10.1.2. 10.1. 10. . =.myvirt.com =.com = (empty rule) If there's no IDENT info (there usually isn't), it doesn't look for the first two rules. If there's no rDNS, it doesn't look for any of the rDNS rules with equals signs. Note the three different catchalls: a single dot that matches any IP address, a single equals sign that matches any host that has rDNS, and an empty name that matches anything. The dot rule and empty name both match everything, with the difference being that the dot rule takes precedence over rDNS wildcards. (Or to put it another way, if there's a dot rule, it never looks at rDNS wildcards because the dot rule matches first.) The actions in the rules can be :allow or :deny. An :allow action can be followed by any number of environment variable assignments, separated by commas. A typical rules file has a few :allow rules with RELAYCLIENT for hosts on the local network that inject mail, a few IP-based :deny rules for hosts that send viruses or pure spam, often some rDNS :deny rules for IP ranges of retail dialup or broadband hosts that have sent nothing but viruses, and a catchall :allow rule. It's a bad idea to use rDNS-based :allow rules, because rDNS is technically easy to forge. If you're using POP-before-SMTP, described in Chapter 7, note that if an address has a :deny rule, tcpserver will summarily reject the connection, never giving the POP-before-SMTP program a chance. Fortunately, as we'll see in the next section, it's possible to use rblsmtpd to do the rejections in a way that makes POP-before-SMTP work: # allow relay from this host 127.:allow,RELAYCLIENT="" # allow relay from other hosts on this network 172.16.42.:allow,RELAYCLIENT="" 172.16.15-18.:allow,RELAYCLIENT="" # reject all connections from spam source 10.10.88.99:deny # reject connections from badly managed DSL pool =.dsl.ineptisp.com:deny # otherwise, allow connections but no relay :allow 9.4.2 Using DNSBLs and DNSWLsA rules file is a fine way to manage IP rejection rules for a single host. For a small network, it's practical to distribute copies of rules of CDB to all of the hosts using scp or rdist that need it. But to share a set of rules among hundreds or thousands of hosts, only a DNSBL will do. To use DNSBL, insert a call to rblsmtpd in between tcpserver and qmail-smtpd. Early versions of rblsmtpd could only check one DNSBL per invocation (dating from the era when Paul Vixie's RBL was the only DNSBL), but Version 0.88 checks any number, as shown in Example 9-1. Example 9-1. Running the SMTP daemon 1. #!/bin/sh 2. limit datasize 2m 3. exec \ 4. tcpserver -u000 -g000 -v -p -R \ 5. -x/var/qmail/rules/smtprules.cdb 0 25 \ 5a. rblsmtpd -b \ 5b. -ahul.habeas.com \ 5c. -rsbl.spamhaus.org \ 5d. -rcbl.abuseat.org \ 6. /var/qmail/bin/qmail-smtpd 2>&1 rblsmtpd either runs the next program in line, generally qmail-smtpd, if the DNSBLs and DNSWLs don't tell it to block mail from the connecting IP, or else turns into a tiny SMTP "rejection server" that only accepts HELO, EHLO, MAIL FROM, and QUIT, returning an error message to anything else. With any luck, the SMTP client on the other end passes the error message back to the sender so that a human sender realizes there's a problem and mailing list software takes the address off its list. The message can be prefixed by either a 451 code, a temporary error that tells the sender to try again later, or 553, a permanent error that tells the sender that it can't send mail to that address. It drops the connection after 60 seconds if the client hasn't already done so. Normally it gives a temporary rejection unless it's run with the --b flag, as in the previous example. (These days most rejections are for mail that you'll never want delivered, so there's no point in retrying.) To decide what to do, rblsmtpd first checks the environment variable RBLSMTPD that might have been set by tcpserver or the run script. If the variable is set to a null string, that's a whitelist entry so rblsmtpd runs the next program in the chain. If it's set to a string, RBLSMTPD runs the rejection server, using the string as the error message. If the string is prefixed with a hyphen, the rejection server gives permanent rather than temporary errors. In the absence of RBLSMTPD, it then goes through the list of --r and --a flags, checking each DNSBL or anti-DNSWL in turn. The argument to each --r or --a flag is the name of the list to check. If a DNSBL has a TXT entry for the IP in TCPREMOTEIP, it starts the rejection server. If an anti-DNSWL has an A entry for the IP, it runs the next program. If it gets to the end of the list of DNSBLs and anti-DNSWLs with no matching entries, it runs the next program. For the most part, you need to select only the DNSBLs you want to use, add them to your run file, and restart the SMTP daemon. Some of the DNSBLs I use in early 2004 include (all have web pages at the same address as the blocklist unless otherwise noted):
The one public DNSWL I currently use is the Habeas Users List. It requires a no-charge license agreement; see http://hul.habeas.com/services.html. The list of effective DNSBLs and DNSWLs changes every month or two, and some of these may no longer be available or may have been replaced by the time you read this. Sometimes you'll find that you want to override a few of the entries in one of the DNSBLs you use because they block mail from someone your users want to hear from. (If the listing is a mistake, most DNSBL maintainers take it out reasonably promptly, but your user will of course want it fixed right away.) rblsmtpd looks at the environment before it looks at any of the DNSBLs, so you can put override entries in your rules file. To whitelist an address, add an entry that sets RBLSMTPD to an empty string. To block an address with a rejection message, add an entry that makes the message the contents of RBLSMTPD: # accept mail from this address, overriding any DNSBL entries 10.20.1.2:allow,RBLSMTPD="" # send temporary rejections to this one 10.30.2.3:allow,RBLSMTPD="Please pay your bill to regain mail access" # reject this entirely 10.40.5.6:allow"RBLSMTPD="-All mail blocked due to pornographic spam". |