Repository: fail2ban/fail2ban

Issue:
Fail2ban 0.9.3 crashes on Freebsd 10.1
Running FreeBSD 10.1 with ipfw and fail2ban 0.9.3

after a restart:

2015-09-23 11:07:22,916 fail2ban.server         [71930]: INFO    Stopping all jails
2015-09-23 11:07:23,843 fail2ban.jail           [71930]: INFO    Jail 'ssh-ipfw' stopped
2015-09-23 11:07:23,912 fail2ban.server         [71930]: INFO    Exiting Fail2ban
2015-09-23 11:07:24,265 fail2ban.server         [72055]: INFO    Changed logging target to /var/log/fail2ban.log for Fail2ban v0.9.3
2015-09-23 11:07:24,266 fail2ban.database       [72055]: INFO    Connected to fail2ban persistent database '/var/db/fail2ban/fail2ban.sqlite3'
2015-09-23 11:07:24,308 fail2ban.jail           [72055]: INFO    Creating new jail 'ssh-ipfw'
2015-09-23 11:07:24,312 fail2ban.jail           [72055]: INFO    Jail 'ssh-ipfw' uses poller
2015-09-23 11:07:24,340 fail2ban.filter         [72055]: INFO    Set jail log file encoding to US-ASCII
2015-09-23 11:07:24,340 fail2ban.jail           [72055]: INFO    Initiated 'polling' backend
2015-09-23 11:07:24,452 fail2ban.filter         [72055]: INFO    Added logfile = /var/log/auth.log
2015-09-23 11:07:24,452 fail2ban.filter         [72055]: INFO    Set maxRetry = 3
2015-09-23 11:07:24,458 fail2ban.filter         [72055]: INFO    Set jail log file encoding to US-ASCII
2015-09-23 11:07:24,459 fail2ban.actions        [72055]: INFO    Set banTime = 86400
2015-09-23 11:07:24,460 fail2ban.filter         [72055]: INFO    Set findtime = 300
2015-09-23 11:07:24,525 fail2ban.jail           [72055]: INFO    Jail 'ssh-ipfw' started
2015-09-23 11:07:39,186 fail2ban                [72055]: CRITICAL Unhandled exception in Fail2Ban:
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/jailthread.py", line 66, in run_with_except_hook
    run(_args, *_kwargs)
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/filterpoll.py", line 97, in run
    self.getFailures(filename)
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/filter.py", line 690, in getFailures
    self.processLineAndAdd(line)
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/filter.py", line 432, in processLineAndAdd
    if self.inIgnoreIPList(ip, log_ignore=True):
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/filter.py", line 372, in inIgnoreIPList
    s[1] = long(s[1])
ValueError: invalid literal for long() with base 10: '24,'

If I do a fail2ban-regex test using my authlog and filter.d/ssh.conf I get : 
# Running tests

Use   failregex filter file : sshd, basedir: /usr/local/etc/fail2ban
Use         maxlines : 10
Use         log file : /var/log/auth.log
Use         encoding : US-ASCII

Nothing updates or is displayed. When I break out of it I get :

^CTraceback (most recent call last):
  File "/usr/local/bin/fail2ban-regex", line 589, in <module>
    fail2banRegex.process(test_lines)
  File "/usr/local/bin/fail2ban-regex", line 381, in process
    line_datetimestripped, ret = fail2banRegex.testRegex(line)
  File "/usr/local/bin/fail2ban-regex", line 340, in testRegex
    line, ret = self._filter.processLine(line, date, checkAllRegex=True)
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/filter.py", line 417, in processLine
    tupleLine, date, returnRawHost, checkAllRegex)
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/filter.py", line 497, in findFailure
    failRegex.search(self.__lineBuffer)
  File "/usr/local/lib/python2.7/site-packages/fail2ban/server/failregex.py", line 81, in search
    def search(self, tupleLines):
KeyboardInterrupt



Discussion:
I agree that we might want to make it more robust but it is RTFM

```
$> grep -1 ignoreip config/jail.conf 

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

```

Head... desk

thanks.

On 9/23/2015 11:49 AM, Yaroslav Halchenko wrote:

> I agree that we might want to make it more robust but it is RTFM
> 
> |$> grep -1 ignoreip config/jail.conf # "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 |
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/fail2ban/fail2ban/issues/1197#issuecomment-142645007.


Resolving patch:
diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py
--- a/fail2ban/client/jailreader.py
+++ b/fail2ban/client/jailreader.py
@@ -33,6 +33,7 @@
 from .filterreader import FilterReader
 from .actionreader import ActionReader
 from ..helpers import getLogger
+from ..helpers import splitcommaspace
 
 # Gets the instance of the logger.
 logSys = getLogger(__name__)
@@ -208,10 +209,8 @@ def convert(self, allow_no_files=False):
 			elif opt == "maxretry":
 				stream.append(["set", self.__name, "maxretry", self.__opts[opt]])
 			elif opt == "ignoreip":
-				for ip in self.__opts[opt].split():
-					# Do not send a command if the rule is empty.
-					if ip != '':
-						stream.append(["set", self.__name, "addignoreip", ip])
+				for ip in splitcommaspace(self.__opts[opt]):
+					stream.append(["set", self.__name, "addignoreip", ip])
 			elif opt == "findtime":
 				stream.append(["set", self.__name, "findtime", self.__opts[opt]])
 			elif opt == "bantime":
diff --git a/fail2ban/helpers.py b/fail2ban/helpers.py
--- a/fail2ban/helpers.py
+++ b/fail2ban/helpers.py
@@ -127,3 +127,13 @@ def excepthook(exctype, value, traceback):
 	getLogger("fail2ban").critical(
 		"Unhandled exception in Fail2Ban:", exc_info=True)
 	return sys.__excepthook__(exctype, value, traceback)
+
+def splitcommaspace(s):
+	"""Helper to split on any comma or space
+
+	Returns empty list if input is empty (or None) and filters
+	out empty entries
+	"""
+	if not s:
+		return []
+	return filter(bool, re.split('[ ,]', s))


Test patch:
diff --git a/fail2ban/tests/misctestcase.py b/fail2ban/tests/misctestcase.py
--- a/fail2ban/tests/misctestcase.py
+++ b/fail2ban/tests/misctestcase.py
@@ -33,6 +33,7 @@
 from StringIO import StringIO
 
 from ..helpers import formatExceptionInfo, mbasename, TraceBack, FormatterWithTraceBack, getLogger
+from ..helpers import splitcommaspace
 from ..server.datetemplate import DatePatternRegex
 
 
@@ -55,6 +56,14 @@ def testFormatExceptionConvertArgs(self):
 			# might be fragile due to ' vs "
 			self.assertEqual(args, "('Very bad', None)")
 
+	def testsplitcommaspace(self):
+		self.assertEqual(splitcommaspace(None), [])
+		self.assertEqual(splitcommaspace(''), [])
+		self.assertEqual(splitcommaspace('  '), [])
+		self.assertEqual(splitcommaspace('1'), ['1'])
+		self.assertEqual(splitcommaspace(' 1 2 '), ['1', '2'])
+		self.assertEqual(splitcommaspace(' 1, 2 , '), ['1', '2'])
+
 
 class SetupTest(unittest.TestCase):