> To: exim-users @ lists.exim.org

~ $ dig lists.exim.org mx
;; QUESTION SECTION:
;lists.exim.org.                        IN      MX

;; ANSWER SECTION:
lists.exim.org.         294     IN      CNAME   cumin.exim.org.
cumin.exim.org.         300     IN      MX      10 cumin.exim.org.

In my home computer (with FreeBSD) by default the MSA is sendmail, I suppose
it "canonicalizes" the hostname before submission to my MTA on my VPS (Exim).

2023-05-12 00:24:49 +0300
H=cumin.exim.org [37.120.190.30]
SMTP error from remote mail server after RCPT TO:<exim-users @ cumin.exim.org>: 
550 unknown user

In my home computer I had to add to /usr/local/etc/unbound/unbound.conf :

local-data: "lists.exim.org MX 10 cumin.exim.org"

> From: Slavko <li...@slavino.sk>

> The problem is in exim. It gets (logs) "authenticator failed ..." line,
> that line contains "535 Incorrect authentication data ..." too. Then
> it responds that (i guess) to client, which never responds. The
> connection is then hold open, until timeout happens (in my case
> i lowered it to 60 sec). As attackers does that login attempts in
> waves 10-15 IPs in short time, here are multiple connections
> openned until timeout happens.

How do you know that connection is held open and timeout happens?
I seldom see that in my logs.
During last 30 days I see (logged in notquit ACL)
3867 connection-lost and 63 command-timeout events
after authentication failed.
In my config:

smtp_max_synprot_errors = 0
WARNTO = l...@lena.kiev.ua
SHELL = /bin/sh
ADDRNAME = $sender_host_address $acl_c_country ${sg{${lookup dnsdb{>, 
defer_never,ptr=$sender_host_address}}}{\N[^\w.,-]\N}{}}
chunking_advertise_hosts =
slow_lookup_log = 1500
auth_advertise_hosts = ${if eq{$sender_helo_name}{ylmf-pc}{}{*}}
log_timezone
smtp_accept_max = 15
smtp_accept_max_nonmail = 9
log_selector = +smtp_confirmation +queue_time +queue_time_overall \
               +deliver_time +receive_time -retry_defer \
               +smtp_incomplete_transaction +smtp_no_mail +incoming_interface
acl_smtp_connect = acl_check_connect
acl_smtp_helo = acl_check_helo
acl_smtp_auth = acl_check_auth
acl_smtp_mail = acl_check_mail
acl_smtp_quit = acl_check_quit
acl_smtp_notquit = acl_check_notquit
host_lookup = *
rfc1413_hosts = *
rfc1413_query_timeout = 2s
HELODETAINTED = ${sg{$sender_helo_name}{\N[^\w.,-]\N}{}}
# these two masks are used only in case of IPv6:
# how many IPv6 addresses you give to your single user:
MASKL = ${if match{$sender_host_address}{:}{/64}}
# how many external IPv6 addresses you treat as one attacker:
MASKW = ${if match{$sender_host_address}{:}{/56}}
...
begin acl
...
acl_check_connect:
  drop  message = $sender_host_address locally blacklisted for a bruteforce \
                  auth (login+password) cracking attempt
        condition = ${if exists{$spool_directory/blocked_IPs}}
        condition = ${lookup{$sender_host_address}iplsearch\
                    {/var/..$spool_directory/blocked_IPs}{1}{0}}
  drop  message = stretchoid and similar scanners banned
                condition = ${if match\
                {${lookup dnsdb{defer_never,ptr=$sender_host_address}}}\
                
{\N\.(stretchoid.com|shodan.io|internet-research-project.net|binaryedge.ninja|tchelebi.io|alphastrike.io|airtelbroadband.in|proxy-research.com)$\N}}

  accept

acl_check_helo:
...
  drop  message = suspicious client with helo=$sender_helo_name \
                  locally blacklisted
        condition = ${if eq{$sender_helo_name}{ylmf-pc}}
        acl = setdnslisttext
        condition = ${if match{$acl_c_country}{(?i)br|cn|vn}}
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs'}}

  drop  message = suspicious client with helo=$sender_helo_name \
                  locally blacklisted
        condition = ${if match{$sender_helo_name}\
                      {\N^(ganymede|ylmf-pc|\*\.\*|\[192\.168\.2\.33\])$\N}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: HELODETAINTED. blocked ADDRNAME; \
           echo; echo for bruteforce auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

  accept

acl_check_auth:
  drop  message = authentication is allowed only once per message in order \
                  to slow down bruteforce cracking
        set acl_m_auth = ${eval10:0$acl_m_auth+1}
        condition = ${if >{$acl_m_auth}{2}}
        delay = 22s

  drop  message = blacklisted for bruteforce cracking attempt
        set acl_c_authnomail = ${eval10:0$acl_c_authnomail+1}
        condition = ${if >{$acl_c_authnomail}{4}}
        condition = ${if exists{$spool_directory/blocked_IPs}\
                         {${lookup{$sender_host_address}iplsearch\
                           {$spool_directory/blocked_IPs}{0}{1}}}\
                         {1}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: blocked ADDRNAME; echo; echo \
           for bruteforce auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

  drop  message = blacklisted for bruteforce cracking attempt
        condition = ${if >{$acl_c_authnomail}{4}}

  accept set acl_c_authhash = ${if match{$smtp_command_argument}\
          {\N(?i)^(?:plain|login) (.+)$\N}{${nhash_1000:$1}}}

acl_check_mail:
  deny  message = 503 Bad sequence of commands - must send HELO/EHLO first
        condition = ${if !def:sender_helo_name}

  accept set acl_c_authnomail = 0

setdnslisttext:
  accept dnslists = all.ascc.dnsbl.bit.nl
         set acl_c_country = ${if match{$dnslist_text}{ CC=(\\S+) }{$1}}

  accept

acl_check_quit:
  accept condition = $authentication_failed
        logwrite = :reject: quit after authentication failed: \
                            ${sg{$sender_rcvhost}{\N[\n\t]+\N}{\040}}
        acl = setdnslisttext
        condition = ${if match{$acl_c_country}{(?i)br|cn|vn}}
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs'}}

  warn  condition = $authentication_failed
        dnslists = auth.spamrats.com
            # http://spamrats.com/rats-auth.php , http://spamrats.com/about.php
        condition = ${if exists{$spool_directory/blocked_IPs}\
                         {${lookup{$sender_host_address}iplsearch\
                           {$spool_directory/blocked_IPs}{0}{1}}}\
                         {1}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: spamrats. blocked ADDRNAME; \
           echo; echo for auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

  warn  condition = $authentication_failed
        condition = ${if match{$sender_helo_name}\
                        {\N^(User|xray500|FlapJack|gerg|smtp.lena.kiev.ua)$\N}}
        condition = ${if exists{$spool_directory/blocked_IPs}\
                         {${lookup{$sender_host_address}iplsearch\
                           {$spool_directory/blocked_IPs}{0}{1}}}\
                         {1}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: HELODETAINTED. blocked ADDRNAME; \
           echo; echo for auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

  warn  condition = $authentication_failed
        condition = ${if def:acl_c_authhash}
        ratelimit = 0 / 5m / strict / $sender_host_address-$acl_c_authhash
        set acl_c_hashrate = ${sg{$sender_rate}{[.].*}{}}

  warn  condition = $authentication_failed
        condition = ${if or{\
                            {!def:acl_c_authhash}\
                            {<{$acl_c_hashrate}{2}}\
                           }}
        ratelimit = 7 / 5m / strict / per_conn
        condition = ${if exists{$spool_directory/blocked_IPs}\
                         {${lookup{$sender_host_address}iplsearch\
                           {$spool_directory/blocked_IPs}{0}{1}}}\
                         {1}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: blocked ADDRNAME; echo; echo \
           for bruteforce auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

acl_check_notquit:
  accept condition = $authentication_failed
        logwrite = :reject: $smtp_notquit_reason after authentication failed: \
                            ${sg{$sender_rcvhost}{\N[\n\t]+\N}{\040}}
        acl = setdnslisttext
        condition = ${if match{$acl_c_country}{(?i)br|cn|vn}}
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs'}}

  warn  condition = $authentication_failed
        dnslists = auth.spamrats.com
            # http://spamrats.com/rats-auth.php , http://spamrats.com/about.php
        condition = ${if exists{$spool_directory/blocked_IPs}\
                         {${lookup{$sender_host_address}iplsearch\
                           {$spool_directory/blocked_IPs}{0}{1}}}\
                         {1}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: spamrats. blocked ADDRNAME; \
           echo; echo for auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

  warn  condition = $authentication_failed
        condition = ${if match{$smtp_notquit_reason}\
                              {^(connection-lost|synchronization-error)}}
        condition = ${if match{$sender_helo_name}\
                
{\N^(User|xray500|FlapJack|gerg|SERVER-KP1|((mail|smtp)\.)?(lena\.kiev|(ksana|sergej)\.org)\.ua)$\N}}
        !hosts = @[]
        condition = ${if exists{$spool_directory/blocked_IPs}\
                         {${lookup{$sender_host_address}iplsearch\
                           {$spool_directory/blocked_IPs}{0}{1}}}\
                         {1}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: HELODETAINTED. blocked ADDRNAME; \
           echo; echo for auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

  warn  condition = $authentication_failed
        condition = ${if def:acl_c_authhash}
        ratelimit = 0 / 2h / strict / $sender_host_address-$acl_c_authhash
        set acl_c_hashrate = ${sg{$sender_rate}{[.].*}{}}

  warn  condition = $authentication_failed
        condition = ${if match{$smtp_notquit_reason}\
                              {^(connection-lost|synchronization-error)}}
        condition = ${if or{\
                            {!def:acl_c_authhash}\
                            {<{$acl_c_hashrate}{2}}\
                           }}
        ratelimit = 7 / 2h / strict / per_conn
        condition = ${if exists{$spool_directory/blocked_IPs}\
                         {${lookup{$sender_host_address}iplsearch\
                           {$spool_directory/blocked_IPs}{0}{1}}}\
                         {1}}
        acl = setdnslisttext
        continue = ${run{SHELL -c 'echo \\\"$sender_host_addressMASKW\\\" \
           >>$spool_directory/blocked_IPs; \
           \N{\N echo Subject: blocked ADDRNAME; echo; echo \
           for bruteforce auth cracking attempt.; \
           \N}\N | $exim_path -f root WARNTO'}}

hash:
  accept set acl_c_authhash = ${nhash_1000:$acl_arg1}

...
begin authenticators

plain:
  driver = plaintext
  public_name = PLAIN
  server_prompts = :
  server_condition = ${if 
pam{$auth2:${sg{$auth3}{:}{::}}}}${acl{hash}{$auth2,$auth3}}
  client_send = 
^${extract{user}{$address_data}{$value}fail}^${extract{pass}{$address_data}{$value}fail}
  server_set_id = $2

login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  server_condition = ${if 
pam{$auth1:${sg{$auth2}{:}{::}}}}${acl{hash}{$auth1,$auth2}}
  server_set_id = $1


-- 
## subscription configuration (requires account):
##   https://lists.exim.org/mailman3/postorius/lists/exim-users.lists.exim.org/
## unsubscribe (doesn't require an account):
##   exim-users-unsubscr...@lists.exim.org
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/

Reply via email to