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

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:
- SpamAssassin logs show:
URIBL_BLOCKED_OPENDNS
RCVD_IN_ZEN_BLOCKED_OPENDNS
- Spam filtering inconsistent or weak
- Manual dig tests sometimes work
- Unbound installed and running
- But Spamhaus still blocking queries
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.

The Correct Fix
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
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
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:
- BIND serves only public DNS queries
- It does NOT interfere with local resolution
- It does NOT bind to 127.0.0.1 or ::1
Restart BIND:
systemctl restart bind9
Remove systemd-resolved
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

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
- Running Unbound on port 5353 but pointing system to port 53
- Leaving BIND listening on localhost
- Keeping systemd-resolved enabled (causes silent fallback)
- Assuming dig @127.0.0.1 means system is using it
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.
- Fix Nginx, Apache, and 502/504 errors
- Resolve SMTP, email, and SES issues
- Debug DNS, SSL, and domain problems
- Optimize performance (CPU, RAM, slow sites)
Conclusion
This issue isn’t about installing Unbound.
It’s about controlling the DNS path completely.
- Shared DNS resolvers get blocked by Spamhaus
- systemd-resolved introduces hidden fallback
- Partial fixes create inconsistent results
Once you:
- isolate BIND (authoritative)
- use Unbound (recursive)
- remove systemd-resolved
SpamAssassin works exactly as intended.



