From 4665ac6b270236d43f96f3cf9b3d93ef53c84006 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Wed, 17 Apr 2013 01:05:04 -0400 Subject: [PATCH 1/9] RF: jail.conf with entries from Debian's copy and changing existing ones to conform the "template" our unittests fail now -- will BF later --- config/jail.conf | 458 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 309 insertions(+), 149 deletions(-) diff --git a/config/jail.conf b/config/jail.conf index 7ed1bbb6..337fe0b0 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -1,9 +1,13 @@ # Fail2Ban jail specifications file # +# WARNING: heavily refactored in 0.9.0 release. Please review and +# customize settings for your setup. +# # Comments: use '#' for comment lines and ';' for inline comments # # Changes: in most of the cases you should not modify this -# file, but provide customizations in jail.local file, e.g.: +# file, but provide customizations in jail.local file, +# or separate .conf files under jail.d/ directory, e.g.: # # [DEFAULT] # bantime = 3600 @@ -11,12 +15,17 @@ # [ssh-iptables] # enabled = true # +# See jail.conf(5) man page for more information # The DEFAULT allows a global definition of the options. They can be overridden # in each jail afterwards. [DEFAULT] +# +# MISCELANEOUS 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. @@ -30,7 +39,7 @@ bantime = 600 findtime = 600 # "maxretry" is the number of failures before a host get banned. -maxretry = 3 +maxretry = 5 # "maxlines" is number of log lines to buffer for multi-line regex searches maxlines = 1 @@ -52,7 +61,7 @@ backend = auto # warn when reverse DNS lookups are performed, or ignore all hostnames in logs # # yes: if a hostname is encountered, a reverse DNS lookup will be performed. -# warn: if a hostname is encountered, a reverse DNS lookup will be performed, +# warn: if a hostname is encountered, a reverse DNS lookup will be performed, # but it will be logged as a warning. # no: if a hostname is encountered, will not be used for banning, # but it will be logged as info. @@ -66,43 +75,113 @@ usedns = warn logencoding = auto -# This jail corresponds to the standard configuration in Fail2ban 0.6. -# The mail-whois action send a notification e-mail with a whois request -# in the body. +# +# ACTIONS +# -[ssh-iptables] +# +# Destination email address used solely for the interpolations in +# jail.{conf,local} configuration files. +destemail = root@localhost -enabled = false +# Default banning action (e.g. iptables, iptables-new, +# iptables-multiport, shorewall, etc) It is used to define +# action_* variables. Can be overridden globally or per +# section within jail.local file +banaction = iptables-multiport + +# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the +# mailing. Change mta configuration parameter to mail if you want to +# revert to conventional 'mail'. +mta = sendmail + +# Default protocol +protocol = tcp + +# Specify chain where jumps would need to be added in iptables-* actions +chain = INPUT + +# +# Action shortcuts. To be used to define action parameter + +# The simplest action to take: ban only +action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report to the destemail. +action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report and relevant log lines +# to the destemail. +action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] + +# Choose default action. To change, just override value of 'action' with the +# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local +# globally (section [DEFAULT]) or per specific section +action = %(action_)s + + +# +# JAILS +# + +# +# SSH servers +# + +[sshd] + +enabled = true +port = ssh filter = sshd -action = iptables[name=SSH, port=ssh, protocol=tcp] - sendmail-whois[name=SSH, dest=you@example.com, sender=fail2ban@example.com] -logpath = /var/log/sshd.log -maxretry = 5 +logpath = /var/log/auth.log + /var/log/sshd.log -[proftpd-iptables] +[sshd-ddos] enabled = false -filter = proftpd -action = iptables[name=ProFTPD, port=ftp, protocol=tcp] - sendmail-whois[name=ProFTPD, dest=you@example.com] -logpath = /var/log/proftpd/proftpd.log -maxretry = 6 +port = ssh +filter = sshd-ddos +logpath = /var/log/auth.log + /var/log/sshd.log -# This jail forces the backend to "polling". - -[sasl-iptables] +[dropbear] enabled = false -filter = sasl -backend = polling -action = iptables[name=sasl, port=smtp, protocol=tcp] - sendmail-whois[name=sasl, dest=you@example.com] -logpath = /var/log/mail.log +port = ssh +filter = sshd +logpath = /var/log/dropbear + + +# Generic filter for PAM. Has to be used with action which bans all +# ports such as iptables-allports, shorewall + +[pam-generic] + +enabled = false +# pam-generic filter can be customized to monitor specific subset of 'tty's +filter = pam-generic +banaction = iptables-allports +# port actually must be irrelevant but lets leave it all for some possible uses +port = anyport +logpath = /var/log/auth.log + +[xinetd-fail] + +enabled = false +filter = xinetd-fail +port = all +banaction = iptables-multiport-log +logpath = /var/log/daemon.log +maxretry = 2 + +# .. custom jails # Here we use TCP-Wrappers instead of Netfilter/Iptables. "ignoreregex" is # used to avoid banning the user "myuser". -[ssh-tcpwrapper] +[sshd-tcpwrapper] enabled = false filter = sshd @@ -114,36 +193,138 @@ logpath = /var/log/sshd.log # Here we use blackhole routes for not requiring any additional kernel support # to store large volumes of banned IPs -[ssh-route] +[sshd-route] enabled = false filter = sshd action = route logpath = /var/log/sshd.log -maxretry = 5 # Here we use a combination of Netfilter/Iptables and IPsets # for storing large volumes of banned IPs # # IPset comes in two versions. See ipset -V for which one to use # requires the ipset package and kernel support. -[ssh-iptables-ipset4] +[sshd-iptables-ipset4] enabled = false filter = sshd action = iptables-ipset-proto4[name=SSH, port=ssh, protocol=tcp] logpath = /var/log/sshd.log -maxretry = 5 -[ssh-iptables-ipset6] +[sshd-iptables-ipset6] + enabled = false filter = sshd action = iptables-ipset-proto6[name=SSH, port=ssh, protocol=tcp, bantime=600] logpath = /var/log/sshd.log -maxretry = 5 -# This jail demonstrates the use of wildcards in "logpath". -# Moreover, it is possible to give other files on a new line. +# This jail uses ipfw, the standard firewall on FreeBSD. The "ignoreip" +# option is overridden in this jail. Moreover, the action "mail-whois" defines +# the variable "name" which contains a comma using "". The characters '' are +# valid too. + +[sshd-ipfw] + +enabled = false +filter = sshd +action = ipfw[localhost=192.168.0.1] + sendmail-whois[name="SSH,IPFW", dest=you@example.com] +logpath = /var/log/auth.log +ignoreip = 168.192.0.1 + + +# +# HTTP servers +# + +[apache-auth] + +enabled = false +port = http,https +filter = apache-auth +logpath = /var/log/apache*/*error.log + +# Ban hosts which agent identifies spammer robots crawling the web +# for email addresses. The mail outputs are buffered. + +[apache-badbots] + +enabled = false +port = http,https +filter = apache-badbots +logpath = /var/log/apache*/*access.log + /var/www/*/logs/access_log +bantime = 172800 +maxretry = 1 + +[apache-noscript] + +enabled = false +port = http,https +filter = apache-noscript +logpath = /var/log/apache*/*error.log +maxretry = 6 + +[apache-overflows] + +enabled = false +port = http,https +filter = apache-overflows +logpath = /var/log/apache*/*error.log +maxretry = 2 + +# Ban attackers that try to use PHP's URL-fopen() functionality +# through GET/POST variables. - Experimental, with more than a year +# of usage in production environments. + +[php-url-fopen] + +enabled = false +port = http,https +filter = php-url-fopen +logpath = /var/www/*/logs/access_log + +# A simple PHP-fastcgi jail which works with lighttpd. +# If you run a lighttpd server, then you probably will +# find these kinds of messages in your error_log: +# ALERT – tried to register forbidden variable ‘GLOBALS’ +# through GET variables (attacker '1.2.3.4', file '/var/www/default/htdocs/index.php') + +[lighttpd-fastcgi] + +enabled = false +port = http,https +filter = lighttpd-fastcgi +logpath = /var/log/lighttpd/error.log + +# Same as above for mod_auth +# It catches wrong authentifications + +[lighttpd-auth] + +enabled = false +port = http,https +filter = lighttpd-auth +logpath = /var/log/lighttpd/error.log + +[roundcube-auth] + +enabled = false +port = http,https +filter = roundcube-auth +logpath = /var/log/roundcube/userlogins + +[sogo-auth] + +enabled = false +filter = sogo-auth +port = http,https +# without proxy this would be: +# port = 20000 +logpath = /var/log/sogo/sogo.log + +# ... custom jails [apache-tcpwrapper] @@ -151,20 +332,39 @@ enabled = false filter = apache-auth action = hostsdeny logpath = /var/log/apache*/*error.log - /home/www/myhomepage/error.log maxretry = 6 -# The hosts.deny path can be defined with the "file" argument if it is -# not in /etc. -[postfix-tcpwrapper] +# +# FTP servers +# + + +[proftpd] enabled = false -filter = postfix -action = hostsdeny[file=/not/a/standard/path/hosts.deny] - sendmail[name=Postfix, dest=you@example.com] -logpath = /var/log/postfix.log -bantime = 300 +port = ftp,ftp-data,ftps,ftps-data +filter = proftpd +logpath = /var/log/proftpd/proftpd.log + +[pure-ftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = pure-ftpd +logpath = /var/log/auth.log +maxretry = 6 + +[vsftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = vsftpd +logpath = /var/log/vsftpd.log +# or overwrite it in jails.local to be +# logpath = /var/log/auth.log +# if you want to rely on PAM failed login attempts +# vsftpd's failregex should match both of those formats # Do not ban anybody. Just report information about the remote host. # A notification is sent at most every 600 seconds (bantime). @@ -178,117 +378,78 @@ logpath = /var/log/vsftpd.log maxretry = 5 bantime = 1800 -# Same as above but with banning the IP address. -[vsftpd-iptables] +[wuftpd] enabled = false -filter = vsftpd -action = iptables[name=VSFTPD, port=ftp, protocol=tcp] - sendmail-whois[name=VSFTPD, dest=you@example.com] -logpath = /var/log/vsftpd.log -maxretry = 5 -bantime = 1800 +port = ftp,ftp-data,ftps,ftps-data +filter = wuftpd +logpath = /var/log/syslog +maxretry = 6 -# Ban hosts which agent identifies spammer robots crawling the web -# for email addresses. The mail outputs are buffered. +# +# Mail servers +# -[apache-badbots] +[couriersmtp] enabled = false -filter = apache-badbots -action = iptables-multiport[name=BadBots, port="http,https"] - sendmail-buffered[name=BadBots, lines=5, dest=you@example.com] -logpath = /var/www/*/logs/access_log -bantime = 172800 -maxretry = 1 +port = smtp,ssmtp +filter = couriersmtp +logpath = /var/log/mail.log -# Use shorewall instead of iptables. - -[apache-shorewall] +[postfix] enabled = false -filter = apache-noscript -action = shorewall +port = smtp,ssmtp +filter = postfix +logpath = /var/log/mail.log + +# The hosts.deny path can be defined with the "file" argument if it is +# not in /etc. + +[postfix-tcpwrapper] + +enabled = false +filter = postfix +action = hostsdeny[file=/not/a/standard/path/hosts.deny] sendmail[name=Postfix, dest=you@example.com] -logpath = /var/log/apache2/error_log +logpath = /var/log/postfix.log +bantime = 300 -# Monitor roundcube server +# +# Mail servers authenticators: might be used for smtp,ftp,imap servers, so +# all relevant ports get banned +# -[roundcube-iptables] +[courierauth] enabled = false -filter = roundcube-auth -action = iptables[name=RoundCube, port="http,https"] -logpath = /var/log/roundcube/userlogins +port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s +filter = courierlogin +logpath = /var/log/mail.log -# Monitor SOGo groupware server - -[sogo-iptables] +[sasl] enabled = false -filter = sogo-auth -port = http, https -# without proxy this would be: -# port = 20000 +port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s +filter = sasl +# You might consider monitoring /var/log/mail.warn instead if you are +# running postfix since it would provide the same log lines at the +# "warn" level but overall at the smaller filesize. +logpath = /var/log/mail.log -action = iptables[name=SOGo, port="http,https"] -logpath = /var/log/sogo/sogo.log - -# Ban attackers that try to use PHP's URL-fopen() functionality -# through GET/POST variables. - Experimental, with more than a year -# of usage in production environments. - -[php-url-fopen] +[dovecot] enabled = false -port = http,https -filter = php-url-fopen -logpath = /var/www/*/logs/access_log -maxretry = 1 +port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s +filter = dovecot +logpath = /var/log/mail.log -# A simple PHP-fastcgi jail which works with lighttpd. -# If you run a lighttpd server, then you probably will -# find these kinds of messages in your error_log: -# ALERT – tried to register forbidden variable ‘GLOBALS’ -# through GET variables (attacker '1.2.3.4', file '/var/www/default/htdocs/index.php') -# This jail would block the IP 1.2.3.4. - -[lighttpd-fastcgi] - -enabled = false -port = http,https -filter = lighttpd-fastcgi -# adapt the following two items as needed -logpath = /var/log/lighttpd/error.log -maxretry = 2 - -# Same as above for mod_auth -# It catches wrong authentications - -[lighttpd-auth] - -enabled = false -port = http,https -filter = lighttpd-auth -# adapt the following two items as needed -logpath = /var/log/lighttpd/error.log -maxretry = 2 - -# This jail uses ipfw, the standard firewall on FreeBSD. The "ignoreip" -# option is overridden in this jail. Moreover, the action "mail-whois" defines -# the variable "name" which contains a comma using "". The characters '' are -# valid too. - -[ssh-ipfw] - -enabled = false -filter = sshd -action = ipfw[localhost=192.168.0.1] - sendmail-whois[name="SSH,IPFW", dest=you@example.com] -logpath = /var/log/auth.log -ignoreip = 168.192.0.1 +# +# DNS servers +# # These jails block attacks against named (bind9). By default, logging is off # with bind9 installation. You will need something like this: @@ -319,30 +480,33 @@ ignoreip = 168.192.0.1 # # enabled = false # filter = named-refused -# action = iptables-multiport[name=Named, port="domain,953", protocol=udp] -# sendmail-whois[name=Named, dest=you@example.com] +# port = domain,953 +# protocol = udp # logpath = /var/log/named/security.log # ignoreip = 168.192.0.1 # This jail blocks TCP traffic for DNS requests. -[named-refused-tcp] +[named-refused] enabled = false filter = named-refused -action = iptables-multiport[name=Named, port="domain,953", protocol=tcp] - sendmail-whois[name=Named, dest=you@example.com] +port = domain,953 logpath = /var/log/named/security.log ignoreip = 168.192.0.1 +# +# Miscelaneous +# + # Multiple jails, 1 per protocol, are necessary ATM: # see https://github.com/fail2ban/fail2ban/issues/37 [asterisk-tcp] enabled = false filter = asterisk -action = iptables-multiport[name=asterisk-tcp, port="5060,5061", protocol=tcp] - sendmail-whois[name=Asterisk, dest=you@example.com, sender=fail2ban@example.com] +port = 5060,5061 +protocol = tcp logpath = /var/log/asterisk/messages maxretry = 10 @@ -350,31 +514,27 @@ maxretry = 10 enabled = false filter = asterisk -action = iptables-multiport[name=asterisk-udp, port="5060,5061", protocol=udp] - sendmail-whois[name=Asterisk, dest=you@example.com, sender=fail2ban@example.com] +port = 5060,5061 +protocol = udp logpath = /var/log/asterisk/messages maxretry = 10 # To log wrong MySQL access attempts add to /etc/my.cnf: # log-error=/var/log/mysqld.log # log-warning = 2 -[mysqld-iptables] +[mysqld-auth] enabled = false filter = mysqld-auth -action = iptables[name=mysql, port=3306, protocol=tcp] - sendmail-whois[name=MySQL, dest=root, sender=fail2ban@example.com] +port = 3306 logpath = /var/log/mysqld.log -maxretry = 5 -[guacamole-iptables] +[guacamole] enabled = false filter = guacamole -action = iptables-multiport[name=Guacmole, port="http,https"] - sendmail-whois[name=Guacamole, dest=root, sender=fail2ban@example.com] +port = http,https logpath = /var/log/tomcat*/catalina.out -maxretry = 5 maxlines = 2 From 8a0ac30bd9145f1d8747e9ddce2485bd28cb51b8 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 22 Apr 2013 16:59:00 -0400 Subject: [PATCH 2/9] ENH: Throw exception if requested Jail is actually not defined at all --- fail2ban/client/jailreader.py | 8 +++++++- fail2ban/tests/clientreadertestcase.py | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 13432dc5..9943b697 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -54,7 +54,13 @@ class JailReader(ConfigReader): return self.__name def read(self): - return ConfigReader.read(self, "jail") + out = ConfigReader.read(self, "jail") + # Before returning -- verify that requested section + # exists at all + if not (self.__name in self.sections()): + raise ValueError("Jail %r was not found among available" + % self.__name) + return out def isEnabled(self): return self.__force_enable or self.__opts["enabled"] diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 5e79dc04..e55420d8 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -107,6 +107,10 @@ option = %s class JailReaderTest(unittest.TestCase): + def testIncorrectJail(self): + jail = JailReader('XXXABSENTXXX', basedir=CONFIG_DIR) + self.assertRaises(ValueError, jail.read) + def testStockSSHJail(self): jail = JailReader('ssh-iptables', basedir=CONFIG_DIR) # we are running tests from root project dir atm self.assertTrue(jail.read()) From 3ba540eca3a2274c0ef05389367e4e15f1fe706f Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 22 Apr 2013 22:23:23 -0400 Subject: [PATCH 3/9] ENH+BF: use %(__name__) by default for filter, defined enabled = false by DEFAULT Now jail.conf is really neat. BF: tests --- config/jail.conf | 108 +++++++------------------ fail2ban/tests/clientreadertestcase.py | 6 +- 2 files changed, 33 insertions(+), 81 deletions(-) diff --git a/config/jail.conf b/config/jail.conf index 651ac3b3..7a869b67 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -12,7 +12,7 @@ # [DEFAULT] # bantime = 3600 # -# [ssh-iptables] +# [sshd] # enabled = true # # See jail.conf(5) man page for more information @@ -71,22 +71,30 @@ usedns = warn # auto: will use the system locale setting logencoding = auto +# "enabled" enables the jails. +# By default all jails are disabled, and it should stay this way. +# Enable only relevant to your setup jails in your .local or jail.d/*.conf +# +# Allowed values: true, false +enabled = false + + +# "filter" defines the filter to use by the jail. +# By default jails have names matching their filter name +# +filter = %(__name__)s + # # ACTIONS # -# +# Some options used for actions + # Destination email address used solely for the interpolations in # jail.{conf,local} configuration files. destemail = root@localhost -# Default banning action (e.g. iptables, iptables-new, -# iptables-multiport, shorewall, etc) It is used to define -# action_* variables. Can be overridden globally or per -# section within jail.local file -banaction = iptables-multiport - # E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the # mailing. Change mta configuration parameter to mail if you want to # revert to conventional 'mail'. @@ -101,17 +109,23 @@ chain = INPUT # # Action shortcuts. To be used to define action parameter +# Default banning action (e.g. iptables, iptables-new, +# iptables-multiport, shorewall, etc) It is used to define +# action_* variables. Can be overridden globally or per +# section within jail.local file +banaction = iptables-multiport + # The simplest action to take: ban only action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] # ban & send an e-mail with whois report to the destemail. action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] - %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] # ban & send an e-mail with whois report and relevant log lines # to the destemail. action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] - %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] + %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] # Choose default action. To change, just override value of 'action' with the # interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local @@ -129,23 +143,18 @@ action = %(action_)s [sshd] -enabled = true -port = ssh -filter = sshd -logpath = /var/log/auth.log - /var/log/sshd.log +port = ssh +logpath = /var/log/auth.log + /var/log/sshd.log [sshd-ddos] -enabled = false -port = ssh -filter = sshd-ddos -logpath = /var/log/auth.log - /var/log/sshd.log +port = ssh +logpath = /var/log/auth.log + /var/log/sshd.log [dropbear] -enabled = false port = ssh filter = sshd logpath = /var/log/dropbear @@ -156,9 +165,7 @@ logpath = /var/log/dropbear [pam-generic] -enabled = false # pam-generic filter can be customized to monitor specific subset of 'tty's -filter = pam-generic banaction = iptables-allports # port actually must be irrelevant but lets leave it all for some possible uses port = anyport @@ -166,8 +173,6 @@ logpath = /var/log/auth.log [xinetd-fail] -enabled = false -filter = xinetd-fail port = all banaction = iptables-multiport-log logpath = /var/log/daemon.log @@ -180,7 +185,6 @@ maxretry = 2 [sshd-tcpwrapper] -enabled = false filter = sshd action = hostsdeny sendmail-whois[name=SSH, dest=you@example.com] @@ -192,7 +196,6 @@ logpath = /var/log/sshd.log [sshd-route] -enabled = false filter = sshd action = route logpath = /var/log/sshd.log @@ -204,14 +207,12 @@ logpath = /var/log/sshd.log # requires the ipset package and kernel support. [sshd-iptables-ipset4] -enabled = false filter = sshd action = iptables-ipset-proto4[name=SSH, port=ssh, protocol=tcp] logpath = /var/log/sshd.log [sshd-iptables-ipset6] -enabled = false filter = sshd action = iptables-ipset-proto6[name=SSH, port=ssh, protocol=tcp, bantime=600] logpath = /var/log/sshd.log @@ -223,7 +224,6 @@ logpath = /var/log/sshd.log [sshd-ipfw] -enabled = false filter = sshd action = ipfw[localhost=192.168.0.1] sendmail-whois[name="SSH,IPFW", dest=you@example.com] @@ -237,9 +237,7 @@ ignoreip = 168.192.0.1 [apache-auth] -enabled = false port = http,https -filter = apache-auth logpath = /var/log/apache*/*error.log # Ban hosts which agent identifies spammer robots crawling the web @@ -247,9 +245,7 @@ logpath = /var/log/apache*/*error.log [apache-badbots] -enabled = false port = http,https -filter = apache-badbots logpath = /var/log/apache*/*access.log /var/www/*/logs/access_log bantime = 172800 @@ -257,17 +253,13 @@ maxretry = 1 [apache-noscript] -enabled = false port = http,https -filter = apache-noscript logpath = /var/log/apache*/*error.log maxretry = 6 [apache-overflows] -enabled = false port = http,https -filter = apache-overflows logpath = /var/log/apache*/*error.log maxretry = 2 @@ -277,9 +269,7 @@ maxretry = 2 [php-url-fopen] -enabled = false port = http,https -filter = php-url-fopen logpath = /var/www/*/logs/access_log # A simple PHP-fastcgi jail which works with lighttpd. @@ -290,9 +280,7 @@ logpath = /var/www/*/logs/access_log [lighttpd-fastcgi] -enabled = false port = http,https -filter = lighttpd-fastcgi logpath = /var/log/lighttpd/error.log # Same as above for mod_auth @@ -300,22 +288,16 @@ logpath = /var/log/lighttpd/error.log [lighttpd-auth] -enabled = false port = http,https -filter = lighttpd-auth logpath = /var/log/lighttpd/error.log [roundcube-auth] -enabled = false port = http,https -filter = roundcube-auth logpath = /var/log/roundcube/userlogins [sogo-auth] -enabled = false -filter = sogo-auth port = http,https # without proxy this would be: # port = 20000 @@ -325,7 +307,6 @@ logpath = /var/log/sogo/sogo.log [apache-tcpwrapper] -enabled = false filter = apache-auth action = hostsdeny logpath = /var/log/apache*/*error.log @@ -339,24 +320,18 @@ maxretry = 6 [proftpd] -enabled = false port = ftp,ftp-data,ftps,ftps-data -filter = proftpd logpath = /var/log/proftpd/proftpd.log [pure-ftpd] -enabled = false port = ftp,ftp-data,ftps,ftps-data -filter = pure-ftpd logpath = /var/log/auth.log maxretry = 6 [vsftpd] -enabled = false port = ftp,ftp-data,ftps,ftps-data -filter = vsftpd logpath = /var/log/vsftpd.log # or overwrite it in jails.local to be # logpath = /var/log/auth.log @@ -368,7 +343,6 @@ logpath = /var/log/vsftpd.log [vsftpd-notification] -enabled = false filter = vsftpd action = sendmail-whois[name=VSFTPD, dest=you@example.com] logpath = /var/log/vsftpd.log @@ -378,9 +352,7 @@ bantime = 1800 [wuftpd] -enabled = false port = ftp,ftp-data,ftps,ftps-data -filter = wuftpd logpath = /var/log/syslog maxretry = 6 @@ -390,16 +362,12 @@ maxretry = 6 [couriersmtp] -enabled = false port = smtp,ssmtp -filter = couriersmtp logpath = /var/log/mail.log [postfix] -enabled = false port = smtp,ssmtp -filter = postfix logpath = /var/log/mail.log # The hosts.deny path can be defined with the "file" argument if it is @@ -407,7 +375,6 @@ logpath = /var/log/mail.log [postfix-tcpwrapper] -enabled = false filter = postfix action = hostsdeny[file=/not/a/standard/path/hosts.deny] sendmail[name=Postfix, dest=you@example.com] @@ -421,7 +388,6 @@ bantime = 300 [courierauth] -enabled = false port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s filter = courierlogin logpath = /var/log/mail.log @@ -429,9 +395,7 @@ logpath = /var/log/mail.log [sasl] -enabled = false port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s -filter = sasl # You might consider monitoring /var/log/mail.warn instead if you are # running postfix since it would provide the same log lines at the # "warn" level but overall at the smaller filesize. @@ -439,9 +403,7 @@ logpath = /var/log/mail.log [dovecot] -enabled = false port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s -filter = dovecot logpath = /var/log/mail.log # @@ -475,7 +437,6 @@ logpath = /var/log/mail.log # # [named-refused-udp] # -# enabled = false # filter = named-refused # port = domain,953 # protocol = udp @@ -486,7 +447,6 @@ logpath = /var/log/mail.log [named-refused] -enabled = false filter = named-refused port = domain,953 logpath = /var/log/named/security.log @@ -500,7 +460,6 @@ ignoreip = 168.192.0.1 # see https://github.com/fail2ban/fail2ban/issues/37 [asterisk-tcp] -enabled = false filter = asterisk port = 5060,5061 protocol = tcp @@ -509,7 +468,6 @@ maxretry = 10 [asterisk-udp] -enabled = false filter = asterisk port = 5060,5061 protocol = udp @@ -521,15 +479,11 @@ maxretry = 10 # log-warning = 2 [mysqld-auth] -enabled = false -filter = mysqld-auth port = 3306 logpath = /var/log/mysqld.log [guacamole] -enabled = false -filter = guacamole port = http,https logpath = /var/log/tomcat*/catalina.out @@ -540,8 +494,6 @@ logpath = /var/log/tomcat*/catalina.out # an infinite loop constantly feeding itself with non-informative lines [recidive] -enabled = false -filter = recidive logpath = /var/log/fail2ban.log action = iptables-allports[name=recidive] sendmail-whois-lines[name=recidive, logpath=/var/log/fail2ban.log] diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index e55420d8..f049c208 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -112,11 +112,11 @@ class JailReaderTest(unittest.TestCase): self.assertRaises(ValueError, jail.read) def testStockSSHJail(self): - jail = JailReader('ssh-iptables', basedir=CONFIG_DIR) # we are running tests from root project dir atm + jail = JailReader('sshd', basedir=CONFIG_DIR) # we are running tests from root project dir atm self.assertTrue(jail.read()) self.assertTrue(jail.getOptions()) self.assertFalse(jail.isEnabled()) - self.assertEqual(jail.getName(), 'ssh-iptables') + self.assertEqual(jail.getName(), 'sshd') def testSplitOption(self): action = "mail-whois[name=SSH]" @@ -195,7 +195,7 @@ class JailsReaderTest(unittest.TestCase): self.assertTrue(len(comm_commands)) # and we know even some of them by heart - for j in ['ssh-iptables', 'recidive']: + for j in ['sshd', 'recidive']: # by default we have 'auto' backend ATM self.assertTrue(['add', j, 'auto'] in comm_commands) # and warn on useDNS From 47a62b60729e13b6811694dc52a07cb6a71cb539 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 22 Apr 2013 22:26:42 -0400 Subject: [PATCH 4/9] ENH: by default enable a single jail -- sshd --- config/jail.conf | 9 ++++++--- fail2ban/tests/clientreadertestcase.py | 9 +++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/config/jail.conf b/config/jail.conf index 7a869b67..f7b3ee04 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -72,10 +72,12 @@ usedns = warn logencoding = auto # "enabled" enables the jails. -# By default all jails are disabled, and it should stay this way. -# Enable only relevant to your setup jails in your .local or jail.d/*.conf +# By default all (but sshd) jails are disabled. +# It is unlikely that the default value should ever be changed. +# Enable only relevant to your setup jails in your .local or jail.d/*.conf # -# Allowed values: true, false +# true: jail will be enabled and lofiles will get monitored for changes +# false: jail is not enabled enabled = false @@ -143,6 +145,7 @@ action = %(action_)s [sshd] +enabled = true port = ssh logpath = /var/log/auth.log /var/log/sshd.log diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index f049c208..8ff45d76 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -115,7 +115,7 @@ class JailReaderTest(unittest.TestCase): jail = JailReader('sshd', basedir=CONFIG_DIR) # we are running tests from root project dir atm self.assertTrue(jail.read()) self.assertTrue(jail.getOptions()) - self.assertFalse(jail.isEnabled()) + self.assertTrue(jail.isEnabled()) self.assertEqual(jail.getName(), 'sshd') def testSplitOption(self): @@ -181,7 +181,12 @@ class JailsReaderTest(unittest.TestCase): comm_commands = jails.convert() # by default None of the jails is enabled and we get no # commands to communicate to the server - self.assertEqual(comm_commands, []) + #self.assertEqual(comm_commands, []) + # by default now we have sshd jail enabled (only) + # so the list of commands should start with + self.assertEqual(comm_commands[0], ['add', 'sshd', 'auto']) + # and end with + self.assertEqual(comm_commands[-1], ['start', 'sshd']) def testReadStockJailConfForceEnabled(self): # more of a smoke test to make sure that no obvious surprises From f4a74d8d8b15dd8bfb860834c9ec37fc79a3ceb6 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 22 Apr 2013 22:42:09 -0400 Subject: [PATCH 5/9] RF: rename/unify naming of courier filters/jails --- config/filter.d/{courierlogin.conf => courier-auth.conf} | 0 config/filter.d/{couriersmtp.conf => courier-smtp.conf} | 0 config/jail.conf | 5 ++--- 3 files changed, 2 insertions(+), 3 deletions(-) rename config/filter.d/{courierlogin.conf => courier-auth.conf} (100%) rename config/filter.d/{couriersmtp.conf => courier-smtp.conf} (100%) diff --git a/config/filter.d/courierlogin.conf b/config/filter.d/courier-auth.conf similarity index 100% rename from config/filter.d/courierlogin.conf rename to config/filter.d/courier-auth.conf diff --git a/config/filter.d/couriersmtp.conf b/config/filter.d/courier-smtp.conf similarity index 100% rename from config/filter.d/couriersmtp.conf rename to config/filter.d/courier-smtp.conf diff --git a/config/jail.conf b/config/jail.conf index f7b3ee04..2021f865 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -363,7 +363,7 @@ maxretry = 6 # Mail servers # -[couriersmtp] +[courier-smtp] port = smtp,ssmtp logpath = /var/log/mail.log @@ -389,10 +389,9 @@ bantime = 300 # all relevant ports get banned # -[courierauth] +[courier-auth] port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s -filter = courierlogin logpath = /var/log/mail.log From d05e7a57469f17bc908ab40d6b796488c4c2cfa7 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 22 Apr 2013 23:47:52 -0400 Subject: [PATCH 6/9] TST: elaborate pass through the default jail.conf with basic checking of shipped filters and actions --- fail2ban/tests/clientreadertestcase.py | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 8ff45d76..7746d291 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -27,6 +27,7 @@ from fail2ban.client.configreader import ConfigReader from fail2ban.client.jailreader import JailReader from fail2ban.client.filterreader import FilterReader from fail2ban.client.jailsreader import JailsReader +from fail2ban.client.actionreader import ActionReader from fail2ban.client.configurator import Configurator TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") @@ -188,6 +189,59 @@ class JailsReaderTest(unittest.TestCase): # and end with self.assertEqual(comm_commands[-1], ['start', 'sshd']) + allFilters = set() + + # All jails must have filter and action set + # TODO: evolve into a parametric test + for jail in jails.sections(): + + filterName = jails.get(jail, 'filter') + allFilters.add(filterName) + self.assertTrue(len(filterName)) + # moreover we must have a file for it + # and it must be readable as a Filter + filterReader = FilterReader(filterName, jail, {}) + filterReader.setBaseDir(CONFIG_DIR) + self.assertTrue(filterReader.read()) # opens fine + filterReader.getOptions({}) # reads fine + + # test if filter has failregex set + self.assertTrue(filterReader._opts.get('failregex', '').strip()) + + actions = jails.get(jail, 'action') + self.assertTrue(len(actions.strip())) + + # somewhat duplicating here what is done in JailsReader if + # the jail is enabled + for act in actions.split('\n'): + actName, actOpt = JailReader.extractOptions(act) + self.assertTrue(len(actName)) + self.assertTrue(isinstance(actOpt, dict)) + if actName == 'iptables-multiport': + self.assertTrue('port' in actOpt) + + actionReader = ActionReader( + actName, jail, {}, basedir=CONFIG_DIR) + self.assertTrue(actionReader.read()) + actionReader.getOptions({}) # populate _opts + cmds = actionReader.convert() + self.assertTrue(len(cmds)) + + # all must have some actionban + self.assertTrue(actionReader._opts.get('actionban', '').strip()) + + # Verify that all filters found under config/ have a jail + def get_all_confs(d): + from glob import glob + return set( + os.path.basename(x.replace('.conf', '')) + for x in glob(os.path.join(CONFIG_DIR, d, '*.conf'))) + + # TODO: provide jails for some additional filters + # ['gssftpd', 'qmail', 'apache-nohome', 'exim', 'dropbear', 'webmin-auth', 'cyrus-imap', 'sieve'] + # self.assertEqual(get_all_confs('filter.d').difference(allFilters), + # set(['common'])) + def testReadStockJailConfForceEnabled(self): # more of a smoke test to make sure that no obvious surprises # on users' systems when enabling shipped jails From 203ddb370a936024244a5b9511304e2902bca24f Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Tue, 23 Apr 2013 10:04:39 -0400 Subject: [PATCH 7/9] PY3(BF): config reader -- handle __name__ interpolation --- fail2ban/client/configparserinc.py | 42 ++++++++++++++++++++++++-- fail2ban/tests/clientreadertestcase.py | 33 +++++++++++++++++--- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/fail2ban/client/configparserinc.py b/fail2ban/client/configparserinc.py index 7b054876..de38c32b 100644 --- a/fail2ban/client/configparserinc.py +++ b/fail2ban/client/configparserinc.py @@ -28,15 +28,45 @@ __copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko' __license__ = 'GPL' import logging, os, sys + if sys.version_info >= (3,2): # pragma: no cover - # SafeConfigParser deprecitated from python 3.2 (renamed ConfigParser) - from configparser import ConfigParser as SafeConfigParser + + # SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser) + from configparser import ConfigParser as SafeConfigParser, \ + BasicInterpolation + + # And interpolation of __name__ was simply removed, thus we need to + # decorate default interpolator to handle it + class BasicInterpolationWithName(BasicInterpolation): + """Decorator to bring __name__ interpolation back. + + Original handling of __name__ was removed because of + functional deficiencies: http://bugs.python.org/issue10489 + + commit v3.2a4-105-g61f2761 + Author: Lukasz Langa + Date: Sun Nov 21 13:41:35 2010 +0000 + + Issue #10489: removed broken `__name__` support from configparser + + But should be fine to reincarnate for our use case + """ + def _interpolate_some(self, parser, option, accum, rest, section, map, + depth): + if section and not (__name__ in map): + map = map.copy() # just to be safe + map['__name__'] = section + return super(BasicInterpolationWithName, self)._interpolate_some( + parser, option, accum, rest, section, map, depth) + else: # pragma: no cover from ConfigParser import SafeConfigParser # Gets the instance of the logger. logSys = logging.getLogger(__name__) +__all__ = ['SafeConfigParserWithIncludes'] + class SafeConfigParserWithIncludes(SafeConfigParser): """ Class adds functionality to SafeConfigParser to handle included @@ -68,6 +98,14 @@ after = 1.conf SECTION_NAME = "INCLUDES" + if sys.version_info >= (3,2): + # overload constructor only for fancy new Python3's + def __init__(self, *args, **kwargs): + kwargs = kwargs.copy() + kwargs['interpolation'] = BasicInterpolationWithName() + super(SafeConfigParserWithIncludes, self).__init__( + *args, **kwargs) + #@staticmethod def getIncludes(resource, seen = []): """ diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 7746d291..d5fee47d 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -21,7 +21,7 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko" __license__ = "GPL" -import os, shutil, tempfile, unittest +import os, shutil, sys, tempfile, unittest from fail2ban.client.configreader import ConfigReader from fail2ban.client.jailreader import JailReader @@ -47,7 +47,7 @@ class ConfigReaderTest(unittest.TestCase): """Call after every test case.""" shutil.rmtree(self.d) - def _write(self, fname, value): + def _write(self, fname, value=None, content=None): # verify if we don't need to create .d directory if os.path.sep in fname: d = os.path.dirname(fname) @@ -55,10 +55,13 @@ class ConfigReaderTest(unittest.TestCase): if not os.path.exists(d_): os.makedirs(d_) f = open("%s/%s" % (self.d, fname), "w") - f.write(""" + if value is not None: + f.write(""" [section] option = %s -""" % value) + """ % value) + if content is not None: + f.write(content) f.close() def _remove(self, fname): @@ -105,6 +108,28 @@ option = %s self._remove("c.local") self.assertEqual(self._getoption(), 1) + def testInterpolations(self): + self.assertFalse(self.c.read('i')) # nothing is there yet + self._write("i.conf", value=None, content=""" +[DEFAULT] +b = a +zz = the%(__name__)s + +[section] +y = 4%(b)s +e = 5${b} +z = %(__name__)s + +[section2] +z = 3%(__name__)s +""") + self.assertTrue(self.c.read('i')) + self.assertEqual(self.c.sections(), ['section', 'section2']) + self.assertEqual(self.c.get('section', 'y'), '4a') # basic interpolation works + self.assertEqual(self.c.get('section', 'e'), '5${b}') # no extended interpolation + self.assertEqual(self.c.get('section', 'z'), 'section') # __name__ works + self.assertEqual(self.c.get('section', 'zz'), 'thesection') # __name__ works even 'delayed' + self.assertEqual(self.c.get('section2', 'z'), '3section2') # and differs per section ;) class JailReaderTest(unittest.TestCase): From 87bac371396ee14bd37f8f40aa60c891855b3a42 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Tue, 23 Apr 2013 13:55:26 -0400 Subject: [PATCH 8/9] ENH: default port to all ports (0:65535) + remove where thus not needed + typos --- config/jail.conf | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/config/jail.conf b/config/jail.conf index 2021f865..9750d16f 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -23,7 +23,7 @@ [DEFAULT] # -# MISCELANEOUS OPTIONS +# MISCELLANEOUS OPTIONS # # "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not @@ -76,7 +76,7 @@ logencoding = auto # It is unlikely that the default value should ever be changed. # Enable only relevant to your setup jails in your .local or jail.d/*.conf # -# true: jail will be enabled and lofiles will get monitored for changes +# true: jail will be enabled and log files will get monitored for changes # false: jail is not enabled enabled = false @@ -108,6 +108,10 @@ protocol = tcp # Specify chain where jumps would need to be added in iptables-* actions chain = INPUT +# Ports to be banned +# Usually should be overridden in a particular jail +port = 0:65535 + # # Action shortcuts. To be used to define action parameter @@ -170,13 +174,10 @@ logpath = /var/log/dropbear # pam-generic filter can be customized to monitor specific subset of 'tty's banaction = iptables-allports -# port actually must be irrelevant but lets leave it all for some possible uses -port = anyport logpath = /var/log/auth.log [xinetd-fail] -port = all banaction = iptables-multiport-log logpath = /var/log/daemon.log maxretry = 2 From 62602a9ed002b9a7f53fe5f458293ac60a67ef7d Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Tue, 23 Apr 2013 13:58:58 -0400 Subject: [PATCH 9/9] Revert "ENH: by default enable a single jail -- sshd" This reverts commit 47a62b60729e13b6811694dc52a07cb6a71cb539. Enabling any jail by default should be a prerogative of particular distributions (thanks Fabian Wenk for the discussion) Conflicts: config/jail.conf --- config/jail.conf | 6 ++---- fail2ban/tests/clientreadertestcase.py | 9 ++------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/config/jail.conf b/config/jail.conf index 55d8202e..c6eea0ef 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -72,9 +72,8 @@ usedns = warn logencoding = auto # "enabled" enables the jails. -# By default all (but sshd) jails are disabled. -# It is unlikely that the default value should ever be changed. -# Enable only relevant to your setup jails in your .local or jail.d/*.conf +# By default all jails are disabled, and it should stay this way. +# Enable only relevant to your setup jails in your .local or jail.d/*.conf # # true: jail will be enabled and log files will get monitored for changes # false: jail is not enabled @@ -149,7 +148,6 @@ action = %(action_)s [sshd] -enabled = true port = ssh logpath = /var/log/auth.log /var/log/sshd.log diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index d5fee47d..62d994c8 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -141,7 +141,7 @@ class JailReaderTest(unittest.TestCase): jail = JailReader('sshd', basedir=CONFIG_DIR) # we are running tests from root project dir atm self.assertTrue(jail.read()) self.assertTrue(jail.getOptions()) - self.assertTrue(jail.isEnabled()) + self.assertFalse(jail.isEnabled()) self.assertEqual(jail.getName(), 'sshd') def testSplitOption(self): @@ -207,12 +207,7 @@ class JailsReaderTest(unittest.TestCase): comm_commands = jails.convert() # by default None of the jails is enabled and we get no # commands to communicate to the server - #self.assertEqual(comm_commands, []) - # by default now we have sshd jail enabled (only) - # so the list of commands should start with - self.assertEqual(comm_commands[0], ['add', 'sshd', 'auto']) - # and end with - self.assertEqual(comm_commands[-1], ['start', 'sshd']) + self.assertEqual(comm_commands, []) allFilters = set()