Impostare il firewall con fail2ban

16 luglio 2023 by Roberto Puzzanghera 0 commenti

Fail2ban ispeziona i log file (ad es. /var/log/apache/error_log) e banna IPs che mostrano un comportamento sospetto -- troppe password sbagliate, tentativi di  exploits, etc. Generalmente Fail2Ban è quindi usato per aggiornare le regole del  firewall al fine di rigettare gli indirizzi IP durante un intervallo di tempo settabile, benchè ogni altra azione (come l'invio di una mail di notifica) può anche altresì essere impostata. Tra le altre cose Fail2Ban mette a disposizione dei filtri per diversi servizi come apache, courier, ssh, etc.

Mostrerò brevemente come installare e configurare fail2ban per rigettare le connessioni di IP sospetti, specialmente quelli riguardanti la patch qmail-dnsrbl. Ciò evita di essere bannati noi stessi da spamhaus, che è gratuito solo fino a 100.000 query al giorno.

fail2banrichiede che si abbia un firewall come nftablesiptables attivo.

Changelog

  • Jul 15, 2023
    - l'installazione e la configurazione è stata rivista per funzionare su Debian, dove python2 non è presente (grazie a Gabriel Torres)
  • Nov 20, 2022
    -switched all actions to nftables, as it has now replaced iptables and fail2ban has support for it. Just replace "iptables" with "nftables" in your jails.
  • Nov 18, 2022
    - fail2ban upgraded to v. 1.0.2
    - jails now have a different action's declaration (iptables[type=multiport] instead of iptables-multiport[])
    - added a short note on how to configure the server with a network bridge

Scaricare e installare

Su Debian è necessario installare questi pacchetti prima di procedere con fail2ban:

apt-get install python3-pyinotify python3-systemd 2to3

Ora si può scaricare fail2ban:

cd /usr/local/src
wget https://codeload.github.com/fail2ban/fail2ban/tar.gz/1.0.2 --output-document=fail2ban-1.0.2.tar.gz
tar xvjf fail2ban-0.11.2.tar.bz2
cd fail2ban-1.0.2

Lo script setup è basato su python2. Se il sistema possiede python2 procedere con l'installazione:

chown -R root.root .
./setup.py install

Se il sistema invece ha solo python3 (ad esempio Debian) è necessario lanciare fail2ban-2to3 prima del setup:

./fail2ban-2to3
python3 setup.py install

Script di avvio

Al fine di avviare il server si può usare uno script reperibile nella cartella files/ della directory sorgente, dove se ne potrà trovare uno adatto alla propria distribuzione linux. Io uso uno script semplicissimo (scarica qui) che non ricordo più dove ho trovato.

Scarichiamo questo script in /usr/local/bin/ o dove meglio si ritiene opportuno in funzione della distribuzione usata, lanciamolo e ricordiamoci di lanciarlo anche all'avvio della macchina:

cd /usr/local/bin
wget https://notes.sagredo.eu/files/qmail/fail2banctl
chmod +x fail2banctl
fail2banctl start

logrotate script

Copiare il logrotate script dalla cartella di installazione citata sopra come segue:

cd /etc/logrotate.d
cp /usr/local/src/fail2ban-x.x.x/files/fail2ban-logrotate fail2ban

File di configurazione principale di Fail2Ban fail2ban.local

E' una buona pratica non modificare i file /etc/fail2ban/*.conf, bensì editare un file con stesso nome ma estensione .local, che sarà letto dal server dopo ogni file .conf per sovrascrivere eventualmente alcune linee che sono state modificate. Inoltre i file .local dovrebbero contenere solo le righe modificate, per evitare che, dopo un upgrade, si conservino impostazioni obsolete o incompatibili che vanno a sovrascrivere il corrispondente .conf. In ciò che segue , dove non specificato, assumeremo che che si stia lavorando in un file .local per sovrascrivere l'analogo file .conf di cui si sta parlando.

Per comprendere la terminologia e come veramente funziona fail2ban è consigliabile almeno la lettura del manuale ufficiale, che è conciso e di facile lettura.

Questo è l'unico parametro che ho modificato in fail2ban.local:

[Definition]
allowipv6 = auto

Configurazione dei jails

Abilitare i jails secondo le proprie intenzioni. Questo è ciò che ho io nel mio jail.local, per quanto riguarda la parte qmail/dovecot:

[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  = 1d
findtime = 1h


[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

Come si può notare, ci sono tre jail, quindi fail2ban andrà a leggere i file qmail-smtp.conf, vpopmail.conf e dovecot.conf sotto la directory filter.d. Mostrerò il contenuto di questi file più sotto in questa pagina.

Il jail qmail-smtp è abbinato al filtro omonimo "qmail-smtp", che intercetta le righe di "qloenvelope", che sostanzialmente registra ogni tipo di respingimento. Il filtro deve essere dichiarato nel file filter.d/qmail-smtp.conf.

Allo stesso modo, il jail vpopmail cercherà di respingere i clients che cercano di indovinare le password degli utentinella porta 587, mentre il jail dovecot farà lo stesso per quanto concerne imap/pop3.

Ricordarsi di aggiungere l'IP del proprio server e ogni altro IP fidato nella sezione DEFAULT, per evitare di bannare se stessi specialmente nel caso quache malintenzionato utilizzasse si mascherasse sotto il nostro stesso 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 <my-external-ip>

Questo è il contenuto dei file con i filtri:

qmail-smtp.conf

# 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
# @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 (I'll keep commented the old filter)
#
# @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
# 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

vpopmail.conf

[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: .* 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

qmailadmin.conf

# 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 =

roundcube-auth.local

Il filtro roundcube-auth.conf esiste già, quindi lo sovrascriviamo.

# 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 10.0.0.2 \(X-Forwarded-For: <HOST>\)
            IMAP Error: (FAILED login|Login failed) for .*? from <HOST>\.    
​
ignoreregex =

dovecot.local

Il filtro dovecot.conf esiste già, quindi lo sovrascriviamo

# 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

Configurazione delle actions

Portarsi nella cartella action.d e modificare le action secondo le proprie necessità, copiando prima il file originale in un file.local

nftables-common.local

Creare un file action.d/nftables-common.local che useremo per sovrascrivere nftables.conf.

Ho modificato la seguente opzione per bloccare tutti i protocolli anzichè il solo tcp.

protocol = tcp,udp,udplite,sctp

sendmail-common.local

Infine sarà il caso di sovrascrivere il file /etc/fail2ban/action.d/sendmail-common.conf per impostare l'email di destinazione dove inviare gli avvisi

# Fail2Ban configuration file
#
# Common settings for sendmail actions

[Init]

# Recipient mail address
#
dest = postmaster@mydomain.tld

# Sender mail address
#
sender = fail2ban@mydomain.tld

usage

Quando si modifica un jail, bisogna ricaricare i jail in questo modo:

fail2banctl reload

oppure

fail2ban-client reload

In questo modo si può ottenere la lista dei jail attivi

# fail2ban-client status
Status: fail2ban
Status
|- Number of jail:      3
`- Jail list:           vpopmail, qmail-smtp, dovecot

Prima di rendere attivo un jail è buona abitudine testare la correttezza del filtro creato utilizzando un opportuno file di log in questo modo:

# 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 con un network bridge

Nel caso i servizi siano in una rete locale dietro un network bridge, allora le regole di nftables devono essere scritte nella catena FORWARD anzichè nella catena INPUT, come normalmente fa fail2ban.

Modificare quindi il proprio file action.d/nftables-common.local come segue

# 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

Aggiungi un commento