Running mail server sounds sometimes easier as it is. There is one particular nasty thing which can happen from time to time to any mail server administrator. Your mail server is rejected by delivering mails for the reason you got on a DNS-based Real-time Blackhole List (DNSRBL). One goal of this blackhole lists was to create a dictionary with open-relay mail servers which are known to send spam. If your mail server is registered on such a blackhole list, there is a good chance you have a degraded mail service.
As the name DNS-based says, the list is build as a DNS zone and is maintained by the DNSRBL provider. For example your mail server receives a connection, you can check first if the clients address isn’t registered on a DNSRBL. Based on this information you can decide to accept or reject the connection.
Your got a connection to your mail server from a client with the IP address let’s say
126.96.36.199. The mail server checks first for example the blackhole list from SpamCop. The mail server builds a specific DNS query with the reversed IP address and appends the domain of the DNSRBL provider. The DNS query will look like the following
~ % host -a 188.8.131.52.bl.spamcop.net
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51340
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;184.108.40.206.bl.spamcop.net. IN ANY
;; ANSWER SECTION:
220.127.116.11.bl.spamcop.net. 2100 IN A 127.0.0.2
18.104.22.168.bl.spamcop.net. 2100 IN TXT "Blocked - see http://www.spamcop.net/bl.shtml?22.214.171.124"
Received 134 bytes from 126.96.36.199#53 in 16 ms
If this DNS lookup returns an A record with
127.0.0.2 the mail server is listed on the blackhole list, if the query returns nothing, the server is good to go. Some provider have also a TXT record with an URL which tells you why the server is registered on the list.
Being responsible for a mail server it is helpful to know, if your mail server is registered on such blackhole lists. For this reason there are tons of websites where you can check if an IP address is registered, e.g. http://dnsbl.info. If you have many mail servers you maybe want a more sophisticated way. The test itself is a very simple DNS lookup and can easily done by a script. I’ve created a Groovy script which runs inside the Bean Scripting Framework Monitor (BSFMonitor) of OpenNMS. To have a shorter script execution run time, I’ve used a thread pool to run DNS queries in parallel. It allows quite effectively to test over 50 DNSRBL provider. A few of them have very slow response times so you need to tweak the
timeout parameter for the script. To save resources I run the test every two hours. The service goes down as soon one of the DNSRBL provider has listed the IP address.
Service down for SPAM-Blacklist-Monitor
The service down event gives a list with all DNSRBL provider
which have the IP address in their blackhole list, so you can start to get in contact with them and dealing with their policies.
The configuration is not very complicated. The Groovy script is copied to
The monitor configuration in
poller-configuration.xml has to look like this
<filter>IPADDR != '0.0.0.0'</filter>
<include-range begin="188.8.131.52" end="254.254.254.254"/>
<include-range begin="::1" end="ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"/>
<service name="SPAM-Blacklist-Monitor" interval="7200000" user-defined="true" status="on">
<parameter key="file-name" value="/etc/opennms/scripts/SpamBlackListMonitor.groovy"/>
<parameter key="lang-class" value="groovy"/>
<parameter key="bsf-engine" value="org.codehaus.groovy.bsf.GroovyEngine"/>
<parameter key="run-type" value="exec" />
<parameter key="retry" value="1" />
<parameter key="timeout" value="60000" />
<parameter key="file-extensions" value="groovy,gy"/>
<parameter key="rrd-repository" value="/opt/opennms/share/rrd/response"/>
<parameter key="rrd-base-name" value="dnsrbl"/>
<downtime interval="30000" begin="0" end="300000"/>
<!-- 30s, 0, 5m -->
<downtime interval="300000" begin="300000" end="43200000"/>
<!-- 5m, 5m, 12h -->
<downtime interval="600000" begin="43200000" end="432000000"/>
<!-- 10m, 12h, 5d -->
<downtime begin="432000000" delete="true"/>
<!-- anything after 5 days delete -->
<monitor service="SPAM-Blacklist-Monitor" class-name="org.opennms.netmgt.poller.monitors.BSFMonitor"/>
I've created a specific poller package which has a different RRD configuration which fits to my polling interval for 2 hours. I don't have set any special IP filters, I assign the monitor by myself, so it will only run on the IP interfaces which have the service assigned. After restarting OpenNMS to load the new monitor, I assign the service SPAM-Blacklist-Monitor to my mail servers IP address I want to check. I’ve set the timeout to 60 seconds and repeat the test every 2 hours, which was in my case fast enough. The response time will be recorded as the total run time of the script, so you can see if your timeout configuration is good enough. So feel free to play. You can find the Groovy script on Github opennms-bsf-scripts repository. If you have any improvements and feedback, you’re welcome.
Are there any drawbacks of the solution using a Groovy Script with BSFMonitor? Yes, there is, the BSFMonitor has to read the script from the hard disk every time the monitor is executed. Before the script is executed the Groovy Script has also to be compiled to byte code, in this specific case additional ~1.3 seconds of CPU time. If you run this test thousands of times, it would be more efficient to implement this monitor in native Java. The good thing is, you can change the script by add or remove DNSRBL provider without restarting OpenNMS. Even being able to run the Script in the native JVM allows a more effective way to use threads instead of scripts using
fork(). I have also direct access to the OpenNMS logging framework and data structures.
Doing the name lookup, I've used the native Java method of
InetAddress.getByName(). In the Java Virtual Machine (JVM) you may have to deal with the JVM DNS caching policies which can be modified with the following JVM parameter
networkaddress.cache.ttl (default: -1)
Indicates the caching policy for successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the successful lookup. A value of -1 indicates "cache forever".
networkaddress.cache.negative.ttl (default: 10)
Indicates the caching policy for un-successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the failure for un-successful lookups.
A value of 0 indicates "never cache". A value of -1 indicates "cache forever".
So long and thanks for all the fish ...