Checking a Domain Against the Spamhaus DBL in PHP

Fellow LockerGnome writer Craighton came to me early on Sunday with a problem. Craighton runs a little URL shortening service called ou.gd, and needed some help adding a blacklist checker to the service. This was a major issue, as his Web host was threatening to cut off his services if he did not (which makes sense, as no one wants to get caught hosting spam links). So, Craighton asked for my assistance in checking submitted URLs against the Spamhaus Domain Block List (DBL). This way, when a user submits a bad URL to the shortening service, the service knows whether or not to reject the blocked domain, ensuring the integrity of the service as well as users who click links generated by it.

The Spamhaus site was a bit difficult to navigate for information at first, but once I located the FAQ, I was able to get the information I needed to sort out this issue. The Spamhaus DBL service is fairly straightforward to use: send a request with the domain you want to check prepended to the Spamhaus hostname and check the response you receive back. The issue is, you are querying a domain nameserver, not a Web server, so the right way to go about this in PHP is not exactly straightforward. How often do you make DNS queries from a Web service, right?

I dug around a bit, and found that PHP had a nifty function built in called dns_get_record(). This function sends a DNS query for a record with the provided hostname. The result is an array filled with the record details. For example, if I were to query the DNS record for lockergnome.com, I would do the following:


$lg_record = dns_get_record("lockergnome.com")
print_r($lg_record);


/*
Output:
Array
(
[0] => Array
(
[host] => lockergnome.com
[type] => A
[ip] => 205.186.156.168
[class] => IN
[ttl] => 266
)
[1] => Array
(
[host] => lockergnome.com
[type] => NS
[target] => ns7.zoneedit.com
[class] => IN
[ttl] => 1916
)
[2] => Array
(
[host] => lockergnome.com
[type] => NS
[target] => ns1.zoneedit.com
[class] => IN
[ttl] => 1916
)
)
*/

Pretty cool, huh? Now, checking a domain against the Spamhaus DBL is just as simple. In fact, I wrote a little sample to demonstrate to Craighton and published it as a GitHub Gist, so here it is for your viewing pleasure:
Powered by Wordpress Plugins - Get the full version!

Basically, if the array that gets returns by dns_get_record() is empty, then Spamhaus does not have the specified domain in its block list. So if Craighton’s URL shortener were to pass whatever URL a user submits through Spamhaus and it came back with an empty array, it could then be assumed that the URL is “safe” and a shortened URL can be created for it. This is a big security point for URL shorteners everywhere, no doubt.

And with that, Craighton’s URL shortener is that much safer. In addition, his Web host is that much more relieved that the site it is hosting is in the green and clear. Best of all, it is all thanks to Yours Truly.

Hopefully this helps in locking down the Web apps and services of other LockerGnome readers. Cheers!

Article Written by

  • Tweeksy

    Might be a stupid question, but does this require you to set php.ini to specify Spamhaus as your DNS server?

    If it is a stupid question, than I put it down to a lack of Red Bull ;)

  • Rodrigo Polo

    I have tried this code without succes… it requires any special setup?

    • http://eddieringle.com Eddie Ringle

      In order to test against the DBL you must query Spamhaus’ service. the dns_get_record() function alone won’t work. In order to query the DBL you must append “.dbl.spamhaus.org” to the domain you want to test. For example, to check “lockergnome.com” against the DBL, I would pass “lockergnome.com.dbl.spamhaus.org” along to the dns_get_record() function.

  • Peter Craddock

    I’ve found that the second “if” statement should read as follows:

    if (empty($dbl_record) || ($dbl_record != NULL && count($dbl_record) == 0))

    otherwise I got false positives with items not listed.

    Thanks for the code – I’ll be trying it both for a URL shortener & as part of anti-spam e-mail validation.

  • Ozh

    This example DOES NOT WORK. You’re just fetching DNS records. Every domain has DNS records. Nowhere in your code you are checking against Spamhaus or any other black list.