Dovecot 2.4 - CSF/LFD no longer catches failed IMAP/POP logins

jigster

Verified User
Joined
Jul 23, 2021
Messages
97
I upgraded to Dovecot 2.4.1-4 and since then CSF/LFD no longer catches failed IMAP/POP logins. I thought the problem was going to be the line logged in /var/log/maillog had changed, which it has a little bit, but the regex that catches the failed logins in /etc/csf/lfd.pl should still work correctly:

Example log line (relevant part):
Code:
imap-login: Login aborted: Connection closed (auth failed, 2 attempts in 16 secs) (auth_failed):

Regex:
Code:
if (($app eq "pop3d" or $app eq "imapd") and $line =~ /\(auth failed, (\d+) attempts/) {

I am using CSF 15.0 but the issue is definitely the Dovecot upgrade because on my other servers with Dovecot 2.3.21.1 and CSF 15.0, it all works perfectly.

Anyone have any ideas what could be causing this? It's very insecure to not catch and block failed IMAP/POP logins so I would like to find a fix for this.
 
Last edited:
I dug a little more and I can see that the regex in /usr/local/csf/lib/ConfigServer/RegexMain.pm doesn't match the line that the new Dovecot is outputting. I thought about adding a custom regex in /etc/csf/regex.custom.pm but I assume that won't count the multiple failed logins like /etc/csf/lfd.pl does (it adds up all attempts from the log lines "X attempts in X secs"). And if I modify /usr/local/csf/lib/ConfigServer/RegexMain.pm directly, I assume this will get overwritten if DA does any updates to CSF? Any ideas on the solution?
 
Last edited:
After some experimenting, I think if you use custom regexes in /etc/csf/regex.custom.pm with the names 'imapd' and 'pop3d' in the rules (not your own unique names), it does count the multiple failures from "X attempts in X secs" as before, and works correctly to block the failed logins. The custom regex seems to have fixed the issue for now at least. I hope DA or someone else starts to maintain CSF, otherwise it looks like we'll all be looking for an alternative soon!
 
It's still secure if you already have BFM enable, that how I protect my server to ensure It still can blocked it, but it slow than LFD.

BFM need the time to scan every {X} seconds.
 
Dovecot 2.4 vs 2.3 config changes https://doc.dovecot.org/2.4.0/installation/upgrade/2.3-to-2.4.html ?

Required Settings​

The first setting in dovecot.conf MUST now be <a href="https://doc.dovecot.org/2.4.0/core/summaries/settings.html#dovecot_config_version">dovecot_config_version</a>. This helps to avoid unexpected configuration changes in the future.

Another new required setting is <a href="https://doc.dovecot.org/2.4.0/core/summaries/settings.html#dovecot_storage_version">dovecot_storage_version</a>. This helps to avoid unexpected storage file format incompatibilities.

Note that the configuration syntax has been changed, and your old configuration will not work without changes.

Variable expansion​

A new Settings Variables syntax has been introduced. All old one-letter %variables have been removed, and some old variable aliases have been dropped too.
 
Last edited:
I don't use DirectAdmin brute force manager, but that's interesting to know. The regex I've added to/etc/csf/regex.custom.pm is the same for both POP and IMAP, but I've listed them separately so can have different name/settings for each:

Code:
# IMAP
if (($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: (imap-login|pop3-login): (Login aborted: (Logged out|Connection closed|Inactivity|Inactivity during authentication))(\s*\(auth failed, \d+ attempts( in \d+ secs)?\) \(auth_failed\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
    return ("Failed IMAP login from",$11,"imapd","20","","3600");
}

# POP
if (($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: (imap-login|pop3-login): (Login aborted: (Logged out|Connection closed|Inactivity|Inactivity during authentication))(\s*\(auth failed, \d+ attempts( in \d+ secs)?\) \(auth_failed\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
    return ("Failed POP3 login from",$11,"pop3d","20","","3600");
}

I'm pretty sure this regex could be improved and maybe doesn't catch every case, but I haven't had time to study the logs in details yet and needed something quickly. It's a work in progress!
 
The following patch can be used:
Code:
--- a/ConfigServer/RegexMain.pm_orig    2025-02-10 13:48:56.000000000 +0200
+++ b/ConfigServer/RegexMain.pm 2025-09-08 15:59:50.459332819 +0300
@@ -192,28 +192,28 @@
    }
 
 #dovecot
-   if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: pop3-login: (Disconnected: )?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(:\s*\S+\sfailed: Connection reset by peer)?(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
+   if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: pop3-login: (?:Login aborted:\s*)?(Disconnected: )?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(:\s*\S+\sfailed: Connection reset by peer)?(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?\s*(?:\(auth_failed\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
         my $ip = $12;
        my $acc = $10;
        $ip =~ s/^::ffff://;
        $acc =~ s/^<|>$//g;
        if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return}
    }
-       if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: imap-login: (Disconnected: )?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(:\s*\S+\sfailed: Connection reset by peer)?(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
+   if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: imap-login: (?:Login aborted:\s*)?(Disconnected: )?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(:\s*\S+\sfailed: Connection reset by peer)?(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?\s*(?:\(auth_failed\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
         my $ip = $12;
        my $acc = $10;
        $ip =~ s/^::ffff://;
        $acc =~ s/^<|>$//g;
        if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return}
    }
-   if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) pop3-login(\[\d+\])?: Info: (Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
+   if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) pop3-login(\[\d+\])?: Info: (?:Login aborted:\s*)?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?\s*(?:\(auth_failed\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
         my $ip = $10;
        my $acc = $8;
        $ip =~ s/^::ffff://;
        $acc =~ s/^<|>$//g;
        if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return}
    }
-   if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) imap-login(\[\d+\])?: Info: (Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
+   if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) imap-login(\[\d+\])?: Info: (?:Login aborted:\s*)?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?\s*(?:\(auth_failed\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) {
         my $ip = $10;
        my $acc = $8;
        $ip =~ s/^::ffff://;

It'll likely be included into DA soon.
 
Back
Top