To help somebody out on the #fail2ban irc channel, I did create a
special filter and actions, which will ban the IP address or disable the
mail account when too many e-mails are sent from an foreign IP address.
The examples below are for qmail, but they should be adaptable to other services. If you see any error or typo on this page, or have some other addition, please send an e-mail. I also create other Fail2ban filters. |
|
Table of Contents |
|
|
Sample log linesThe filter and action mention in this article use log lines in the format below. If your log lines differ, then you will maybe need to adjust the Filter qmail-ratelimit and for sure the shell script from Action qmail-disableaccount (see the line which starts withACCOUNTS= ). |
@40000000527d6f2c3a1b7724 CHKUSER accepted sender: from <fabian@wenks.ch:fabian@wenks.ch:> remote <9b1a1ab9080c4d6:unknown:::ffff:192.0.2.42> rcpt <> : sender accepted @40000000527d6f2d00660b0c CHKUSER relaying rcpt: from <fabian@wenks.ch:fabian@wenks.ch:> remote <9b1a1ab9080c4d6:unknown:::ffff:192.0.2.42> rcpt <recipient@example.com> : client allowed to relay |
Filter qmail-ratelimitThis filter is for qmail, a mail transfer agent (MTA). It is different from other Fail2ban filters, as it does not check for any failed logins, but it is used to count the amount of sent e-mails (depending on the configuration offindtime
and maxretry in the Jail
Configuration). Copy & paste from below and save it as
/etc/fail2ban/filter.d/qmail-ratelimit.local or take it from
the Complete Archive. |
# Fail2Ban configuration file for qmail-ratelimit # # Author: Fabian Wenk <fabian@wenks.ch> # 08-Nov-2013 initial publication # # $Revision$ # [Definition] # Option: failregex # Notes.: regex to match the password failures messages in the logfile. # Values: TEXT # failregex = CHKUSER (accepted sender|relaying rcpt): from \<.*@.*:.*@.*:\> remote \<.*:unknown:::ffff:<HOST>\> rcpt .* : (sender accepted|client allowed to relay)$ # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex = |
# Fail2Ban configuration file # # Author: Cyril Jaquier # Modified by Yaroslav Halchenko for multiport banning # Modified by Fabian Wenk for ban-foreign # [INCLUDES] before = iptables-blocktype.conf [Definition] # Option: actionstart # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # actionstart = iptables -N fail2ban-<name> iptables -A fail2ban-<name> -j RETURN iptables -I <chain> -p <protocol> -m multiport --dports <port> j fail2ban-<name> # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # actionstop = iptables -D <chain> -p <protocol> -m multiport --dports <port> -j fail2ban-<name> iptables -F fail2ban-<name> iptables -X fail2ban-<name> # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # actioncheck = iptables -n -L <chain> | grep -q 'fail2ban-<name>[ \t]' # Option: actionban # Notes.: command executed when banning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: See jail.conf(5) man page # Values: CMD # actionban = printf %%b "Subject: [Fail2Ban] <name>: <ip> Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` From: Fail2Ban <<sender>> To: <dest>\n `/etc/fail2ban/scripts/ban-foreign-iptables-multiport.sh <name> "<blocktype>" <ip> <logpath> <country> ban`\n " | /usr/sbin/sendmail -f <sender> <dest> # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: See jail.conf(5) man page # Values: CMD # actionunban = /etc/fail2ban/scripts/ban-foreign-iptables-multiport.sh <name> "<blocktype>" <ip> <logpath> <country> unban [Init] # Default name of the chain # name = default # Option: port # Notes.: specifies port to monitor # Values: [ NUM | STRING ] Default: # port = ssh # Option: protocol # Notes.: internally used by config reader for interpolations. # Values: [ tcp | udp | icmp | all ] Default: tcp # protocol = tcp # Option: chain # Notes specifies the iptables chain to which the fail2ban rules should # be # added # Values: STRING Default: INPUT chain = INPUT # Destination/Addressee of the mail # dest = root # Sender of the mail # sender = fail2ban |
For the above action to work also copy & paste from
below and save it as
/etc/fail2ban/scripts/ban-foreign-iptables-multiport.sh
or take it from the Complete Archive. |
#!/usr/bin/env bash # ban only foreign IP addresses and # add local (choosed country) to the ignore list of the jail # notify admin of banned IP with log lines and whois output # # Fabian Wenk <fabian@wenks.ch> # 21-Nov-2013 Initial publication # 02-Dec-2013 reworked # check if needed options are given if [ "${4}" = "" ]; then echo " Error: use ${0} <jail> <blocktype> <ip> <logpath> <country> <action>" exit 1 else if [ ! -f ${4} ]; then echo " Error: file ${4} does not exist" exit 1 else JAIL=${1} BLOCKTYPE=${2} IP=${3} LOGPATH=${4} if [ "${5}" = "" ]; then echo " Error: <country> not set, use ISO country code for source IP to ignore." echo " If you do not want to filter based on country use: DISABLED" exit 1 else COUNTRY="`echo ${5} | tr '[:lower:]' '[:upper:]'`" fi if [ "${6}" = "" ]; then echo " Error: <action> not set, use 'ban' or 'unban'." exit 1 else ACTION="${6}" fi fi fi # Define variables # Commands to ban / unban foreign IP addresses ACTIONBAN="iptables -I fail2ban-${JAIL} 1 -s ${IP} -j ${BLOCKTYPE}" ACTIONUNBAN="iptables -D fail2ban-${JAIL} -s ${IP} -j ${BLOCKTYPE}" # check if IP address is from local or foreign country and act on it WHOIS="`whois ${IP}`" CURRENTCOUNTRY="`echo "${WHOIS}" | grep ^country: | awk '{ print $2 }' | tr '[:lower:]' '[:upper:]' | uniq`" if [ "${ACTION}" = "ban" ]; then if [ ! "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then ${ACTIONBAN} echo "IP address banned:" echo "==================" else echo "IP address not banned, added to ignorelist:" echo "===========================================" fi echo echo "Affected IP address: ${IP}" echo "Affected Country: ${CURRENTCOUNTRY}" if [ "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then echo fail2ban-client set ${JAIL} addignoreip ${IP} echo echo "To manually ban this IP address, until the fail2ban-server is restarted, use:" echo " ${ACTIONBAN}" fi echo echo echo "Entries from log file:" echo "----------------------" grep ${IP} ${LOGPATH} echo echo echo "Whois output:" echo "-------------" echo "${WHOIS}" else if [ ! "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then ${ACTIONUNBAN} fi fi exit 0 |
# Fail2Ban configuration file # # Author: Nick Munger # Modified by: Ken Menzel # Daniel Black (start/stop) # Fabian Wenk (many ideas as per fail2ban users list) # Fabian Wenk (ban-foreign) # # Ensure firewall_enable="YES" in the top of /etc/rc.conf # [Definition] # Option: actionstart # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # actionstart = ipfw show | fgrep -q 'table(<table>)' || ( ipfw show | awk 'BEGIN { b = 1 } { if ($1 <= b) { b = $1 + 1 } else { e = b } } END { if (e) exit e <br> else exit b }'; num=$?; ipfw -q add $num <blocktype> <block> from table\(<table>\) to me <port>; echo $num > "<startstatefile>" ) # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # actionstop = [ ! -f <startstatefile> ] || ( read num < "<startstatefile>" <br> ipfw -q delete $num <br> rm "<startstatefile>" ) # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # actioncheck = # Option: actionban # Notes.: command executed when banning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: See jail.conf(5) man page # Values: CMD # # requires an ipfw rule like "deny ip from table(1) to me" actionban = printf %%b "Subject: [Fail2Ban] <name>: <ip> Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` From: Fail2Ban <<sender>> To: <dest>\n `/etc/fail2ban/scripts/ban-foreign-bsd-ipfw.sh <name> <table> <ip> <logpath> <country> ban`\n " | /usr/sbin/sendmail -f <sender> <dest> # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: See jail.conf(5) man page # Values: CMD # actionunban = /etc/fail2ban/scripts/ban-foreign-bsd-ipfw.sh <name> <table> <ip> <logpath> <country> unban [Init] # Option: table # Notes: The ipfw table to use. If a ipfw rule using this table already exists, # this action will not create a ipfw rule to block it and the following # options will have no effect. # Values: NUM table = 1 # Option: port # Notes.: Specifies port to monitor. Blank indicate block all ports. # Values: [ NUM | STRING ] # port = # Option: startstatefile # Notes: A file to indicate that the table rule that was added. Ensure it is unique per table. # Values: STRING startstatefile = /var/run/fail2ban/ipfw-started-table_<table> # Option: block # Notes: This is how much to block. # Can be "ip", "tcp", "udp" or various other options. # Values: STRING block = ip # Option: blocktype # Notes.: How to block the traffic. Use a action from man 5 ipfw # Common values: deny, unreach port, reset # ACTION defination at the top of man ipfw for allowed values. # Values: STRING # blocktype = unreach port # Destination/Addressee of the mail # dest = root # Sender of the mail # sender = fail2ban |
For the above action to work also copy & paste from
below and save it as
/etc/fail2ban/scripts/ban-foreign-bsd-ipfw.sh
or take it from the Complete Archive. |
#!/usr/bin/env bash # ban only foreign IP addresses and # add local (choosed country) to the ignore list of the jail # notify admin of banned IP with log lines and whois output # # Fabian Wenk <fabian@wenks.ch> # 21-Nov-2013 Initial publication # 28-Nov-2013 Adapted for bsd-ipfw # 02-Dec-2013 reworked # check if needed options are given if [ "${4}" = "" ]; then echo " Error: use ${0} <jail> <table> <ip> <logpath> <country> <action>" exit 1 else if [ ! -f ${4} ]; then echo " Error: file ${4} does not exist" exit 1 else JAIL=${1} TABLE=${2} IP=${3} LOGPATH=${4} if [ "${5}" = "" ]; then echo " Error: <country> not set, use ISO country code for source IP to ignore" exit 1 else COUNTRY="`echo ${5} | tr '[:lower:]' '[:upper:]'`" fi if [ "${6}" = "" ]; then echo " Error: <action> not set, use 'ban' or 'unban'." exit 1 else ACTION="${6}" fi fi fi # Define variables # Commands to ban / unban foreign IP addresses ACTIONBAN="ipfw table ${TABLE} add ${IP}" ACTIONUNBAN="ipfw table ${TABLE} delete ${IP}" # function for reporting to admin WHOIS="`whois ${IP}`" CURRENTCOUNTRY="`echo "${WHOIS}" | grep ^country: | awk '{ print $2 }' | tr '[:lower:]' '[:upper:]' | uniq`" if [ "${ACTION}" = "ban" ]; then if [ ! "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then ${ACTIONBAN} echo "IP address banned:" echo "==================" else echo "IP address not banned, added to ignorelist:" echo "===========================================" fi echo echo "Affected IP address: ${IP}" echo "Affected Country: ${CURRENTCOUNTRY}" if [ "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then echo fail2ban-client set ${JAIL} addignoreip ${IP} echo echo "To manually ban this IP address, until the fail2ban-server is restarted, use:" echo " ${ACTIONBAN}" fi echo echo echo "Entries from log file:" echo "----------------------" grep ${IP} ${LOGPATH} echo echo echo "whois output:" echo "-------------" echo "${WHOIS}" else if [ ! "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then ${ACTIONUNBAN} fi fi exit 0 |
Action qmail-disableaccountThis action will disable SMTP accounts for qmail, but only when e-mails are sent from IP addresses of foreign countries and not from one configured local country. The IP address from the local country will be added to the ignoreip list of the configured jail so the script does not need to be run to often. This action does also send a notification e-mail to the user with an URL where you can give detailed instructions. It also does send a notification e-mail with useful information to the admin. Copy & paste from below and save it as/etc/fail2ban/action.d/qmail-disableaccount.local or take it
from the Complete Archive. |
# Fail2Ban configuration file for qmail-ratelimit # # Author: Fabian Wenk <fabian@wenks.ch> # 12-Nov-2013 initial publication # 21-Nov-2013 small adjustments # 02-Dec-2013 small adjustments # # $Revision$ # [Definition] # Option: actionstart # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # actionstart = # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # actionstop = # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # actioncheck = # Option: actionban # Notes.: command executed when banning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: See jail.conf(5) man page # Values: CMD # actionban = printf %%b "Subject: [Fail2Ban] <name>: <ip> Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` From: Fail2Ban <<sender>> To: <dest>\n `/etc/fail2ban/scripts/qmail-disableaccount.sh <name> <ip> <logpath> <country> <url>`\n " | /usr/sbin/sendmail -f <sender> <dest> # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: See jail.conf(5) man page # Values: CMD # actionunban = [Init] # Default name of the chain # name = default # Destination/Addressee of the mail # dest = root # Sender of the mail # sender = fail2ban |
For the above action to work also copy & paste from
below and save it as
/etc/fail2ban/scripts/qmail-disableaccount.sh
or take it from the Complete Archive. |
#!/usr/bin/env bash # parse log messages from qmail, disable smtp account and notfiy user # add local (choosed country) to the ignore list of the jail # notify admin of "banned" IP with log lines and whois output # # Fabian Wenk <fabian@wenks.ch> # 12-Nov-2013 Initial publication # 21-Nov-2013 small corrections # 02-Dec-2013 reworked # check if needed options are given if [ "${3}" = "" ]; then echo " Error: use ${0} <jail> <ip> <logpath> <country> <url>" exit 1 else if [ ! -f ${3} ]; then echo " Error: file ${3} does not exist" exit 1 else JAIL=${1} IP=${2} LOGPATH=${3} if [ "${4}" = "" ]; then echo " Error: <country> not set, use ISO country code for source IP to ignore." echo " If you do not want to filter based on country use: DISABLED" exit 1 else COUNTRY="`echo ${4} | tr '[:lower:]' '[:upper:]'`" fi if [ "${5}" = "" ]; then echo " Error: <url> not set." exit 1 else URL="${5}" fi fi fi # Define variables # Command to disable account (e-mail address will be appended): COMMANDTODISABLEACCOUNT="vmoduser -d -p -w -i" # Subject of the e-mail to the disabled account (e-mail address will be appended): SUBJECT="SMTP access disabled for" # Mail body text sent to the disabled account: MAILTEXT="Dear User We had to disable your SMTP access for your account, for more information please visit: ${URL} Best Regards" # check if IP address is from a foreign country and act on it WHOIS="`whois ${IP}`" CURRENTCOUNTRY="`echo "${WHOIS}" | grep ^country: | awk '{ print $2 }' | tr '[:lower:]' '[:upper:]' | uniq`" LOGLINES="`grep ${IP} ${LOGPATH}`" ACCOUNTS="`echo "${LOGLINES}" | grep 'CHKUSER accepted sender' | awk '{ print $6 }' | sed 's/^<.*:\(.*\):>$/\1/' | sort | uniq`" if [ ! "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then # disabling accounts and send info to user (and admin) for i in ${ACCOUNTS} ; do ${COMMANDTODISABLEACCOUNT} ${i} echo "${MAILTEXT}" | mailx -s "${SUBJECT} ${i}" ${i} done echo "E-mail accounts disabled:" echo "=========================" echo echo "Because of abuse from ${IP} the following accounts had been disabled:" echo echo "${ACCOUNTS}" else echo "No e-mail account disabled, IP address added to ignorelist:" echo "===========================================================" fi echo echo "Affected IP address: ${IP}" echo "Affected Country: ${CURRENTCOUNTRY}" if [ "${CURRENTCOUNTRY}" = "${COUNTRY}" ]; then echo fail2ban-client set ${JAIL} addignoreip ${IP} echo echo "To manually disable this e-mail accounts, use:" for i in ${ACCOUNTS} ; do echo " ${COMMANDTODISABLEACCOUNT} ${i}" done echo echo "Do not forget to inform the user!" fi echo echo echo "Entries from log file:" echo "----------------------" echo "${LOGLINES}" echo echo echo "Whois output:" echo "-------------" echo "${WHOIS}" exit 0 |
Jail ConfigurationTo use the above actions (ban-foreign-iptables-multiport, ban-foreign-bsd-ipfw or qmail-disableaccount) copy & paste the corresponding entry from below to your/etc/fail2ban/jail.local file or take it from the Complete Archive.
Be sure to change enabled = false to enabled =
true and also adjust country= , url= and
dest= (You do not want to send me e-mails with the details
out of your log files!) parmeters. Eventually also adjust both
logpath= occurrences for the jail you use.
For all three jails even if a local IP address is matched, fail2ban will add the IP address to the list of banned IP addresses, but the script which is started from the action takes care, that in this case no IP address is banned or the account is disabled. But still, after the bantime is reached fail2ban will unban it, but for local IP
addresses with just doing nothing. For the [qmail-disable]
jail the bantime is not relevant, but still used, so it is
the best to leave it at 0 . In the fail2ban.log ban and unban
are logged anyway, depending on the loglevel you have
set. |
[DEFAULT] ignoreip = 127.0.0.1 # qmail-foreign with iptables-multiport [qmail-foreign] enabled = false filter = qmail-ratelimit action = ban-foreign-iptables-multiport[name=qmail-foreign, port="25,465,587", logpath=/var/log/qmail/smtpd/current, country=CH, dest=fabian@wenks.ch] logpath = /var/log/qmail/smtpd/current findtime = 10 maxretry = 5 bantime = 7200 # qmail-foreign with bsd-ipfw [qmail-foreign] enabled = false filter = qmail-ratelimit action = ban-foreign-bsd-ipfw[name=qmail-foreign, port="25,465,587", table=25, logpath=/var/log/qmail/smtpd/current, country=CH, dest=fabian@wenks.ch] logpath = /var/log/qmail/smtpd/current findtime = 10 maxretry = 5 bantime = 7200 # qmail-disable accounts [qmail-disable] enabled = false filter = qmail-ratelimit action = qmail-disableaccount[name="qmail-disable", logpath=/var/log/qmail/smtpd/current, country=CH, url="http://www.example.com/", dest=fabian@wenks.ch] logpath = /var/log/qmail/smtpd/current findtime = 120 maxretry = 50 bantime = 0 |
Complete ArchiveDownload the complete fail2ban-action-with-script.tgz archive, which contains all the files from this article. Extract it and copy the needed files into the corresponding directories in your existing/etc/fail2ban/ directory. |
Document History |
|
02-Dec-2013 | Initial publication |
Fabian Wenk | last update 02-Dec-2013 |