Fix SpamAssassin “URIBL_BLOCKED / Spamhaus Blocked Due to Open Resolver”

(When Unbound Alone Doesn’t Fix It)

SpamAssassin still showing URIBL_BLOCKED_OPENDNS even after installing Unbound? The issue is usually DNS leakage via systemd-resolved. Here’s the correct, production-safe setup that actually fixes it.

Table of Contents

One of my clients recently ran into a frustrating issue: SpamAssassin was clearly not working as expected. Spam emails were slipping through, and the logs kept showing:

				
					URIBL_BLOCKED_OPENDNS
RCVD_IN_ZEN_BLOCKED_OPENDNS
				
			
URIBL_BLOCKED_OPENDNS

At first glance, this looks like a typical Spamhaus issue — usually fixed by installing Unbound.

But in this case, even after Unbound was installed and working, the problem persisted.

That’s where things got interesting.

This wasn’t a missing package or a broken config. It was a DNS architecture problem — and it’s more common than most guides admit.

If you’re running a VPS with Virtualmin, BIND9, Postfix, and SpamAssassin, this is a common issue under Email & SMTP Issues.

Problem Summary

Here’s what we observed:

URIBL_BLOCKED_OPENDNS

RCVD_IN_ZEN_BLOCKED_OPENDNS

The key issue:

Your server is using a shared DNS resolver (like Hetzner DNS) instead of performing its own recursive lookups.

Spamhaus intentionally blocks these shared resolvers.

Verify Spamhaus is actually blocked

First, confirm the issue:

				
					dig zen.spamhaus.org
				
			

If you get:

				
					ANSWER: 0
				
			

That’s a silent block.

Then test with a known query:

				
					dig 2.0.0.127.zen.spamhaus.org
				
			

If this fails or returns something similar to the below image (Answer Section) → Spamhaus queries are not working.

Spamhaus not working

The Correct Fix

(Production-Ready Setup)

Instead of partial fixes or layered workarounds, the goal is simple:

Make all DNS queries from your server go through a local recursive resolver (Unbound), with zero fallback.

Install and Configure Unbound

(Local Recursive Resolver)

Install Unbound:

				
					apt install unbound -y
				
			

Create a clean recursive config:

				
					nano /etc/unbound/unbound.conf.d/recursive.conf
				
			

Configure it:

				
					server:
    interface: 127.0.0.1
    interface: ::1
    port: 53

    access-control: 127.0.0.0/8 allow

    do-ip4: yes
    do-ip6: yes
    do-udp: yes
    do-tcp: yes

    root-hints: "/usr/share/dns/root.hints"

    hide-identity: yes
    hide-version: yes

    qname-minimisation: yes
    harden-glue: yes
    harden-dnssec-stripped: yes

    cache-min-ttl: 300
    cache-max-ttl: 86400
				
			

Ensure root hints exist:

				
					wget -O /usr/share/dns/root.hints https://www.internic.net/domain/named.root
				
			

Start Unbound:

				
					systemctl enable unbound
systemctl restart unbound
				
			

Configure BIND as Authoritative Only

(Critical)

If you’re using Virtualmin or BIND9, it will be running on port 53.

To avoid conflict and ensure clean separation:

Edit:

				
					nano /etc/bind/named.conf.options
				
			

Set:

				
					options {
    directory "/var/cache/bind";

    recursion no;

    listen-on { YOUR_PUBLIC_IPV4; };
    listen-on-v6 { YOUR_PUBLIC_IPV6; };

    dnssec-validation auto;
};
				
			

This ensures:

Restart BIND:

				
					systemctl restart bind9
				
			

Remove systemd-resolved

(Prevents DNS Leakage)

systemd-resolved is the main cause of hidden DNS fallback.

Disable it completely:

				
					systemctl disable systemd-resolved
systemctl stop systemd-resolved
				
			

Replace /etc/resolv.conf:

				
					rm -f /etc/resolv.conf
nano /etc/resolv.conf
				
			

Add:

				
					nameserver 127.0.0.1
				
			

This forces:

All DNS queries → Unbound → direct recursion

No fallback. No ambiguity.

Final DNS Architecture

After applying the above:

				
					LOCAL DNS (server → internet)
    → Unbound (127.0.0.1:53)

PUBLIC DNS (internet → your server)
    → BIND (public IPv4 + IPv6)
				
			

Verification (IMPORTANT)

Do not skip this. This confirms the fix is real.

1. Confirm system is using Unbound

				
					dig google.com
				
			

You should see:

				
					SERVER: 127.0.0.1#53
				
			

2. Confirm Spamhaus is working

				
					dig 2.0.0.127.zen.spamhaus.org
				
			

Expected:

				
					127.0.0.2
127.0.0.4
127.0.0.10
				
			
Spamhaus working

3. Confirm SpamAssassin no longer blocked

				
					spamassassin -D < email.eml 2>&1 | grep -i blocked
				
			

You should NOT see:

				
					URIBL_BLOCKED
RCVD_IN_ZEN_BLOCKED_OPENDNS
				
			

4. Confirm no DNS leakage (advanced but recommended)

				
					tcpdump -ni any port 53
				
			

You should NOT see external DNS like 185.x.x.x. Only root DNS queries.

Common Mistakes / Edge Cases

Need Help Fixing Your VPS?

If you’re stuck with server issues and need a reliable fix, I troubleshoot real VPS problems daily — from Nginx errors and SMTP failures to DNS and performance issues.

Instead of guessing, get a proven fix based on real experience.

Conclusion

This issue isn’t about installing Unbound.

It’s about controlling the DNS path completely.

Once you:

SpamAssassin works exactly as intended.

Tharindu

Hey!! I'm Tharindu. I'm from Sri Lanka. I'm a part time freelancer and this is my blog where I write about everything I think might be useful to readers. If you read a tutorial here and want to hire me, contact me here.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button