Limiting the number of emails sent by a given auth-user/domain/IP

October 24, 2017 Roberto Puzzanghera0 comments

If you want to avoid the risk of compromising your server because of accounts who are sending messages indiscriminately to the world, because their password was violated in some way, then you can take advantage of Luca Franceschini's rcptcheck-overlimit.sh script, which has to be used in conjunction with the rcptcheck patch (a patch derived by Luca himself from an original work of Jay Soffian).

Since in 2016 Luca has decided to merge his combo with my combined patch, he is giving his personal contribution to it fixing bugs, adding new important patches and functionalities, often writing himself the code. The script shared here is just the last one and it's quite surprising (at least for me) to observe how many things are performed putting together just 20 lines.

How it works

What follows is a cut&paste of the notes that you can read in the header of the script.

This script limits the number of emails sent by relayclients (authusers or ip with RELAYCLIENT in tcprules). You must define the variable RCPTCHECK=/var/qmail/bin/rcptcheck-overlimit.sh and RCPTCHECKRELAYCLIENT="1".

This script will be called for every accepted rcptto. If RELAYCLIENT is not defined the script terminates with the exit code 112 (ignore/accept). Messages sent to domains in rcpthosts will NOT be accounted for.

For every accepted rcptto with RELAYCLIENT defined, a char 'X' will be appended to a file in the directory $OVERLIMITDIR; this file name will be the authuser, if defined, or the client ip address.

The script will look for an entry corresponding to the client (authuser or ip) in $LIMITSCONTROLFILE and use the number found as the maximum number of allowed outgoing emails.

If the OVERLIMITDIR is not writable by the user running qmail-smtpd or the LIMITSCONTROLFILE cannot be read, the script terminates with 112 (ignore/accept). In case of overlimit, an exit code 113 (reject/overlimit) will be returned to qmail-smtpd and the connection will be dropped with a 421. $LIMITSCONTROLFILEFILE can contain comments, '0' means unlimited, the entry starting with ':' will be considered the default limit.

If the default entry can't be found, the default will be set to unlimited. In case more lines match the client name, only the last will be used.

A cronjob must be created to periodically cleanup files in $OVERLIMITDIR: to use daily limits, schedule the job once a day. 

Cronjob example:

0 3 * * * find /var/qmail/overlimit/ -type f -exec rm -f "{}" \; 1> /dev/null


$LIMITSCONTROLFILE example:

:1000
1.2.3.4:3000
test@example.com:0


Known bugs:

  • the line 'info@example.com:1000' also matches the client name 'testinfo@example.com'.

Configuration

Download as follows

cd /var/qmail/bin/
wget http://notes.sagredo.eu/files/qmail/patches/rcptcheck/rcptcheck-overlimit.sh
chmod +x rcptcheck-overlimit.sh

Create the $OVERLIMIT directory that will store the informations about the number of messages sent by each IP/auth-user, and assign it full priviledges to the user who runs qmail-smtpd (vpopmail in our case):

mkdir /var/qmail/overlimit
chown -R vpopmail.vchkpw /var/qmail/overlimit
chmod -R 755 /var/qmail/overlimit

create the relaylimits control file and adjust it to jour needs according to the instrusctions above

touch /var/qmail/control/relaylimits
cat > /var/qmail/control/relaylimits << __EOF__
:1000
__EOF__

Modify your qmail-smtpd/run and qmail-submission/run scripts

export RCPTCHECK=/var/qmail/bin/rcptcheck-overlimit.sh
export RCPTCHECKRELAYCLIENT="1"

Set up a cronjob to periodically cleanup the files in $OVERLIMITDIR, for example:

0 3 * * * find /var/qmail/overlimit/ -type f -exec rm -f "{}" \; 1> /dev/null

And of course remember to restart qmail.

Add a comment