diff --git a/config/action.d/badips.conf b/config/action.d/badips.conf index 4a5c0f97..70b46546 100644 --- a/config/action.d/badips.conf +++ b/config/action.d/badips.conf @@ -10,7 +10,7 @@ [Definition] -actionban = curl --fail --user-agent "fail2ban v0.8.12" http://www.badips.com/add// +actionban = curl --fail --user-agent "" http://www.badips.com/add// [Init] diff --git a/config/action.d/blocklist_de.conf b/config/action.d/blocklist_de.conf index 6d520694..2f31d8b9 100644 --- a/config/action.d/blocklist_de.conf +++ b/config/action.d/blocklist_de.conf @@ -54,7 +54,7 @@ actioncheck = # 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 "fail2ban v0.8.12" "https://www.blocklist.de/en/httpreports.html" +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 diff --git a/config/action.d/mynetwatchman.conf b/config/action.d/mynetwatchman.conf index 5245a4e3..8f3edf9e 100644 --- a/config/action.d/mynetwatchman.conf +++ b/config/action.d/mynetwatchman.conf @@ -111,13 +111,17 @@ myip = `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0- # protocol = tcp +# Option: agent +# Default: Fail2ban +agent = Fail2ban + # Option: getcmd # Notes.: A command to fetch a URL. Should output page to STDOUT # Values: CMD Default: wget # -getcmd = wget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document=- --user-agent=Fail2Ban +getcmd = wget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document=- --user-agent= # Alternative value: -# getcmd = curl --silent --show-error --retry 3 --connect-timeout 10 --max-time 60 --user-agent Fail2Ban +# getcmd = curl --silent --show-error --retry 3 --connect-timeout 10 --max-time 60 --user-agent # Option: srcport # Notes.: The source port of the attack. You're unlikely to have this info, so diff --git a/config/jail.conf b/config/jail.conf index 02543705..1d560288 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -146,6 +146,9 @@ chain = INPUT # Usually should be overridden in a particular jail port = 0:65535 +# Format of user-agent https://tools.ietf.org/html/rfc7231#section-5.5.3 +fail2ban_agent = Fail2Ban/%(fail2ban_version)s + # # Action shortcuts. To be used to define action parameter @@ -187,7 +190,7 @@ action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"] # [Init] # blocklist_de_apikey = {api key from registration] # -action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s"] +action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"] # Report ban via badips.com, and use as blacklist # @@ -197,7 +200,11 @@ action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apik # NOTE: This action relies on banaction being present on start and therefore # should be last action defined for a jail. # -action_badips = badips.py[category="%(name)s", banaction="%(banaction)s"] +action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"] +# +# Report ban via badips.com (uses action.d/badips.conf for reporting only) +# +action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)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 diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 54ac59fa..56b8889c 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -32,6 +32,7 @@ import re from .configreader import ConfigReaderUnshared, ConfigReader from .filterreader import FilterReader from .actionreader import ActionReader +from ..version import version from ..helpers import getLogger from ..helpers import splitcommaspace @@ -108,6 +109,10 @@ class JailReader(ConfigReader): ["string", "filter", ""], ["string", "action", ""]] + # Before interpolation (substitution) add static options always available as default: + defsec = self._cfg.get_defaults() + defsec["fail2ban_version"] = version + # Read first options only needed for merge defaults ('known/...' from filter): self.__opts = ConfigReader.getOptions(self, self.__name, opts1st) if not self.__opts: diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index d19090be..fcabc727 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -28,18 +28,20 @@ import re import shutil import tempfile import unittest -from ..client.configreader import ConfigReaderUnshared +from ..client.configreader import ConfigReader, ConfigReaderUnshared from ..client import configparserinc from ..client.jailreader import JailReader from ..client.filterreader import FilterReader from ..client.jailsreader import JailsReader from ..client.actionreader import ActionReader from ..client.configurator import Configurator +from ..version import version from .utils import LogCaptureTestCase TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") from .utils import CONFIG_DIR +CONFIG_DIR_TESTSHARE_CFG = {} STOCK = os.path.exists(os.path.join('config','fail2ban.conf')) @@ -251,6 +253,34 @@ class JailReaderTest(LogCaptureTestCase): result = JailReader.extractOptions(option) self.assertEqual(expected, result) + def testVersionAgent(self): + jail = JailReader('blocklisttest', force_enable=True, basedir=CONFIG_DIR) + # emulate jail.read(), because such jail not exists: + ConfigReader.read(jail, "jail"); + sections = jail._cfg.get_sections() + sections['blocklisttest'] = dict((('__name__', 'blocklisttest'), + ('filter', ''), ('failregex', '^test $'), + ('sender', 'f2b-test@example.com'), ('blocklist_de_apikey', 'test-key'), + ('action', + '%(action_blocklist_de)s\n' + '%(action_badips_report)s\n' + '%(action_badips)s\n' + 'mynetwatchman[port=1234,protocol=udp,agent="%(fail2ban_agent)s"]' + ), + )) + # get options: + self.assertTrue(jail.getOptions()) + # convert and get stream + stream = jail.convert() + # get action and retrieve agent from it, compare with agent saved in version: + act = [o for o in stream if len(o) > 4 and (o[4] == 'agent' or o[4].endswith('badips.py'))] + useragent = 'Fail2Ban/%s' % version + self.assertEqual(len(act), 4) + self.assertEqual(act[0], ['set', 'blocklisttest', 'action', 'blocklist_de', 'agent', useragent]) + self.assertEqual(act[1], ['set', 'blocklisttest', 'action', 'badips', 'agent', useragent]) + self.assertEqual(eval(act[2][5]).get('agent', ''), useragent) + self.assertEqual(act[3], ['set', 'blocklisttest', 'action', 'mynetwatchman', 'agent', useragent]) + def testGlob(self): d = tempfile.mkdtemp(prefix="f2b-temp") # Generate few files