Skip to main content

DNS blocklists

A DNS blocklist (DNSBL) answers one question over DNS: is this address listed? Ask 4.3.2.1.bl.spamcop.net, and an answer means 1.2.3.4 is listed, no answer means it is not. The WAF asks through @rbl:

SecRule REMOTE_ADDR "@rbl bl.spamcop.net" "id:10002,phase:1,deny,status:403,msg:'listed by SpamCop'"

Any zone that follows the convention works. ipv4 addresses are reversed octet by octet, ipv6 ones nibble by nibble, as RFC 5782 describes.

The engine never waits on DNS​

Rule evaluation is synchronous, and a DNS query is not. So the two are kept apart:

  1. Before evaluating, the WAF plugin reads the zones its rules name, and asks about the caller for each one it has no answer for.
  2. It waits for those answers at most reputation.rbl.wait-millis (100 ms by default). A blocklist that answers in time decides this request; one that does not decides the next ones, since the query carries on and its answer is cached.
  3. During evaluation, @rbl reads that cache and nothing else.
AnswerCached forCounts as
Listed (127.0.0.0/8)listed-ttl-seconds, 15 minlisted
Not listed (no such name)unlisted-ttl-seconds, 5 minnot listed
An error code, or an answer outside 127.0.0.0/8unlisted-ttl-secondsnot listed
No answer within timeout-milliserror-ttl-seconds, 30 snot listed

A blocklist that cannot be reached never blocks anyone. Concurrent questions about one address share one query, and the resolver runs on a thread of its own, so a blocklist that stops answering costs requests at most the wait, never a thread.

A zone written with a macro — @rbl %{tx.zone} — is only known during evaluation, so it cannot be asked about beforehand: its first request from an address is judged without the answer.

Public resolvers, and why Spamhaus says no​

Most blocklists refuse queries that come through public resolvers (Google, Cloudflare, Quad9…), and many cloud nodes use one without anyone choosing it. They do not all refuse the same way:

  • Spamhaus answers 127.255.255.254. That is an error code, not a listing, and is counted as such: an address in 127.255.255.0/24 never counts as listed.
  • Through some resolvers, Spamhaus answers "no such name" to everything. On any single lookup, that is indistinguishable from "not listed".

The second case is why every zone is checked. RFC 5782 requires every blocklist to list 127.0.0.2, so the resolver asks about it the first time a zone is used, and every ten minutes after that. A zone that does not list its own test entry is reported as unhealthy in /_status (rbl.zones), with the reason, and once an hour in the logs.

The fix is to ask through a resolver of your own: point reputation.rbl.nameservers at it, or at the name servers your provider gives you. Some resolvers also answer a miss with the address of a search page. Those answers fall outside 127.0.0.0/8, so they are never counted as listings either.

Project Honey Pot​

http:BL puts an access key in front of the address. Set it in reputation.rbl.httpbl-key, and @rbl dnsbl.httpbl.org uses it. SecHttpBlKey in a ruleset is accepted and ignored, because the key belongs to the resolver, not to the rules.

What it does not do​

  • Host names are never asked about. Only address literals become queries. A name in a request turned into a DNS query is a way to make the gateway contact any domain.
  • The CRS does not use it. CRS 4 moved its IP reputation rules out of the core ruleset. This is for your own rules.
  • The answer is not a score. @rbl matches or it does not. For weighted reputation, use threat feeds and the threat score.

Configuration​

Under reputation.rbl in the extension configuration.

KeyDefault
enabledtrue
timeout-millis2000
wait-millis100 — 0 never waits
listed-ttl-seconds, unlisted-ttl-seconds, error-ttl-seconds900, 300, 30
max-entries100000
nameserversthe system's — ["10.0.0.53", "10.0.0.54:5353"]
httpbl-key—