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]

Reply via email to