November 20, 2022 Roberto Puzzanghera 19 comments
Fail2ban scans log files (e.g. /var/log/apache/error_log) and bans IPs that show the malicious signs -- too many password failures, seeking for exploits, etc. Generally Fail2Ban is then used to update firewall rules to reject the IP addresses for a specified amount of time, although any arbitrary other action (e.g. sending an email) could also be configured. Out of the box Fail2Ban comes with filters for various services (apache, courier, ssh, etc).
I will show shortly how to install and configure fail2ban
to ban malicious IPs, especially those related to the qmail-dnsrbl
patch. This will avoid to be banned ourselves by spamhaus
, which is free up to 100.000 queries per day.
fail2ban
requires that you have a firewall as nftables
or iptables
active.
nftables
, as it has now replaced iptables
and fail2ban
has support for it. Just replace "iptables" with "nftables" in your jails.cd /usr/local/src wget --no-check-certificate https://github.com/fail2ban/fail2ban/archive/1.0.2.tar.gz --output-document=fail2ban-1.0.2.tar.gz tar xzf fail2ban-1.0.2.tar.gz cd fail2ban-1.0.2 chown -R root:root . ./setup.py install
In order to start the server you can use an init script that you can copy from the files/
folder of the source dir, where you can probably find one suitable for your distribution. I use this one (download here) that I don't remember where I found:
#!/bin/sh # # Copyright (c) 2008-2013, Nishant Limbachia, Hoffman Estates, IL, USA # # /usr/local/bin/fail2banctl # # start|stop|restart|reload|status|ping fail2ban server # # To start fail2ban automatically at boot, make this file executable: # chmod 755 /usr/local/bin/fail2banctl # you must also add this to rc.local for fail2ban to start during boot. # default socket file is /var/run/fail2ban/fail2ban.sock which can be # changed via the config file: /etc/fail2ban/fail2ban.conf fail2ban_start() { if [ -x /usr/local/bin/fail2banctl ]; then echo "Starting fail2ban: " ### using -x option to remove any stale socket file. /usr/bin/fail2ban-client -x start fi } fail2ban_stop() { echo "Stopping fail2ban" /usr/bin/fail2ban-client stop } fail2ban_reload() { echo "Reloading fail2ban" /usr/bin/fail2ban-client reload } fail2ban_status() { echo "Status: fail2ban" /usr/bin/fail2ban-client status } fail2ban_ping() { echo "Pinging fail2ban" /usr/bin/fail2ban-client ping } case "$1" in 'start') fail2ban_start ;; 'stop') fail2ban_stop ;; 'restart') fail2ban_stop sleep 5 fail2ban_start ;; 'reload') fail2ban_reload ;; 'status') fail2ban_status ;; 'ping') fail2ban_ping ;; *) echo "USAGE: $0 start|stop|restart|reload|status|ping" exit 1 ;; esac
Copy in /usr/local/bin
or wherever you want, run it and remember to launch it at boot time as well:
cd /usr/local/bin wget https://notes.sagredo.eu/files/qmail/fail2banctl chmod +x fail2banctl fail2banctl start
You can copy a logrotate script from the install dir as follows:
cd /etc/logrotate.d cp /usr/local/src/fail2ban-x.x.x/files/fail2ban-logrotate fail2ban
To understand the terminology and how fail2ban
works you are invited to read the manual (quite concise and easy to read).
It is a good practice not to modify the /etc/fail2ban/*.conf
files, but edit a customized file with a .local
extension, which will be read by the server after each .conf to eventually overwrite the lines that you modified.
cd /etc/fail2ban cp jail.conf jail.local
Enable the jails according to your needs.
This is what I have in my jail.local, concerning the qmail/dovecot
part:
[qmail-smtp] enabled = true filter = qmail-smtp action = nftables[type=multiport, name=SMTP, port="25,465,587"] sendmail-whois-lines[name=SMTP, logpath="%(logpath)s"] logpath = /var/log/qmail/smtpd/current maxretry = 5 bantime = 1d findtime = 1h [qmail-submission] enabled = true filter = qmail-smtp action = nftables[type=multiport, name=SUBMISSION, port="25,465,587"] sendmail-whois-lines[name=SUBMISSION, logpath="%(logpath)s"] logpath = /var/log/qmail/submission/current maxretry = 5 bantime = 1d findtime = 1h [vpopmail] enabled = true filter = vpopmail action = nftables[type=multiport, name=VPOPMAIL, port="25,465,587"] sendmail-whois-lines[name=VPOPMAIL, logpath="%(logpath)s"] # check your syslog mail related log (mail.log in some systems) logpath = /var/log/maillog maxretry = 5 bantime = 86400 findtime = 3600 [qmailadmin] enabled = true filter = qmailadmin action = nftables[type=multiport, name=QMA, port="80,443"] sendmail-whois-lines[name=QMA, logpath="%(logpath)s"] logpath = /var/log/qma-auth.log maxretry = 4 bantime = 1d findtime = 1h [roundcube-auth] enabled = true filter = roundcube-auth action = nftables[type=multiport, name=RC, port="80,443"] sendmail-whois-lines[name=RC, logpath="%(logpath)s"] logpath = /var/www/roundcube/logs/userlogins.log maxretry = 4 bantime = 1d findtime = 1h [dovecot-pop3] enabled = true filter = dovecot action = nftables[type=multiport, name=POP3, port="993,995"] sendmail-whois-lines[name=POP3, logpath="%(logpath)s"] logpath = /var/log/dovecot/dovecot.log maxretry = 6 bantime = 1h findtime = 1h [dovecot-imap] enabled = true filter = dovecot action = nftables[type=multiport, name=IMAP, port="993,995"] sendmail-whois-lines[name=IMAP, logpath="%(logpath)s"] logpath = /var/log/dovecot/dovecot.log maxretry = 6 bantime = 1h findtime = 1h
As you can see, we have three jails, so fail2ban
will look for the files qmail-smtp.conf
, vpopmail.conf
and dovecot.conf
under the filter.d
directory. I'll show the content of these files below.
The qmail-smtp jail is related to a filter named "qmail-smtp" which matches lines in the qmail-smtp
log mainly related to the qlogenvelope
line, which records almost all kind of rejects. The filter has to be declared in the filter.d/qmail-smtp.conf
file.
Similarly, the vpopmail
jail will try to ban clients trying to guess the users' password in the submission
port, while the dovecot
jail will do the same as far as imap/pop3
is concerned.
Remember to add your server's IP and any other trusted IP in the DEFAULT section, just to avoid to ban yourself expecially in case someone is imitating your own IP (spoofing):
[DEFAULT] # # MISCELLANEOUS OPTIONS # # "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not # ban a host which matches an address in this list. Several addresses can be # defined using space separator. ignoreip = 127.0.0.1/8 10.0.0.1/8 91.121.144.116
Here is the content of the filter files:
# Fail2Ban filters for qmail-smtp patched for qmail-dnsbl (http://qmail-dnsbl.sourceforge.net), chkuser (http://opensource.interazioni.it/qmail/chkuser.html) and greetdelay # # Here is an example of log lines that this filter is going to hit: # # @40000000545076ad1de678ec GREETDELAY from 77.65.15.93: client sent data before greeting # qmail-smtpd: read failed: (null) from 95.141.38.94 to (null) helo host220-227-149-62.serverdedicati.aruba.it # @4000000055154dc40e884894 qmail-smtpd: timeout: (null) from 95.141.38.94 to (null) helo host220-227-149-62.serverdedicati.aruba.it # # All lines concerning chkuser, qmail-dnsbl and others like these are now catched by the qlogenvelope line: # # @4000000059f5194706e649ec CHKUSER accepted sender: from <sender@remotedomain.xy|remoteinfo/auth:|chkuser-identify:> remote <helo:free-112-191.mediaworksit.net|remotehostname:unknown|remotehostip:95.140.112.191> rcpt <> : sender accepted # @4000000059f519470be7b0fc CHKUSER accepted rcpt: from <sender@remotedomain.xy|remoteinfo/auth:|chkuser-identify:> remote <helo:free-112-191.mediaworksit.net|remotehostname:unknown|remotehostip:95.140.112.191> rcpt <localuser@localdomain.xy> : found existing recipient # @4000000059f519470be860c4 qmail-smtpd[20003]: rcptcheck: checking <localuser@localdomain.xy> at 95.140.112.191 # @4000000059f519470c084ca4 qmail-smtpd[20003]: rcptcheck: ignore address <localuser@localdomain.xy> at 95.140.112.191 # @4000000059f5195c1f6d7e7c qmail-smtpd[20003]: rbl: ip=95.140.112.191 query=191.112.140.95.zen.spamhaus.org result=ignore message='' # @4000000059f5195c211f1294 qmail-smtpd[20003]: rbl: ip=95.140.112.191 query=191.112.140.95.b.barracudacentral.org result=reject message='Client host blocked using Barracuda Reputation, see http://www.barracudanetworks.com/reputation/?r=1&ip=95.140.112.191' # @4000000059f5195c211f2234 qlogenvelope: result=rejected code=553 reason=rblreject detail=b.barracudacentral.org helo=free-112-191.mediaworksit.net mailfrom=sender@remotedomain.xy rcptto=localuser@localdomain.xy relay=no rcpthosts=yes size= authuser= authtype= encrypted= sslverified=no localip=10.0.0.4 localport=25 remoteip=95.140.112.191 remoteport=15630 remotehost= qp= pid=20003 # @4000000059f5195c28b8b49c qmail-smtpd: read failed: sender@remotedomain.xy from 95.140.112.191 to localuser@localdomain.xy helo free-112-191.mediaworksit.net # 2022-02-18 16:23:03.719762500 helo-dns-check: blocked with: HELO doesn't match IP [91.121.144.116] # # Be aware that the following regex match only my patched chkuser at https://notes.sagredo.eu/en/qmail-notes-185/patching-qmail-82.html # If you are using a standard version of chkuser you can refer to this page for the correct filter: http://wiki.qmailtoaster.com/index.php/Fail2Ban [Definition] failregex = qlogenvelope: result=rejected .* remoteip=<HOST> helo-dns-check: blocked with: .* \[<HOST>\] GREETDELAY from <HOST>: client sent data before greeting qmail-smtpd: reject \(auth not available\): \(null\) from <HOST> ignoreregex = # DEV Notes: # # Author: Roberto Puzzanghera
[Definition] # Jul 10 12:05:53 qmail vpopmail[3076]: vchkpw-submission: vpopmail user not found helpdesk@yourdomain.xy:191.233.70.140 # Jul 22 17:31:46 qmail vpopmail[6383]: vchkpw-submission: password fail (pass: 'dasdas') postmaster@yourdomain.xy:1.2.3.4 failregex = vchkpw-submission: vpopmail user not found .*:<HOST>$ vchkpw-submission: password fail .*:<HOST>$ # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. ignoreregex = # DEV Notes: # # Author: Roberto Puzzanghera
# bans qmailadmin login attempts looking for lines like this # 2015/05/27 15:45:58 user:postmaster@domain.xy ip:1.2.3.4 auth:failed [@domain.xy] # qmailadmin must be patched with http://notes.sagredo.eu/sites/notes.sagredo.eu/files/qmail/patches/qmailadmin/qmailadmin-1.2.16-log.patch # (thanks to Tony) [INCLUDES] before = common.conf [Definition] failregex = ip:<HOST> auth:failed ignoreregex =
The filter roundcube-auth.conf
already exists, so we'll overwrite it.
# Fail2Ban configuration file for roundcube webmail # # Author: Roberto Puzzanghera # 15/07/2022 # # Log line to match (the 1st one in case of rc behind a firewall) # [12-Jul-2022 08:56:39 +0200]: <3lq5onb8> Failed login for postmaster from 10.0.0.2 (X-Forwarded-For: 2.42.23.100) in session 3lq5onb87b7oqnc7 (error: 1) # [01-Sep-2014 00:07:11 +0200]: IMAP Error: Login failed for sisgri@iol.it from 151.55.133.38. AUTHENTICATE PLAIN: Authentication failed. in /usr/local/www/htdocs/roundcubemail-1.0.2/progr> [INCLUDES] before = common.conf [Definition] failregex = Failed login for from .* \(X-Forwarded-For: <HOST>\) IMAP Error: (FAILED login|Login failed) for .*? from <HOST>\. ignoreregex =
The filter dovecot.conf
already exists, so we'll overwrite it.
# Fail2Ban filter Dovecot authentication and pop3/imap server # # Jul 22 23:33:29 auth-worker(27283): Info: sql(user@yourdomain.xy:1.2.3.4): Password mismatch # Jul 22 23:33:31 imap-login: Info: Disconnected (auth failed, 1 attempts in 2 secs): user=<user@yourdomain.xy>, method=PLAIN, rip=1.2.3.4, lip=5.6.7.8, session=<k2t5+c7+5AAKAAAC> # Jul 22 23:34:04 auth-worker(27283): Info: sql(adminww@yourdomain.xy:1.2.3.4): unknown user # Jul 22 23:34:06 imap-login: Info: Disconnected (auth failed, 1 attempts in 2 secs): user=<adminww@yourdomain.xy>, method=PLAIN, rip=1.2.3.4, lip=5.6.7.8, session=<ONqY+87+7gAKAAAC> [Definition] failregex = \(\S*,<HOST>(?:,\S*)?\): (?:unknown user|invalid credentials|Password mismatch) ignoreregex = # DEV Notes: # # Author: Roberto Puzzanghera
Finally you may want to overwrite the file /etc/fail2ban/action.d/sendmail-common.conf
just to set the recipient email address where to send the alerts
# Fail2Ban configuration file # # Common settings for sendmail actions [Init] # Recipient mail address # dest = postmaster@yourdomain.xy # Sender mail address # sender = fail2ban@yourdomain.xy
Locate to the action.d directory and modify the action you are using to your needs, always copying the original .conf file in a .local
I did the following modication to ban all protocols as default, instead of banning the only tcp
protocol = tcp,udp,udplite,sctp
Remember to put you destination email here.
When you modify something, you have to reload the jails in this way:
fail2banctl reload
or simply
fail2ban-client reload
Look at the jail list
# fail2ban-client status Status: fail2ban Status |- Number of jail: 3 `- Jail list: vpopmail, qmail-smtp, dovecot
Before you turn on a jail it's always a good practice to test your newly created filter against a log file as follows:
# fail2ban-regex /var/log/qmail/smtpd/current /etc/fail2ban/filter.d/qmail-smtp.conf Running tests ============= Use failregex file : /etc/fail2ban/filter.d/qmail-smtp.conf Use log file : /var/log/qmail/smtpd/@40000000532f677b088a7854.s Results ======= Failregex: 65 total |- #) [# of hits] regular expression | 1) [58] qmail-smtpd: message rejected \(qmail-dnsbl\) .* from | 2) [3] CHKUSER rejected rcpt: from <.*> remote <.*remotehostip:> .* : not existing recipient$ | 3) [4] CHKUSER rejected relaying: from <.*> remote <.*remotehostip:> .* : client not allowed to relay$ `- Ignoreregex: 0 total Date template hits: |- [# of hits] date format | [1596] TAI64N `- Lines: 1596 lines, 0 ignored, 65 matched, 1531 missed Missed line(s): too many to print. Use --print-all-missed to print all 1531 lines
fail2ban
with a network bridgeIn case your services are in a localnet and the packets to be filtered go through a network bridge, then your nftables
rules must be written into the FORWARD
chain instead of the INPUT
one, like fail2ban
normally does.
Modify your nftables.local action as follows
# Option: chain_hook # Notes.: refers to the kind of chain to be created # Values: [ prerouting | input | forward | output | postrouting ] Default: input # chain_hook = forward # was input
qq_temporary_problem_(#4.3.0)
June 2, 2023 06:32
qq_temporary_problem_(#4.3.0)
June 1, 2023 21:18
qq_temporary_problem_(#4.3.0)
May 31, 2023 18:22
qq_temporary_problem_(#4.3.0)
May 31, 2023 14:42
qq_temporary_problem_(#4.3.0)
May 31, 2023 14:33
Thank you! for all the documentation, patches and support
May 26, 2023 08:42
free(): double free detected in tcache 2: /var/www/qmail/cgi-bin/qmailadmin
May 17, 2023 15:25
free(): double free detected in tcache 2: /var/www/qmail/cgi-bin/qmailadmin
May 17, 2023 07:46
Tags
apache clamav dkim dovecot ezmlm fail2ban hacks lamp letsencrypt linux linux-vserver lxc mariadb mediawiki mozilla mysql openboard owncloud patches php proftpd qmail qmail to postfix qmail-spp qmailadmin rbl roundcube rsync sieve simscan slackware solr spamassassin spf ssh ssl surbl tcprules tex ucspi-tcp vpopmail vqadmin
Comments
Fail2ban alternative
Yasuo Ohgaki September 28, 2022 02:51
Fail2ban requires obsolete setuptools and feature. It seems it is not maintained, so I published my simple IP blocker to github.
https://github.com/yohgaki/ssblocker
Reply | Permalink
Fail2ban alternative
Roberto Puzzanghera Yasuo Ohgaki September 28, 2022 07:12
Thanks. Fail2ban is alive as a new major version was released yesterday
Reply | Permalink
qlogenvelope: reason=authfailed
nic November 20, 2019 05:33
Hi Roberto,
Having a lot of
Fail2ban did not pick them up. About 20 of them within 1 min
Please help.
Thanks
nic
Reply | Permalink
qlogenvelope: reason=authfailed
Roberto Puzzanghera nic November 20, 2019 14:52
What do you have in your fail2ban rule? Can you post the entire log line?
In my example in the fail2ban page I have
but this cannot match the line you posted, as it misses the remoteip string
Reply | Permalink
qlogenvelope: reason=authfailed
nic Roberto Puzzanghera November 29, 2019 04:49
I have the same as you. Duplicated from the site
Reply | Permalink
qlogenvelope: reason=authfailed
Roberto Puzzanghera nic November 29, 2019 16:47
Can you check that the filter was actually loaded:
If yes check that the filter is matching lines against your log files
Reply | Permalink
qlogenvelope: reason=authfailed
nic Roberto Puzzanghera November 29, 2019 17:00
My results is very different from yours.
Reply | Permalink
qlogenvelope: reason=authfailed
Roberto Puzzanghera nic November 29, 2019 18:52
Are sure that you have those qlogenvelope lines in the log files?
In that case try to write from scratch the filter, because it's not working
Reply | Permalink
Updates
Gabriel Torres June 25, 2019 23:11
Hi,
Fail2ban is now on github. So the tutorial should be updated as:
Also, the manual is now at https://github.com/fail2ban/fail2ban/wiki so the below paragraph should be updated:
Reply | Permalink
Updates
Roberto Puzzanghera Gabriel Torres June 26, 2019 20:05
Thanks for pointing out that. I suggest to download the sources in this way because this page concerns the 0.10 version that I have already tested with my configutation, otherwise the 0.11-dev version will be downloaded
Reply | Permalink
Updates
Gabriel Torres Roberto Puzzanghera June 27, 2019 01:21
Cool, no worries.
Also, I made a mistake, I recommended the wiki, but the manual available for version 0.80 and linked in the tutorial is more complete.
Reply | Permalink
qmail-smtpd fail2ban
nic October 29, 2017 07:23
Hi, fail2ban is not blocking
Any idea?
Thanks
nic
Reply | Permalink
Re: qmail-smtpd fail2ban
Roberto Puzzanghera nic October 29, 2017 08:19
I can confirm that it is hitting those events here... double check everything
Reply | Permalink
ylmf-pc - fail2ban
nic January 2, 2016 15:47
Hi Roberto,
qmail-smtp fail2ban is not catching ylmf-pc
What can i do to get it working?
Thanks
nic
Reply | Permalink
Hi Nic,
roberto puzzanghera nic January 2, 2016 15:58
Hi Nic,
according to my examples, fail2ban is tuned with a "qmail-smtpd: read failed:" string, not with a particular helo string. In my example there must be two such events within an hour (findtime parameter).
If you want to match other string you have to modify your qmail filter accordingly
Reply | Permalink
Wrong log path for vpopmail / qmail-submission
Otto Dandenell September 13, 2014 23:10
Hi,
In /etc/fail2ban/jail.local, in the [vpopmail] section, you have:
But in the scripts setting up qmail-submission (which is the service listening on port 587) the log file path is set to:
(See http://notes.sagredo.eu/node/83)
Regards
/ Otto
Reply | Permalink
That's correct
roberto puzzanghera Otto Dandenell September 14, 2014 19:56
That's correct, Otto. The failed login attempts are logged exactly there.
Reply | Permalink
Sorry, I was expecting the
Otto Dandenell roberto puzzanghera September 15, 2014 08:22
Sorry, I was expecting the submission service to log to that fiile, but I suppose the login comes earlier in the chain and those errors are routed to a custom location?
However, after searching through my logs, the failed login attempts from the submission service are logged in:
(Please notice the dot).
Not sure wher this is configured?
Regards
/ Otto
Reply | Permalink
vpopmail and syslog
roberto puzzanghera Otto Dandenell September 15, 2014 14:39
You are right. The log are directed to syslog (look around line no. 679 of vchkpw.c). My slackware put all mail.* logs in /var/log/maillog, so it's worth that I clarify this point as soon as possible.
But you can manage what syslog is going to write at configure time:
The second one is not very clear to me, but maybe can adjust the log file name.
As an alternative you may want to record your logs on mysql
but this is not convenient if you are going to use fail2ban
Reply | Permalink