Blocking with RBLs
Hi,
Is there a way to block with RBLs? I already have a really good and very trustworthy and accurate internal one that works extremely well and fast with my SMTP servers for years now. Is there a way to apply the same RBL to dovecot? Logs are really going crazy as they stopped with SMTP and started with IMAP for a while now since dovecot is wide open to these attacks. Anvil does not seem to do much here. I am looking for solutions other than fail2ban or anything similar to this.
Lefteris
On 09/01/2026 12:08 EET Lefteris Tsintjelis via dovecot <dovecot@dovecot.org> wrote:
Hi,
Is there a way to block with RBLs? I already have a really good and very trustworthy and accurate internal one that works extremely well and fast with my SMTP servers for years now. Is there a way to apply the same RBL to dovecot? Logs are really going crazy as they stopped with SMTP and started with IMAP for a while now since dovecot is wide open to these attacks. Anvil does not seem to do much here. I am looking for solutions other than fail2ban or anything similar to this.
Lefteris
You can use auth_policy_server settings to configure an external service for this, please see e.g. https://github.com/PowerDNS/weakforced/ as an example of such service.
Aki
On 9 Jan 2026, at 12:31, Aki Tuomi <aki.tuomi@open-xchange.com> wrote:
On 09/01/2026 12:08 EET Lefteris Tsintjelis via dovecot <dovecot@dovecot.org> wrote:
Hi,
Is there a way to block with RBLs? I already have a really good and very trustworthy and accurate internal one that works extremely well and fast with my SMTP servers for years now. Is there a way to apply the same RBL to dovecot? Logs are really going crazy as they stopped with SMTP and started with IMAP for a while now since dovecot is wide open to these attacks. Anvil does not seem to do much here. I am looking for solutions other than fail2ban or anything similar to this.
Lefteris
You can use auth_policy_server settings to configure an external service for this, please see e.g. https://github.com/PowerDNS/weakforced/ as an example of such service.
Aki
Thank you. Looks very flexible and powerful but in this case seems like a huge overkill for such a simple thing just for checking one local DNSBL. I was thinking more like the code below. I think AI gave me a fast and acceptable solution
#!/usr/bin/env python3 import sys import socket
data = sys.stdin.buffer.read(1024).split(b'\n') if len(data) < 3: sys.exit(1)
username = data[0].decode() password = data[1].decode() # we don't care rip = data[2].decode() # remote IP
DNSBL(s) here
DNSBLS = [ “my.own.dnsbl.gr", ]
def is_blacklisted(ip): try: rev = '.'.join(reversed(ip.split('.'))) for zone in DNSBLS: try: socket.gethostbyname(f"{rev}.{zone}") return True except socket.gaierror: pass return False except: return False # be fail-open on DNS failure
if is_blacklisted(rip): sys.stderr.write(f"DNSBL blocked IP {rip}\n") sys.exit(1)
Otherwise pass to next auth (PAM, passwd-file, sql, etc)
sys.exit(0)
Lefteris
YOu can also implement simple RBL auth policy server, the auth policy feature sends JSON blob of fields and excepts a JSON blob in response. Upside is that the policy check is done before any authentication happens. You can ignore all the other stuff and just check the remote IP.
See https://doc.dovecot.org/2.4.2/core/config/auth/policy.html#authentication-po...
Aki
On 09/01/2026 13:19 EET Lefteris Tsintjelis via dovecot <dovecot@dovecot.org> wrote:
On 9 Jan 2026, at 12:31, Aki Tuomi <aki.tuomi@open-xchange.com> wrote:
On 09/01/2026 12:08 EET Lefteris Tsintjelis via dovecot <dovecot@dovecot.org> wrote:
Hi,
Is there a way to block with RBLs? I already have a really good and very trustworthy and accurate internal one that works extremely well and fast with my SMTP servers for years now. Is there a way to apply the same RBL to dovecot? Logs are really going crazy as they stopped with SMTP and started with IMAP for a while now since dovecot is wide open to these attacks. Anvil does not seem to do much here. I am looking for solutions other than fail2ban or anything similar to this.
Lefteris
You can use auth_policy_server settings to configure an external service for this, please see e.g. https://github.com/PowerDNS/weakforced/ as an example of such service.
Aki
Thank you. Looks very flexible and powerful but in this case seems like a huge overkill for such a simple thing just for checking one local DNSBL. I was thinking more like the code below. I think AI gave me a fast and acceptable solution
#!/usr/bin/env python3 import sys import socket
data = sys.stdin.buffer.read(1024).split(b'\n') if len(data) < 3: sys.exit(1)
username = data[0].decode() password = data[1].decode() # we don't care rip = data[2].decode() # remote IP
DNSBL(s) here
DNSBLS = [ “my.own.dnsbl.gr", ]
def is_blacklisted(ip): try: rev = '.'.join(reversed(ip.split('.'))) for zone in DNSBLS: try: socket.gethostbyname(f"{rev}.{zone}") return True except socket.gaierror: pass return False except: return False # be fail-open on DNS failure
if is_blacklisted(rip): sys.stderr.write(f"DNSBL blocked IP {rip}\n") sys.exit(1)
Otherwise pass to next auth (PAM, passwd-file, sql, etc)
sys.exit(0)
Lefteris
dovecot mailing list -- dovecot@dovecot.org To unsubscribe send an email to dovecot-leave@dovecot.org
On 9 Jan 2026, at 12:31, Aki Tuomi via dovecot <dovecot@dovecot.org> wrote:
On 09/01/2026 12:08 EET Lefteris Tsintjelis via dovecot <dovecot@dovecot.org> wrote:
Hi,
Is there a way to block with RBLs? I already have a really good and very trustworthy and accurate internal one that works extremely well and fast with my SMTP servers for years now. Is there a way to apply the same RBL to dovecot? Logs are really going crazy as they stopped with SMTP and started with IMAP for a while now since dovecot is wide open to these attacks. Anvil does not seem to do much here. I am looking for solutions other than fail2ban or anything similar to this.
Lefteris
You can use auth_policy_server settings to configure an external service for this, please see e.g. https://github.com/PowerDNS/weakforced/ as an example of such service.
Aki
I think the following is very light in resources by using POSIX and can be used with IPv4 and IPv6 and does exactly what I want to check my single trusted DNSBL.
This should be before any other passdb
passdb { args = /…path to.../local.rbl.sh driver = checkpassword result_success = continue result_failure = return-fail }
The following must be executable:
cat local.rbl.sh
#!/bin/sh
--- CONFIGURATION ---
DNSBL_ZONE=“mysingle.trusted.dnsbl" LOGGING=1
Log helper
log_msg() { if [ "$LOGGING" -eq 1 ]; then logger -p mail.notice -t dovecot-dnsbl "$1" fi }
1. CONSUME CREDENTIALS (Read FD 3 if available)
user="" if [ -e /dev/fd/3 ]; then data=$(dd if=/dev/fd/3 bs=4096 count=1 2>/dev/null) if [ -n "$data" ]; then user=$(echo "$data" | awk -F '\0' '{print $1}') fi fi
2. GET IP ADDRESS
REMOTE_IP="${TCPREMOTEIP:-$IP}"
If running manually for a test, allow passing IP as 2nd arg
usage: ./script.sh dummy_binary 1.2.3.4
if [ -z "$REMOTE_IP" ] && [ -n "$2" ]; then REMOTE_IP="$2" fi
if [ -z "$REMOTE_IP" ]; then # No IP found, allow access (e.g. internal socket or manual run without args) log_msg "Allowing (no IP provided)${user:+ for user $user}" if [ -x "$1" ]; then exec "$1" else printf '\0' exit 0 fi fi
3. DETECT IP VERSION AND PREPARE QUERY
if echo "$REMOTE_IP" | grep -q ":"; then # --- IPv6 LOGIC (AWK) --- REVERSED_IP=$(echo "$REMOTE_IP" | awk ' BEGIN { FS=":"; OFS="" } { if (index($0, "::") > 0) { match($0, /::/); head = substr($0, 1, RSTART-1); tail = substr($0, RSTART+2); n_head = (head == "") ? 0 : split(head, h, ":"); n_tail = (tail == "") ? 0 : split(tail, t, ":"); missing = 8 - n_head - n_tail; full = head; for(i=0; i<missing; i++) full = full ":0000"; if (tail != "") { if (full != "") full = full ":" tail; else full = tail; } } else { full = $0; } split(full, groups, ":"); res = ""; for (i=8; i>=1; i--) { val = groups[i]; while (length(val) < 4) val = "0" val; for (j=4; j>=1; j--) res = res "." substr(val, j, 1); } print substr(res, 2); }') else # --- IPv4 LOGIC --- REVERSED_IP=$(echo "$REMOTE_IP" | awk -F. '{print $4"."$3"."$2"."$1}') fi
4. PERFORM LOOKUP
if [ -z "$REVERSED_IP" ]; then # Invalid IP, allow log_msg "Allowing invalid IP $REMOTE_IP${user:+ for user $user}" if [ -x "$1" ]; then exec "$1" else printf '\0' exit 0 fi fi
QUERY="${REVERSED_IP}.${DNSBL_ZONE}"
if host -t A "$QUERY" >/dev/null 2>&1; then log_msg "REJECTED: $REMOTE_IP is listed in $DNSBL_ZONE${user:+ for user $user}" exit 1 fi
5. SUCCESS HAND-OFF
log_msg "Allowing $REMOTE_IP (Clean)${user:+ for user $user}" if [ -x "$1" ]; then exec "$1" else printf '\0' exit 0 fi
Lefteris
On 9 Jan 2026, at 12:31, Aki Tuomi via dovecot <dovecot@dovecot.org>
wrote:
On 09/01/2026 12:08 EET Lefteris Tsintjelis via dovecot
<dovecot@dovecot.org> wrote:
Hi,
Is there a way to block with RBLs? I already have a really good and
very trustworthy and accurate internal one that works extremely well
and fast with my SMTP servers for years now. Is there a way to apply
the same RBL to dovecot? Logs are really going crazy as they stopped
with SMTP and started with IMAP for a while now since dovecot is wide
open to these attacks. Anvil does not seem to do much here. I am
looking for solutions other than fail2ban or anything similar to this.
Lefteris
You can use auth_policy_server settings to configure an external service
for this, please see e.g. https://github.com/PowerDNS/weakforced/ as an
example of such service.
Aki
I think the following is very light in resources by using POSIX and can be used with IPv4 and IPv6 and does exactly what I want to check my single trusted DNSBL.
This should be before any other passdb
passdb {
args = /...path to.../local.rbl.sh
driver = checkpassword
result_success = continue
result_failure = return-fail
}
The following must be executable:
cat local.rbl.sh
#!/bin/sh
--- CONFIGURATION ---
DNSBL_ZONE="mysingle.trusted.dnsbl"
LOGGING=1
Log helper
log_msg() {
if [ "$LOGGING" -eq 1 ]; then
logger -p mail.notice -t dovecot-dnsbl "$1"
fi
}
1. CONSUME CREDENTIALS (Read FD 3 if available)
user=""
if [ -e /dev/fd/3 ]; then
data=$(dd if=/dev/fd/3 bs=4096 count=1 2>/dev/null)
if [ -n "$data" ]; then
user=$(echo "$data" | awk -F '\0' '{print $1}')
fi
fi
2. GET IP ADDRESS
REMOTE_IP="${TCPREMOTEIP:-$IP}"
If running manually for a test, allow passing IP as 2nd arg
usage: ./script.sh dummy_binary 1.2.3.4
if [ -z "$REMOTE_IP" ] && [ -n "$2" ]; then
REMOTE_IP="$2"
fi
if [ -z "$REMOTE_IP" ]; then
# No IP found, allow access (e.g. internal socket or manual run
without args)
log_msg "Allowing (no IP provided)${user:+ for user $user}"
if [ -x "$1" ]; then
exec "$1"
else
printf '\0'
exit 0
fi
fi
3. DETECT IP VERSION AND PREPARE QUERY
if echo "$REMOTE_IP" | grep -q ":"; then
# --- IPv6 LOGIC (AWK) ---
REVERSED_IP=$(echo "$REMOTE_IP" | awk '
BEGIN { FS=":"; OFS="" }
{
if (index($0, "::") > 0) {
match($0, /::/);
head = substr($0, 1, RSTART-1);
tail = substr($0, RSTART+2);
n_head = (head == "") ? 0 : split(head, h, ":");
n_tail = (tail == "") ? 0 : split(tail, t, ":");
missing = 8 - n_head - n_tail;
full = head;
for(i=0; i<missing; i++) full = full ":0000";
if (tail != "") { if (full != "") full = full ":" tail; else
full = tail; }
} else { full = $0; }
split(full, groups, ":");
res = "";
for (i=8; i>=1; i--) {
val = groups[i];
while (length(val) < 4) val = "0" val;
for (j=4; j>=1; j--) res = res "." substr(val, j, 1);
}
print substr(res, 2);
}')
else
# --- IPv4 LOGIC ---
REVERSED_IP=$(echo "$REMOTE_IP" | awk -F. '{print $4"."$3"."$2"."$1}')
fi
4. PERFORM LOOKUP
if [ -z "$REVERSED_IP" ]; then
# Invalid IP, allow
log_msg "Allowing invalid IP $REMOTE_IP${user:+ for user $user}"
if [ -x "$1" ]; then
exec "$1"
else
printf '\0'
exit 0
fi
fi
QUERY="${REVERSED_IP}.${DNSBL_ZONE}"
if host -t A "$QUERY" >/dev/null 2>&1; then
log_msg "REJECTED: $REMOTE_IP is listed in $DNSBL_ZONE${user:+ for
user $user}"
exit 1
fi
5. SUCCESS HAND-OFF
log_msg "Allowing $REMOTE_IP (Clean)${user:+ for user $user}"
if [ -x "$1" ]; then
exec "$1"
else
printf '\0'
exit 0
fi
Lefteris
On 09/01/2026 11:08, Lefteris Tsintjelis via dovecot wrote:
Hi,
Is there a way to block with RBLs? I already have a really good and very trustworthy and accurate internal one that works extremely well and fast with my SMTP servers for years now. Is there a way to apply the same RBL to dovecot? Logs are really going crazy as they stopped with SMTP and started with IMAP for a while now since dovecot is wide open to these attacks. Anvil does not seem to do much here. I am looking for solutions other than fail2ban or anything similar to this.
Lefteris
dovecot mailing list -- dovecot@dovecot.org To unsubscribe send an email to dovecot-leave@dovecot.org
Hi Lefteris
for smtp port 25 incoming email the use of RBLs is a consolidated practice but for smtp auth the use of RBLs may not be so easy to apply and I think the same goes for IMAP authentication.
I find it useful (both on Postfix and Dovecot) to apply XBL to block connection to authenticated services. For me it works, but I have a very low probability that legitimate users will connect from ip addresses on XBL. Others have mentioned that it is not generally feasible if you have a lot of users from dynamic ips, due to the potential of recycling of blocked ip addresses to legitimate users.
In Dovecot if I remember correctly Aki previously mentioned that it would be possible to use LUA scripts to do RBL looks prior to authenticating, something that is on my to do list for future investigation.
In the meantime I run a locally patched version of Dovecot. I added an "rbl_check" parameter to the protocol section, so it can also be configured for managesieve as well as imap and pop3. I also took the step of making protocol error limits configurable and then setting them to a very low value (in my case 1). I think legitimate clients don't need much space to make protocol errors so I am not too lenient.
John
On Fri, 9 Jan 2026, John Fawcett wrote:
I find it useful (both on Postfix and Dovecot) to apply XBL to block connection to authenticated services.
I grep'd through last week's logs for probable brute forcers, and check the IPs against 3 RBLs. (Many IPs tried only once.)
Aggregate statistics:
87 - - - (No hits)
46 + - -
32 + + -
9 + - +
6 + + +
5 - + -
4 - - +
102/189 (54%) were listed by at least one of the RBLs, with the following stats
RBL hits rate rate (>0 hits)
(col#1) bl.blocklist.de 93 49% 91%
(col#2) auth.spamrats.com 52 28% 51%
(col#3) xbl.spamhaus.org 19 10% 19%
You should try one of the other 2 RBLs: they specificaly list brute forcers. I use them as pre-emptive block-on-sight for SMTP auth, and I don't recall ever getting a false positive.
Joseph Tam <jtam.home@gmail.com>
On 10/01/2026 03:04, Joseph Tam via dovecot wrote:
On Fri, 9 Jan 2026, John Fawcett wrote:
I find it useful (both on Postfix and Dovecot) to apply XBL to block connection to authenticated services.
I grep'd through last week's logs for probable brute forcers, and check the IPs against 3 RBLs. (Many IPs tried only once.)
Aggregate statistics:
87 - - - (No hits) 46 + - - 32 + + - 9 + - + 6 + + + 5 - + - 4 - - +
102/189 (54%) were listed by at least one of the RBLs, with the following stats
RBL hits rate rate (>0 hits) (col#1) bl.blocklist.de 93 49% 91% (col#2) auth.spamrats.com 52 28% 51% (col#3) xbl.spamhaus.org 19 10% 19%
You should try one of the other 2 RBLs: they specificaly list brute forcers. I use them as pre-emptive block-on-sight for SMTP auth, and I don't recall ever getting a false positive.
Joseph Tam <jtam.home@gmail.com>
Hi Joseph
thanks for the tip. I do use auth.spamrats.com on smtp auth, not so far on imap/managesieve. I do know of blocklist.de but I can't remember now if I evaluated to use it in this context. I will look into those.
Out of curiosity are those data from smtp auth or from Dovecot brute force auth attempts? I assume Dovecot but wanted to make sure I understood correctly. Do you do any kind of blocking on Dovecot that could influence the numbers?
It's a while since I checked blocking performance, but what I seem to remember is that I got a lot more attempts before I started blocking, so what I see now with blocking applied is not necessarily representative of what I would see if I didn't block. My assumption is that behind multiple ips there can be the same actor switching ips to fly under the radar of fail2ban. When applying outright blocking at connection time seems that the actors can move on elsewhere and consequently you end up avoiding more than you actually see as rejects. That's kind of anecdotal, I don't think I have hard evidence of it.
John
On Sat, 10 Jan 2026, John Fawcett wrote:
Out of curiosity are those data from smtp auth or from Dovecot brute force auth attempts?
Dovecot.
I assume Dovecot but wanted to make sure I understood correctly. Do you do any kind of blocking on Dovecot that could influence the numbers?
Not really. I thought perhaps some of my larger Asian firewall blockw could affect this, but the firewall logs do not show this. The volume of BFD attempts are way higher on SMTP than IMAP/POP3.
It's a while since I checked blocking performance, but what I seem to remember is that I got a lot more attempts before I started blocking, so what I see now with blocking applied is not necessarily representative of what I would see if I didn't block. My assumption is that behind multiple ips there can be the same actor switching ips to fly under the radar of fail2ban. When applying outright blocking at connection time seems that the actors can move on elsewhere and consequently you end up avoiding more than you actually see as rejects. That's kind of anecdotal, I don't think I have hard evidence of it.
I guess some attackers could give up after some rejections, but mostly I see time/user correlated attempt from many different IPs, indicating the same actor is using a botnet.
Joseph Tam <jtam.home@gmail.com>
participants (4)
-
Aki Tuomi
-
John Fawcett
-
Joseph Tam
-
Lefteris Tsintjelis