Skip to main content

Client library for querying SURBL and other RBL blocklists.

Project description

surblclient

A small client library for querying SURBL, URIBL, and other RBL-style blocklists over DNS.

Give it a domain (or URL host, or IP address) and it tells you whether the domain is listed, and on which sub-lists.

Installation

uv add surblclient

Or, from a checkout:

uv pip install .

Usage

>>> from surblclient import surbl
>>> "test.surbl.org" in surbl
True
>>> surbl.lookup("test.surbl.org")
('test.surbl.org', ['ph', 'mw', 'abuse', 'cr'])
>>> "google.com" in surbl
False

lookup resolves the base domain before querying, so subdomains work too:

>>> surbl.lookup("foo.bar.baz.test.surbl.org")
('test.surbl.org', ['ph', 'mw', 'abuse', 'cr'])

It returns a (base_domain, lists) tuple on a hit, False when the domain is confirmed not listed, and None when the answer is unknown — a temporary DNS error, or the service refusing the query (see below).

The same interface is available for URIBL:

>>> from surblclient import uribl
>>> "test.uribl.com" in uribl
True

Note that in can only return a bool, so it collapses the None (unknown/refused) case into False. If you need to distinguish "not listed" from "couldn't check", use lookup() and test for None:

result = surbl.lookup(domain)
if result is None:
    ...        # unknown — do NOT treat as clean (often a blocked resolver)
elif result is False:
    ...        # confirmed not listed
else:
    base, lists = result   # listed

Resolver requirements

SURBL and URIBL refuse queries that arrive via public/shared DNS resolvers (Google Public DNS, OpenDNS, Cloudflare, and most ISP caching resolvers) and rate-limit heavy users. A refused query comes back as 127.0.0.1, which this library reports as None (unknown) — so on a public resolver every lookup silently returns "unknown" and the library can't do its job.

This is the services' documented anti-abuse policy, not a bug in this library:

  • URIBL — "All queries that we refuse, we return a 127.0.0.1 response to … Public DNS providers such as OpenDNS or Google Public DNS are effected due to the high volume of queries they generate, as are many other internet service providers (ISP) that use caching nameservers …" (uribl.com/refused.shtml)
  • SURBL — "If you get a result of 127.0.0.1 when doing a DNS query into the public nameservers, then it means your access is blocked … A good administrative solution is to run a local caching nameserver …" (surbl.org/faq/guidelines)

To use this library reliably, run your own recursive resolver (e.g. unbound) on the machine doing the checks and point it at the DNS roots, then resolve through 127.0.0.1. High volume use needs a data feed / datafeed instead of the public DNS mirrors; the free public service has usage limits (broadly, fewer than 1,000 users or 250,000 messages/day).

Development

This project is managed with uv.

uv sync                      # set up the environment
uv run python -m unittest -v # run the tests (mocked; no network)
uv build                     # build the wheel and sdist

The default test run mocks DNS, so it is deterministic and offline. The live integration tests in tests/test_live.py hit the real services and are skipped unless you opt in — and they only pass through a non-public resolver (see Resolver requirements):

SURBL_LIVE_TESTS=1 uv run python -m unittest -v

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

surblclient-0.2.0a1.tar.gz (77.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

surblclient-0.2.0a1-py3-none-any.whl (79.4 kB view details)

Uploaded Python 3

File details

Details for the file surblclient-0.2.0a1.tar.gz.

File metadata

  • Download URL: surblclient-0.2.0a1.tar.gz
  • Upload date:
  • Size: 77.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for surblclient-0.2.0a1.tar.gz
Algorithm Hash digest
SHA256 8c97f929bd1c2c534e5a1a61514ebfc3742864f462a1ef79b274d0aac0a01643
MD5 0671ebf3d424e1c7e8fd00a398e0eb56
BLAKE2b-256 c36b79fb8340d1321b0cb04bec9a93c4cbe24d43b490f782c6af29c05d3ed1a5

See more details on using hashes here.

File details

Details for the file surblclient-0.2.0a1-py3-none-any.whl.

File metadata

  • Download URL: surblclient-0.2.0a1-py3-none-any.whl
  • Upload date:
  • Size: 79.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for surblclient-0.2.0a1-py3-none-any.whl
Algorithm Hash digest
SHA256 9ae3d984427a70a63a578ff19813e97a920b4e25a1840e452a8e64183147c1fd
MD5 695e29a8e054c02d06ed9ed905ad3daf
BLAKE2b-256 c3df63ea5a6f56a84579f1909c3003cfe418da6d40c38ea93eb1a89f76446e8f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page