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