diff --git a/.etckeeper b/.etckeeper index f128a5c..acf810f 100755 --- a/.etckeeper +++ b/.etckeeper @@ -22,6 +22,12 @@ mkdir -p './dnf/aliases.d' mkdir -p './dnf/modules.defaults.d' mkdir -p './dnf/plugins/copr.d' mkdir -p './exports.d' +mkdir -p './fail2ban/fail2ban.d' +mkdir -p './firewalld/helpers' +mkdir -p './firewalld/icmptypes' +mkdir -p './firewalld/ipsets' +mkdir -p './firewalld/policies' +mkdir -p './firewalld/services' mkdir -p './glvnd' mkdir -p './gnupg' mkdir -p './groff/site-font' @@ -673,39 +679,192 @@ maybe chmod 0644 'exports' maybe chmod 0755 'exports.d' maybe chmod 0755 'fail2ban' maybe chmod 0755 'fail2ban/action.d' +maybe chmod 0644 'fail2ban/action.d/abuseipdb.conf' +maybe chmod 0644 'fail2ban/action.d/apf.conf' +maybe chmod 0644 'fail2ban/action.d/badips.conf' +maybe chmod 0644 'fail2ban/action.d/badips.py' maybe chmod 0644 'fail2ban/action.d/badips.py.rpmnew' maybe chmod 0644 'fail2ban/action.d/badips.py.rpmsave' +maybe chmod 0644 'fail2ban/action.d/blocklist_de.conf' +maybe chmod 0644 'fail2ban/action.d/cloudflare.conf' +maybe chmod 0644 'fail2ban/action.d/dshield.conf' +maybe chmod 0644 'fail2ban/action.d/dummy.conf' +maybe chmod 0644 'fail2ban/action.d/firewallcmd-allports.conf' +maybe chmod 0644 'fail2ban/action.d/firewallcmd-common.conf' +maybe chmod 0644 'fail2ban/action.d/firewallcmd-ipset.conf' +maybe chmod 0644 'fail2ban/action.d/firewallcmd-multiport.conf' +maybe chmod 0644 'fail2ban/action.d/firewallcmd-new.conf' +maybe chmod 0644 'fail2ban/action.d/firewallcmd-rich-logging.conf' +maybe chmod 0644 'fail2ban/action.d/firewallcmd-rich-rules.conf' +maybe chmod 0644 'fail2ban/action.d/helpers-common.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-allports.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-common.conf' maybe chmod 0644 'fail2ban/action.d/iptables-common.conf.rpmsave' +maybe chmod 0644 'fail2ban/action.d/iptables-ipset-proto4.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-ipset-proto6-allports.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-ipset-proto6.conf' maybe chmod 0640 'fail2ban/action.d/iptables-ipset.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-multiport-log.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-multiport.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-new.conf' +maybe chmod 0644 'fail2ban/action.d/iptables-xt_recent-echo.conf' +maybe chmod 0644 'fail2ban/action.d/iptables.conf' +maybe chmod 0644 'fail2ban/action.d/mail-whois-common.conf' maybe chmod 0644 'fail2ban/action.d/mail.conf.rpmsave' +maybe chmod 0644 'fail2ban/action.d/mynetwatchman.conf' +maybe chmod 0644 'fail2ban/action.d/netscaler.conf' +maybe chmod 0644 'fail2ban/action.d/nftables-allports.conf' +maybe chmod 0644 'fail2ban/action.d/nftables-multiport.conf' +maybe chmod 0644 'fail2ban/action.d/nftables.conf' +maybe chmod 0644 'fail2ban/action.d/nginx-block-map.conf' +maybe chmod 0644 'fail2ban/action.d/npf.conf' +maybe chmod 0644 'fail2ban/action.d/nsupdate.conf' +maybe chmod 0644 'fail2ban/action.d/route.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-buffered.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-common.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-geoip-lines.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-whois-ipjailmatches.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-whois-ipmatches.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-whois-lines.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-whois-matches.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail-whois.conf' +maybe chmod 0644 'fail2ban/action.d/sendmail.conf' +maybe chmod 0644 'fail2ban/action.d/shorewall-ipset-proto6.conf' +maybe chmod 0644 'fail2ban/action.d/smtp.py' maybe chmod 0644 'fail2ban/action.d/smtp.py.rpmnew' maybe chmod 0644 'fail2ban/action.d/smtp.py.rpmsave' +maybe chmod 0644 'fail2ban/action.d/symbiosis-blacklist-allports.conf' +maybe chmod 0644 'fail2ban/action.d/xarf-login-attack.conf' +maybe chmod 0644 'fail2ban/fail2ban.conf' maybe chmod 0644 'fail2ban/fail2ban.conf.rpmsave' +maybe chmod 0755 'fail2ban/fail2ban.d' maybe chmod 0755 'fail2ban/filter.d' +maybe chmod 0644 'fail2ban/filter.d/3proxy.conf' maybe chmod 0640 'fail2ban/filter.d/a.txt' +maybe chmod 0644 'fail2ban/filter.d/apache-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-badbots.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-botsearch.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-common.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-fakegooglebot.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-modsecurity.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-nohome.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-noscript.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-overflows.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-pass.conf' +maybe chmod 0644 'fail2ban/filter.d/apache-shellshock.conf' +maybe chmod 0644 'fail2ban/filter.d/assp.conf' +maybe chmod 0644 'fail2ban/filter.d/asterisk.conf' +maybe chmod 0644 'fail2ban/filter.d/bitwarden.conf' +maybe chmod 0644 'fail2ban/filter.d/botsearch-common.conf' +maybe chmod 0644 'fail2ban/filter.d/centreon.conf' +maybe chmod 0644 'fail2ban/filter.d/common.conf' +maybe chmod 0644 'fail2ban/filter.d/counter-strike.conf' +maybe chmod 0644 'fail2ban/filter.d/courier-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/courier-smtp.conf' +maybe chmod 0644 'fail2ban/filter.d/cyrus-imap.conf' +maybe chmod 0644 'fail2ban/filter.d/directadmin.conf' +maybe chmod 0644 'fail2ban/filter.d/domino-smtp.conf' +maybe chmod 0644 'fail2ban/filter.d/dovecot.conf' maybe chmod 0644 'fail2ban/filter.d/dovecot.conf.rpmnew' maybe chmod 0644 'fail2ban/filter.d/dovecot.conf.rpmsave' +maybe chmod 0644 'fail2ban/filter.d/dropbear.conf' +maybe chmod 0644 'fail2ban/filter.d/drupal-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/ejabberd-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/exim-common.conf' +maybe chmod 0644 'fail2ban/filter.d/exim-spam.conf' +maybe chmod 0644 'fail2ban/filter.d/exim.conf' +maybe chmod 0644 'fail2ban/filter.d/freeswitch.conf' +maybe chmod 0644 'fail2ban/filter.d/froxlor-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/gitlab.conf' +maybe chmod 0644 'fail2ban/filter.d/grafana.conf' +maybe chmod 0644 'fail2ban/filter.d/groupoffice.conf' +maybe chmod 0644 'fail2ban/filter.d/gssftpd.conf' +maybe chmod 0644 'fail2ban/filter.d/guacamole.conf' +maybe chmod 0644 'fail2ban/filter.d/haproxy-http-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/horde.conf' maybe chmod 0755 'fail2ban/filter.d/ignorecommands' +maybe chmod 0755 'fail2ban/filter.d/ignorecommands/apache-fakegooglebot' maybe chmod 0755 'fail2ban/filter.d/ignorecommands/apache-fakegooglebot.rpmsave' +maybe chmod 0644 'fail2ban/filter.d/kerio.conf' +maybe chmod 0644 'fail2ban/filter.d/lighttpd-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/mongodb-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/monit.conf' +maybe chmod 0644 'fail2ban/filter.d/murmur.conf' +maybe chmod 0644 'fail2ban/filter.d/mysqld-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/nagios.conf' +maybe chmod 0644 'fail2ban/filter.d/named-refused.conf' maybe chmod 0644 'fail2ban/filter.d/named-refused.conf.rpmnew' maybe chmod 0644 'fail2ban/filter.d/named-refused.conf.rpmsave' +maybe chmod 0644 'fail2ban/filter.d/nginx-botsearch.conf' maybe chmod 0644 'fail2ban/filter.d/nginx-botsearch.conf.rpmsave' maybe chmod 0640 'fail2ban/filter.d/nginx-forbidden.conf' +maybe chmod 0644 'fail2ban/filter.d/nginx-http-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/nginx-limit-req.conf' +maybe chmod 0644 'fail2ban/filter.d/nsd.conf' +maybe chmod 0644 'fail2ban/filter.d/openhab.conf' +maybe chmod 0644 'fail2ban/filter.d/openwebmail.conf' +maybe chmod 0644 'fail2ban/filter.d/oracleims.conf' +maybe chmod 0644 'fail2ban/filter.d/pam-generic.conf' +maybe chmod 0644 'fail2ban/filter.d/perdition.conf' +maybe chmod 0644 'fail2ban/filter.d/php-url-fopen.conf' +maybe chmod 0644 'fail2ban/filter.d/phpmyadmin-syslog.conf' +maybe chmod 0644 'fail2ban/filter.d/portsentry.conf' maybe chmod 0640 'fail2ban/filter.d/postfix-auth.conf' maybe chmod 0640 'fail2ban/filter.d/postfix-rbl.conf' maybe chmod 0644 'fail2ban/filter.d/postfix-sasl.conf' maybe chmod 0640 'fail2ban/filter.d/postfix-smtp-reject.conf' maybe chmod 0640 'fail2ban/filter.d/postfix-ssl-error.conf' +maybe chmod 0644 'fail2ban/filter.d/postfix.conf' +maybe chmod 0644 'fail2ban/filter.d/proftpd.conf' +maybe chmod 0644 'fail2ban/filter.d/pure-ftpd.conf' +maybe chmod 0644 'fail2ban/filter.d/qmail.conf' +maybe chmod 0644 'fail2ban/filter.d/recidive.conf' maybe chmod 0644 'fail2ban/filter.d/recidive.conf.rpmsave' +maybe chmod 0644 'fail2ban/filter.d/roundcube-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/screensharingd.conf' +maybe chmod 0644 'fail2ban/filter.d/selinux-common.conf' +maybe chmod 0644 'fail2ban/filter.d/selinux-ssh.conf' +maybe chmod 0644 'fail2ban/filter.d/sendmail-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/sendmail-reject.conf' +maybe chmod 0644 'fail2ban/filter.d/sieve.conf' +maybe chmod 0644 'fail2ban/filter.d/slapd.conf' +maybe chmod 0644 'fail2ban/filter.d/softethervpn.conf' +maybe chmod 0644 'fail2ban/filter.d/sogo-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/solid-pop3d.conf' +maybe chmod 0644 'fail2ban/filter.d/squid.conf' +maybe chmod 0644 'fail2ban/filter.d/squirrelmail.conf' +maybe chmod 0644 'fail2ban/filter.d/sshd.conf' maybe chmod 0644 'fail2ban/filter.d/sshd.conf.rpmnew' maybe chmod 0644 'fail2ban/filter.d/sshd.conf.rpmsave' +maybe chmod 0644 'fail2ban/filter.d/stunnel.conf' +maybe chmod 0644 'fail2ban/filter.d/suhosin.conf' +maybe chmod 0644 'fail2ban/filter.d/tine20.conf' +maybe chmod 0644 'fail2ban/filter.d/traefik-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/uwimap-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/vsftpd.conf' +maybe chmod 0644 'fail2ban/filter.d/webmin-auth.conf' +maybe chmod 0644 'fail2ban/filter.d/wuftpd.conf' +maybe chmod 0644 'fail2ban/filter.d/xinetd-fail.conf' +maybe chmod 0644 'fail2ban/filter.d/znc-adminlog.conf' +maybe chmod 0644 'fail2ban/filter.d/zoneminder.conf' +maybe chmod 0644 'fail2ban/jail.conf' maybe chmod 0644 'fail2ban/jail.conf.rpmsave' maybe chmod 0755 'fail2ban/jail.d' +maybe chmod 0644 'fail2ban/jail.d/00-firewalld.conf' maybe chmod 0640 'fail2ban/jail.d/default.conf' maybe chmod 0644 'fail2ban/jail.d/recidive.conf' maybe chmod 0640 'fail2ban/jail.local' +maybe chmod 0644 'fail2ban/paths-common.conf' +maybe chmod 0644 'fail2ban/paths-fedora.conf' maybe chmod 0644 'filesystems' maybe chmod 0750 'firewalld' +maybe chmod 0644 'firewalld/firewalld.conf' +maybe chmod 0750 'firewalld/helpers' +maybe chmod 0750 'firewalld/icmptypes' +maybe chmod 0750 'firewalld/ipsets' +maybe chmod 0644 'firewalld/lockdown-whitelist.xml' +maybe chmod 0750 'firewalld/policies' +maybe chmod 0750 'firewalld/services' maybe chmod 0750 'firewalld/zones' maybe chmod 0644 'firewalld/zones/public.xml' maybe chmod 0755 'fonts' @@ -2541,7 +2700,9 @@ maybe chmod 0644 'logrotate.d/btmp' maybe chmod 0644 'logrotate.d/chrony' maybe chmod 0644 'logrotate.d/clamav-unofficial-sigs' maybe chmod 0644 'logrotate.d/dnf' +maybe chmod 0644 'logrotate.d/fail2ban' maybe chmod 0644 'logrotate.d/fail2ban.rpmsave' +maybe chmod 0644 'logrotate.d/firewalld' maybe chmod 0644 'logrotate.d/httpd' maybe chmod 0644 'logrotate.d/iptraf-ng' maybe chmod 0644 'logrotate.d/kvm_stat' @@ -3316,6 +3477,7 @@ maybe chmod 0644 'mock/templates/rocky-8.tpl' maybe chmod 0755 'modprobe.d' maybe chmod 0644 'modprobe.d/blacklist-firewire.conf' maybe chmod 0640 'modprobe.d/cramfs.conf' +maybe chmod 0644 'modprobe.d/firewalld-sysctls.conf' maybe chmod 0644 'modprobe.d/lockd.conf' maybe chmod 0644 'modprobe.d/mlx4.conf' maybe chmod 0644 'modprobe.d/nodccp.conf' @@ -3362,6 +3524,12 @@ maybe chmod 0755 'newrelic-infra/logging.d' maybe chmod 0644 'newrelic-infra/logging.d/postfix.yml' maybe chmod 0644 'nfs.conf' maybe chmod 0644 'nfsmount.conf' +maybe chmod 0700 'nftables' +maybe chmod 0600 'nftables/main.nft' +maybe chmod 0600 'nftables/nat.nft' +maybe chmod 0700 'nftables/osf' +maybe chmod 0600 'nftables/osf/pf.os' +maybe chmod 0600 'nftables/router.nft' maybe chmod 0755 'nginx' maybe chown 'nginx' 'nginx/.anaf' maybe chgrp 'nginx' 'nginx/.anaf' @@ -4963,6 +5131,8 @@ maybe chmod 0644 'sysconfig/chronyd' maybe chmod 0755 'sysconfig/console' maybe chmod 0644 'sysconfig/cpupower' maybe chmod 0644 'sysconfig/crond' +maybe chmod 0600 'sysconfig/ebtables-config' +maybe chmod 0644 'sysconfig/firewalld' maybe chmod 0644 'sysconfig/firstboot' maybe chmod 0644 'sysconfig/garb' maybe chmod 0644 'sysconfig/htcacheclean' @@ -5011,6 +5181,7 @@ maybe chmod 0755 'sysconfig/network-scripts/init.ipv6-global' maybe chmod 0644 'sysconfig/network-scripts/network-functions' maybe chmod 0644 'sysconfig/network-scripts/network-functions-ipv6' maybe chmod 0644 'sysconfig/network-scripts/route-eth0' +maybe chmod 0600 'sysconfig/nftables.conf' maybe chmod 0644 'sysconfig/node_exporter' maybe chmod 0644 'sysconfig/nrpe' maybe chmod 0644 'sysconfig/opendkim' diff --git a/fail2ban/action.d/abuseipdb.conf b/fail2ban/action.d/abuseipdb.conf new file mode 100644 index 0000000..ed958c8 --- /dev/null +++ b/fail2ban/action.d/abuseipdb.conf @@ -0,0 +1,104 @@ +# Fail2ban configuration file +# +# Action to report IP address to abuseipdb.com +# You must sign up to obtain an API key from abuseipdb.com. +# +# NOTE: These reports may include sensitive Info. +# If you want cleaner reports that ensure no user data see the helper script at the below website. +# +# IMPORTANT: +# +# Reporting an IP of abuse is a serious complaint. Make sure that it is +# serious. Fail2ban developers and network owners recommend you only use this +# action for: +# * The recidive where the IP has been banned multiple times +# * Where maxretry has been set quite high, beyond the normal user typing +# password incorrectly. +# * For filters that have a low likelihood of receiving human errors +# +# This action relies on a api_key being added to the above action conf, +# and the appropriate categories set. +# +# Example, for ssh bruteforce (in section [sshd] of `jail.local`): +# action = %(known/action)s +# abuseipdb[abuseipdb_apikey="my-api-key", abuseipdb_category="18,22"] +# +# See below for categories. +# +# Added to fail2ban by Andrew James Collett (ajcollett) + +## abuseIPDB Categories, `the abuseipdb_category` MUST be set in the jail.conf action call. +# Example, for ssh bruteforce: action = %(action_abuseipdb)s[abuseipdb_category="18,22"] +# ID Title Description +# 3 Fraud Orders +# 4 DDoS Attack +# 9 Open Proxy +# 10 Web Spam +# 11 Email Spam +# 14 Port Scan +# 18 Brute-Force +# 19 Bad Web Bot +# 20 Exploited Host +# 21 Web App Attack +# 22 SSH Secure Shell (SSH) abuse. Use this category in combination with more specific categories. +# 23 IoT Targeted +# See https://abuseipdb.com/categories for more descriptions + +[Definition] + +# bypass action for restored tickets +norestored = 1 + +# Option: actionstart +# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false). +# Values: CMD +# +actionstart = + +# Option: actionstop +# Notes.: command executed at the stop of jail (or 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. +# +# ** IMPORTANT! ** +# +# By default, this posts directly to AbuseIPDB's API, unfortunately +# this results in a lot of backslashes/escapes appearing in the +# reports. This also may include info like your hostname. +# If you have your own web server with PHP available, you can +# use my (Shaun's) helper PHP script by commenting out the first #actionban +# line below, uncommenting the second one, and pointing the URL at +# wherever you install the helper script. For the PHP helper script, see +# +# +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionban = lgm=$(printf '%%.1000s\n...' ""); curl -sSf "https://api.abuseipdb.com/api/v2/report" -H "Accept: application/json" -H "Key: " --data-urlencode "comment=$lgm" --data-urlencode "ip=" --data "categories=" + +# 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] +# Option: abuseipdb_apikey +# Notes Your API key from abuseipdb.com +# Values: STRING Default: None +# Register for abuseipdb [https://www.abuseipdb.com], get api key and set below. +# You will need to set the category in the action call. +abuseipdb_apikey = diff --git a/fail2ban/action.d/apf.conf b/fail2ban/action.d/apf.conf new file mode 100644 index 0000000..5c4a261 --- /dev/null +++ b/fail2ban/action.d/apf.conf @@ -0,0 +1,25 @@ +# Fail2Ban configuration file +# https://www.rfxn.com/projects/advanced-policy-firewall/ +# +# Note: APF doesn't play nicely with other actions. It has been observed to +# remove bans created by other iptables based actions. If you are going to use +# this action, use it for all of your jails. +# +# DON'T MIX APF and other IPTABLES based actions +[Definition] + +actionstart = +actionstop = +actioncheck = +actionban = apf --deny "banned by Fail2Ban " +actionunban = apf --remove + +[Init] + +# Name used in APF configuration +# +name = default + +# DEV NOTES: +# +# Author: Mark McKinstry diff --git a/fail2ban/action.d/badips.conf b/fail2ban/action.d/badips.conf new file mode 100644 index 0000000..6f9513f --- /dev/null +++ b/fail2ban/action.d/badips.conf @@ -0,0 +1,19 @@ +# Fail2ban reporting to badips.com +# +# Note: This reports an IP only and does not actually ban traffic. Use +# another action in the same jail if you want bans to occur. +# +# Set the category to the appropriate value before use. +# +# To get see register and optional key to get personalised graphs see: +# http://www.badips.com/blog/personalized-statistics-track-the-attackers-of-all-your-servers-with-one-key + +[Definition] + +actionban = curl --fail --user-agent "" http://www.badips.com/add// + +[Init] + +# Option: category +# Notes.: Values are from the list here: http://www.badips.com/get/categories +category = diff --git a/fail2ban/action.d/badips.py b/fail2ban/action.d/badips.py new file mode 100644 index 0000000..d57b4e3 --- /dev/null +++ b/fail2ban/action.d/badips.py @@ -0,0 +1,392 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- +# vi: set ft=python sts=4 ts=4 sw=4 noet : + +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import sys +if sys.version_info < (2, 7): # pragma: no cover + raise ImportError("badips.py action requires Python >= 2.7") +import json +import threading +import logging +if sys.version_info >= (3, ): # pragma: 2.x no cover + from urllib.request import Request, urlopen + from urllib.parse import urlencode + from urllib.error import HTTPError +else: # pragma: 3.x no cover + from urllib.request import Request, urlopen + from urllib.error import HTTPError + from urllib.parse import urlencode + +from fail2ban.server.actions import Actions, ActionBase, BanTicket +from fail2ban.helpers import splitwords, str2LogLevel + + + +class BadIPsAction(ActionBase): # pragma: no cover - may be unavailable + """Fail2Ban action which reports bans to badips.com, and also + blacklist bad IPs listed on badips.com by using another action's + ban method. + + Parameters + ---------- + jail : Jail + The jail which the action belongs to. + name : str + Name assigned to the action. + category : str + Valid badips.com category for reporting failures. + score : int, optional + Minimum score for bad IPs. Default 3. + age : str, optional + Age of last report for bad IPs, per badips.com syntax. + Default "24h" (24 hours) + banaction : str, optional + Name of banaction to use for blacklisting bad IPs. If `None`, + no blacklist of IPs will take place. + Default `None`. + bancategory : str, optional + Name of category to use for blacklisting, which can differ + from category used for reporting. e.g. may want to report + "postfix", but want to use whole "mail" category for blacklist. + Default `category`. + bankey : str, optional + Key issued by badips.com to retrieve personal list + of blacklist IPs. + updateperiod : int, optional + Time in seconds between updating bad IPs blacklist. + Default 900 (15 minutes) + loglevel : int/str, optional + Log level of the message when an IP is (un)banned. + Default `DEBUG`. + Can be also supplied as two-value list (comma- or space separated) to + provide level of the summary message when a group of IPs is (un)banned. + Example `DEBUG,INFO`. + agent : str, optional + User agent transmitted to server. + Default `Fail2Ban/ver.` + + Raises + ------ + ValueError + If invalid `category`, `score`, `banaction` or `updateperiod`. + """ + + TIMEOUT = 10 + _badips = "https://www.badips.com" + def _Request(self, url, **argv): + return Request(url, headers={'User-Agent': self.agent}, **argv) + + def __init__(self, jail, name, category, score=3, age="24h", + banaction=None, bancategory=None, bankey=None, updateperiod=900, + loglevel='DEBUG', agent="Fail2Ban", timeout=TIMEOUT): + super(BadIPsAction, self).__init__(jail, name) + + self.timeout = timeout + self.agent = agent + self.category = category + self.score = score + self.age = age + self.banaction = banaction + self.bancategory = bancategory or category + self.bankey = bankey + loglevel = splitwords(loglevel) + self.sumloglevel = str2LogLevel(loglevel[-1]) + self.loglevel = str2LogLevel(loglevel[0]) + self.updateperiod = updateperiod + + self._bannedips = set() + # Used later for threading.Timer for updating badips + self._timer = None + + @staticmethod + def isAvailable(timeout=1): + try: + response = urlopen(Request("/".join([BadIPsAction._badips]), + headers={'User-Agent': "Fail2Ban"}), timeout=timeout) + return True, '' + except Exception as e: # pragma: no cover + return False, e + + def logError(self, response, what=''): # pragma: no cover - sporadical (502: Bad Gateway, etc) + messages = {} + try: + messages = json.loads(response.read().decode('utf-8')) + except: + pass + self._logSys.error( + "%s. badips.com response: '%s'", what, + messages.get('err', 'Unknown')) + + def getCategories(self, incParents=False): + """Get badips.com categories. + + Returns + ------- + set + Set of categories. + + Raises + ------ + HTTPError + Any issues with badips.com request. + ValueError + If badips.com response didn't contain necessary information + """ + try: + response = urlopen( + self._Request("/".join([self._badips, "get", "categories"])), timeout=self.timeout) + except HTTPError as response: # pragma: no cover + self.logError(response, "Failed to fetch categories") + raise + else: + response_json = json.loads(response.read().decode('utf-8')) + if not 'categories' in response_json: + err = "badips.com response lacked categories specification. Response was: %s" \ + % (response_json,) + self._logSys.error(err) + raise ValueError(err) + categories = response_json['categories'] + categories_names = set( + value['Name'] for value in categories) + if incParents: + categories_names.update(set( + value['Parent'] for value in categories + if "Parent" in value)) + return categories_names + + def getList(self, category, score, age, key=None): + """Get badips.com list of bad IPs. + + Parameters + ---------- + category : str + Valid badips.com category. + score : int + Minimum score for bad IPs. + age : str + Age of last report for bad IPs, per badips.com syntax. + key : str, optional + Key issued by badips.com to fetch IPs reported with the + associated key. + + Returns + ------- + set + Set of bad IPs. + + Raises + ------ + HTTPError + Any issues with badips.com request. + """ + try: + url = "?".join([ + "/".join([self._badips, "get", "list", category, str(score)]), + urlencode({'age': age})]) + if key: + url = "&".join([url, urlencode({'key': key})]) + self._logSys.debug('badips.com: get list, url: %r', url) + response = urlopen(self._Request(url), timeout=self.timeout) + except HTTPError as response: # pragma: no cover + self.logError(response, "Failed to fetch bad IP list") + raise + else: + return set(response.read().decode('utf-8').split()) + + @property + def category(self): + """badips.com category for reporting IPs. + """ + return self._category + + @category.setter + def category(self, category): + if category not in self.getCategories(): + self._logSys.error("Category name '%s' not valid. " + "see badips.com for list of valid categories", + category) + raise ValueError("Invalid category: %s" % category) + self._category = category + + @property + def bancategory(self): + """badips.com bancategory for fetching IPs. + """ + return self._bancategory + + @bancategory.setter + def bancategory(self, bancategory): + if bancategory != "any" and bancategory not in self.getCategories(incParents=True): + self._logSys.error("Category name '%s' not valid. " + "see badips.com for list of valid categories", + bancategory) + raise ValueError("Invalid bancategory: %s" % bancategory) + self._bancategory = bancategory + + @property + def score(self): + """badips.com minimum score for fetching IPs. + """ + return self._score + + @score.setter + def score(self, score): + score = int(score) + if 0 <= score <= 5: + self._score = score + else: + raise ValueError("Score must be 0-5") + + @property + def banaction(self): + """Jail action to use for banning/unbanning. + """ + return self._banaction + + @banaction.setter + def banaction(self, banaction): + if banaction is not None and banaction not in self._jail.actions: + self._logSys.error("Action name '%s' not in jail '%s'", + banaction, self._jail.name) + raise ValueError("Invalid banaction") + self._banaction = banaction + + @property + def updateperiod(self): + """Period in seconds between banned bad IPs will be updated. + """ + return self._updateperiod + + @updateperiod.setter + def updateperiod(self, updateperiod): + updateperiod = int(updateperiod) + if updateperiod > 0: + self._updateperiod = updateperiod + else: + raise ValueError("Update period must be integer greater than 0") + + def _banIPs(self, ips): + for ip in ips: + try: + ai = Actions.ActionInfo(BanTicket(ip), self._jail) + self._jail.actions[self.banaction].ban(ai) + except Exception as e: + self._logSys.error( + "Error banning IP %s for jail '%s' with action '%s': %s", + ip, self._jail.name, self.banaction, e, + exc_info=self._logSys.getEffectiveLevel()<=logging.DEBUG) + else: + self._bannedips.add(ip) + self._logSys.log(self.loglevel, + "Banned IP %s for jail '%s' with action '%s'", + ip, self._jail.name, self.banaction) + + def _unbanIPs(self, ips): + for ip in ips: + try: + ai = Actions.ActionInfo(BanTicket(ip), self._jail) + self._jail.actions[self.banaction].unban(ai) + except Exception as e: + self._logSys.error( + "Error unbanning IP %s for jail '%s' with action '%s': %s", + ip, self._jail.name, self.banaction, e, + exc_info=self._logSys.getEffectiveLevel()<=logging.DEBUG) + else: + self._logSys.log(self.loglevel, + "Unbanned IP %s for jail '%s' with action '%s'", + ip, self._jail.name, self.banaction) + finally: + self._bannedips.remove(ip) + + def start(self): + """If `banaction` set, blacklists bad IPs. + """ + if self.banaction is not None: + self.update() + + def update(self): + """If `banaction` set, updates blacklisted IPs. + + Queries badips.com for list of bad IPs, removing IPs from the + blacklist if no longer present, and adds new bad IPs to the + blacklist. + """ + if self.banaction is not None: + if self._timer: + self._timer.cancel() + self._timer = None + + try: + ips = self.getList( + self.bancategory, self.score, self.age, self.bankey) + # Remove old IPs no longer listed + s = self._bannedips - ips + m = len(s) + self._unbanIPs(s) + # Add new IPs which are now listed + s = ips - self._bannedips + p = len(s) + self._banIPs(s) + if m != 0 or p != 0: + self._logSys.log(self.sumloglevel, + "Updated IPs for jail '%s' (-%d/+%d)", + self._jail.name, m, p) + self._logSys.debug( + "Next update for jail '%' in %i seconds", + self._jail.name, self.updateperiod) + finally: + self._timer = threading.Timer(self.updateperiod, self.update) + self._timer.start() + + def stop(self): + """If `banaction` set, clears blacklisted IPs. + """ + if self.banaction is not None: + if self._timer: + self._timer.cancel() + self._timer = None + self._unbanIPs(self._bannedips.copy()) + + def ban(self, aInfo): + """Reports banned IP to badips.com. + + Parameters + ---------- + aInfo : dict + Dictionary which includes information in relation to + the ban. + + Raises + ------ + HTTPError + Any issues with badips.com request. + """ + try: + url = "/".join([self._badips, "add", self.category, str(aInfo['ip'])]) + self._logSys.debug('badips.com: ban, url: %r', url) + response = urlopen(self._Request(url), timeout=self.timeout) + except HTTPError as response: # pragma: no cover + self.logError(response, "Failed to ban") + raise + else: + messages = json.loads(response.read().decode('utf-8')) + self._logSys.debug( + "Response from badips.com report: '%s'", + messages['suc']) + +Action = BadIPsAction diff --git a/fail2ban/action.d/blocklist_de.conf b/fail2ban/action.d/blocklist_de.conf new file mode 100644 index 0000000..ba6d427 --- /dev/null +++ b/fail2ban/action.d/blocklist_de.conf @@ -0,0 +1,84 @@ +# Fail2Ban configuration file +# +# Author: Steven Hiscocks +# +# + +# Action to report IP address to blocklist.de +# Blocklist.de must be signed up to at www.blocklist.de +# Once registered, one or more servers can be added. +# This action requires the server 'email address' and the associated apikey. +# +# From blocklist.de: +# www.blocklist.de is a free and voluntary service provided by a +# Fraud/Abuse-specialist, whose servers are often attacked on SSH-, +# Mail-Login-, FTP-, Webserver- and other services. +# The mission is to report all attacks to the abuse departments of the +# infected PCs/servers to ensure that the responsible provider can inform +# the customer about the infection and disable them +# +# IMPORTANT: +# +# Reporting an IP of abuse is a serious complaint. Make sure that it is +# serious. Fail2ban developers and network owners recommend you only use this +# action for: +# * The recidive where the IP has been banned multiple times +# * Where maxretry has been set quite high, beyond the normal user typing +# password incorrectly. +# * For filters that have a low likelihood of receiving human errors +# + +[Definition] + +# Option: actionstart +# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false). +# Values: CMD +# +actionstart = + +# Option: actionstop +# Notes.: command executed at the stop of jail (or 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 = curl --fail --data-urlencode "server=" --data "apikey=" --data "service=" --data "ip=" --data-urlencode "logs=
" --data 'format=text' --user-agent "" "https://www.blocklist.de/en/httpreports.html" + +# 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 = + +# Option: email +# Notes server email address, as per blocklist.de account +# Values: STRING Default: None +# +#email = + +# Option: apikey +# Notes your user blocklist.de user account apikey +# Values: STRING Default: None +# +#apikey = + +# Option: service +# Notes service name you are reporting on, typically aligns with filter name +# see http://www.blocklist.de/en/httpreports.html for full list +# Values: STRING Default: None +# +#service = diff --git a/fail2ban/action.d/cloudflare.conf b/fail2ban/action.d/cloudflare.conf new file mode 100644 index 0000000..361cb17 --- /dev/null +++ b/fail2ban/action.d/cloudflare.conf @@ -0,0 +1,83 @@ +# +# Author: Mike Rushton +# +# IMPORTANT +# +# Please set jail.local's permission to 640 because it contains your CF API key. +# +# This action depends on curl (and optionally jq). +# Referenced from http://www.normyee.net/blog/2012/02/02/adding-cloudflare-support-to-fail2ban by NORM YEE +# +# To get your CloudFlare API Key: https://www.cloudflare.com/a/account/my-account +# +# CloudFlare API error codes: https://www.cloudflare.com/docs/host-api.html#s4.2 + +[Definition] + +# Option: actionstart +# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false). +# Values: CMD +# +actionstart = + +# Option: actionstop +# Notes.: command executed at the stop of jail (or 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: IP address +# number of failures +#