On 9 Jan 2026, at 12:31, Aki Tuomi via dovecot <[email protected]>
wrote:
On 09/01/2026 12:08 EET Lefteris Tsintjelis via dovecot
<[email protected]> 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
_______________________________________________
dovecot mailing list -- [email protected]
To unsubscribe send an email to [email protected]