Spamhaus refuses queries that reach it through a public resolver. Ask its blocklist about an address from a laptop whose DNS goes through Cloudflare's 1.1.1.1 or Google's 8.8.8.8, and the answer you get back describes your resolver, not the address. Depending on the resolver it comes as an error code shaped exactly like a listing or as silence that looks like a clean bill. Neither is about the IP you asked for. So Mosaic's reputation check does not ask Spamhaus at all, and the reason is written above the list of blocklists it does ask: a check that lies is worse than one that is missing.

How a DNS blocklist answers

A DNS blocklist, or DNSBL, is queried with an ordinary DNS lookup. To ask whether 203.0.113.7 is listed in a zone, you reverse its four numbers and put the zone name after them:

7.113.0.203.zen.spamhaus.org

If the name does not exist, the address is not listed. If it resolves, the address it resolves to is not somewhere to connect. It is a reason code, and every list publishes its own table of them. Listings live in 127.0.0.x, where each last number means something different: a spam source, an open proxy, a hijacked range.

That design is cheap and fast, and it has one weakness. The blocklist never sees you. It sees the recursive resolver that forwarded your lookup, and a large public resolver forwards lookups for millions of people at once.

Paste one gateway line. Every profile mints its own exitIn Mosaic: Provider minting. One gateway line, a separate exit for every profile. Free holds 3 profiles. Pro is $49 a month for any number.

How it works: Provider minting

Why "spamhaus query refused public resolver" happens

Spamhaus's free mirrors are meant for low-volume use, and the operator cannot tell how much one user is asking if every query arrives from the same public resolver. So it does not answer queries arriving that way. Instead it sends an answer from a separate range, 127.255.255.x, which it uses for errors: a mistyped zone, too many queries, and, at 127.255.255.254, a query that came through a public or open resolver. Some public resolvers do not even pass that code along and answer as if nothing were listed.

Mail servers meet this first. A server whose resolver forwards to a public one gets the error code on every lookup. If its software treats any answer as a listing, it rejects every incoming message, and the log line says "blocked using zen.spamhaus.org". The other failure is quieter and worse. A resolver that turns the refusal into "not listed" lets everything through, and nothing errors, so nobody notices.

Why we left it out instead of handling it

Our reputation check is part of the same proxy check that tests whether an exit answers and tunnels. It runs on the computer Mosaic is installed on, and it sends its blocklist lookups to 1.1.1.1 and 8.8.8.8 on purpose. Some home and office ISP resolvers filter blocklist zones entirely, and we did not want the answer to depend on whichever network the laptop happened to be on that day. Pinning the resolvers makes the result repeatable. It also puts every query on exactly the route Spamhaus refuses.

We could have kept Spamhaus and read its error codes properly. That would have left a row in the report that never produces an answer on an ordinary machine. On a Cloudflare route it would show a refusal on every address, and on a route that swallows the code it would show "not listed" on every address, which is the worse of the two because it looks like information. A blocklist the check cannot read honestly is better gone than present and wrong, so the code comment says it plainly: Spamhaus is deliberately absent.

What the check asks instead

The check asks a handful of other lists instead, SpamCop among them. Each has its own table of codes, so a hit is printed as its meaning, "Reported as a spam source" rather than 127.0.0.2. An answer that is not in a list's table is printed as the raw address rather than translated, so an unexpected code shows up as something odd to look at rather than as a clean result. A missing name and a timeout are both treated as silence: neither is evidence the address is bad. That cuts both ways, and we know it. A list that stops answering looks, from here, like a list that has nothing on you, so a clean row means "nothing checked said otherwise", not proof.

A listing is only one input. The check also looks at whether the exit sits in a datacentre range, using the network classification from the geo lookup and words like hosting or vps in the reverse DNS name or the ISP, and whether there is any reverse DNS at all. Those add up to a risk from 0 to 100: 25 for each listing up to 60, 20 more if a listing names an open proxy or relay, 25 for a datacentre range and 5 for no reverse DNS. Under 25 is clean, from 25 to 59 is caution and 60 or more is risky. Only IPv4 addresses can be scored this way, and the report says so instead of pretending.

There is one more line the check adds when it applies. If the proxy endpoint rotates, the address it scored is one draw from a pool, not the exit a profile will browse from, and the report says to pin a sticky session to score the real one. Reputation is part of checking a proxy before you use it, and what a clean residential address can still trip over is in a residential IP detected as a proxy.

If you need Spamhaus's verdict on one exit, look the address up on Spamhaus's own website. It answers a person directly, with nothing in between to change the meaning.