We were about to simply start over when we found that Yiorgos Adamopoulos had rewritten an early (but cleaner) version to use the ADNS library instead of the standard DNS resolvers. He had done this as an exercise, but the code was clean and looked to be a much better place to start. We used his code as a base for what amounts to nearly a complete rewrite.
Quick Links
Our favorite blocklist is the Open Relay Database, which lists IP addresses of computers known to be open relays. Being an open relay is highly correlated with being a middleman for spam, and we've found that rejecting mail from these servers not only reduces our spam load, but also creates an incentive on the open relay owners to secure their computers. We love ORDB.
There are plenty of other lists of varying utility and rates of adoption, but the benefits and drawbacks of any individual list are beyond the scope of this document. Here, we're only concerned about how to query a list, not evaluate it.
All of the blocklists we're talking about use DNS as their lookup mechanism: the IP address of the connecting server is converted into a domain name, and this name is used in a standard DNS name lookup. These are always based on the IP address of the sender, not on any part of the email envelope (such as From: or To: lines).
For instance, to perform an ORDB lookup of the mailserver located at 63.203.17.35 involves a DNS query of 35.17.203.63.relays.ordb.org looking for an A (address) resource record. If there is no such record, then this IP address is not "on the list", so the connection should be accepted. Note that the four octets of the IP address are reversed, à la the in-addr.arpa mechanism.
One can do this "by hand" with the dig command and the long domain name, and we'll show some examples here. The first is a random site that's known to be an open relay (at the time of testing), followed by one of our own mailservers:
The actual value of the answer (here, it's 127.0.0.2) is not always interesting because it's the presense of a response, not the value of the response that is meaningful. An IP address is used because that's the only thing that a query for an "A" record can return, and one return value is as good as any other.$ dig +short 130.119.226.159.relays.ordb.org A random open relay 127.0.0.2 it's in the list $ dig +short 35.17.203.63.relays.ordb.org A our mail server no reply: not in the list $
But some blocklists have different responses for different reasons, so knowing just which response was given might be interesting. An example is NJABL, which has a small table of possible return values: 127.0.0.2 is for open relays, 127.0.0.3 is for dialup ranges (these systems should be their ISP's SMTP servers), 127.0.0.4 for known spam sources, and a few others.
Each DNSBL can have its own sets of meanings, but any answer means that the IP being queried is "in the list". Consult the particular DNSBL documentation for the meaning - if any - of the returned values.
An effect of this behavior is that queries to lists that no longer exist (or to lists whose names have simply been misspelled) are not reported as any kind of error. This suggests that these incorrect queries could stick around for a long time, giving an inappropriate sense of confidence in the non-spam-ness of the incoming connections, not to mention the waste of resources asking questions that won't ever get an interesting answer.
Fortunately, there seems to be a de facto standard for asking "is this a valid DNSBL?", and that involves making a query for the IP address 127.0.0.2. This should always return an "it's on the list" value, and it can be done to verify that a particular DNSBL is working or not.
When arblcheck is run without command-line arguments, it reports a short "help" listing that summarizes the options available, which are expanded.
-h | Show a brief help listing, then exit. |
-v | Show the program's version information, then exit. |
-l | Display the current list of DNSBL sites that will be queried. The program has a compiled-in list that's initialized at startup, but this list can be modified by command-line arguments. The list displayed is the list in effect at the time the -l parameter is encountered. |
-c | Clear the current list of DNSBL sites to query, rendering it empty. This presumes that the -s option will be used to add new DNSBL sites to the list later. |
-s SITE | Add SITE to the current list of DNSBL sites to query. |
-f | Only show "filtered" results: do not generate any output for "not in the list" responses. |
This program has three kinds of exits:
2003-10-21 1.4.1 -- Initial release of rewritten code.