Querying Spamhaus for IP reputation

Published: 2021-04-16
Last Updated: 2021-04-17 03:07:21 UTC
by Rick Wanner (Version: 1)
0 comment(s)

Way back in 2018 I posted a diary describing how I have been using the Neutrino API to do IP reputation checks.  In the subsequent 2+ years that python script has evolved some which hopefully I can go over at some point in the future, but for now I would like to show you the most recent capability I added into that script.

As most of you know, The Spamhaus Project has been forefront in the fight against Spam for over 20 years. But did you know they provide a DNS query based api that can be used, for low volume non-commercial use, to query all of the Spamhaus blocklists at once. The interface is zen.spamhaus.org. Because it is DNS query based you can perform the query using nslookup or dig and the returned IP address is the return code.

For example say we want to test whether or not is on a Spamhaus list.  First because the interface takes a DNS query we would need to reverse the IP address and then add .zen.spamhaus.org.  i.e. the DNS query would look like

$ nslookup

Non-authoritative answer:

or with dig...

$ dig

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.4 <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64622
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 4096
;    IN   A


As you can see in both cases the DNS response returned two results. and  In practicality just the fact that you receive return codes tells you that this IP is on Spamhaus's lists, and has recently been involved in naughty behavior. However to know which Spamhaus lists in particular the return codes apply to:

Return Code	Zone	Description	SBL	    Spamhaus SBL Data	SBL	    Spamhaus SBL CSS Data	XBL	    CBL Data	SBL	    Spamhaus DROP/EDROP Data	PBL	    ISP Maintained	PBL	    Spamhaus Maintained

If you query an IP which is not on any Spamhaus lists the result will be Non-Existent Domain (NXDOMAIN)


** server can't find NXDOMAIN

I have created a Python script which performs this lookup and have integrated this code into my ip reputation script. 

$ python3 queryspamhaus.py ['SBL']
$ python3 queryspamhaus.py 0 ['Not Found']

The script does have a bug.  The socket.gethostbyname() function only returns one result, so is returning an incomplete result for IPs which are on multiple Spamhaus lists. Since usually all I am looking for is if the IP is on any list I have never bothered to research how to fix this bug.

For those of you who are interested, the script is below.  As usual, I only build these scripts for my own use/research, so a real python programmer could very likely code something better.

# queryspamhaus.py

import os
import sys, getopt, argparse
import socket

def check_spamhaus(ip):
    hostname = ".".join(ip.split(".")[::-1]) + ".zen.spamhaus.org"
       result  = socket.gethostbyname(hostname)
    except socket.error:
       result = 0

    rdict = {"": ["SBL"],
             "": ["SBL CSS"],
             "": ["XBL"],
             "": ["XBL"],
             "": ["XBL"],
             "": ["SBL"],
             "": ["PBL"],
             "": ["PBL"],
             0 : ["Not Found"]

    return result, rdict[result]

def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('IP', help="IP address")

   result,tresult  = check_spamhaus(ip)
   print('{} {} {}'.format(ip, result, tresult))


-- Rick Wanner MSISE - rwanner at isc dot sans dot edu - Twitter:namedeplume (Protected)

Keywords: Spamhaus
0 comment(s)


Diary Archives